(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
	typeof define === 'function' && define.amd ? define(['exports'], factory) :
	(factory((global.echarts = {})));
}(this, (function (exports) { 'use strict';

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// (1) The code `if (__DEV__) ...` can be removed by build tool.
// (2) If intend to use `__DEV__`, this module should be imported. Use a global
// variable `__DEV__` may cause that miss the declaration (see #6535), or the
// declaration is behind of the using position (for example in `Model.extent`,
// And tools like rollup can not analysis the dependency if not import).

var dev;

// In browser
if (typeof window !== 'undefined') {
    dev = window.__DEV__;
}
// In node
else if (typeof global !== 'undefined') {
    dev = global.__DEV__;
}

if (typeof dev === 'undefined') {
    dev = true;
}

var __DEV__ = dev;

/**
 * zrender: 生成唯一id
 *
 * @author errorrik (errorrik@gmail.com)
 */

var idStart = 0x0907;

var guid = function () {
    return idStart++;
};

/**
 * echarts设备环境识别
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author firede[firede@firede.us]
 * @desc thanks zepto.
 */

/* global wx */

var env = {};

if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') {
    // In Weixin Application
    env = {
        browser: {},
        os: {},
        node: false,
        wxa: true, // Weixin Application
        canvasSupported: true,
        svgSupported: false,
        touchEventsSupported: true,
        domSupported: false
    };
}
else if (typeof document === 'undefined' && typeof self !== 'undefined') {
    // In worker
    env = {
        browser: {},
        os: {},
        node: false,
        worker: true,
        canvasSupported: true,
        domSupported: false
    };
}
else if (typeof navigator === 'undefined') {
    // In node
    env = {
        browser: {},
        os: {},
        node: true,
        worker: false,
        // Assume canvas is supported
        canvasSupported: true,
        svgSupported: true,
        domSupported: false
    };
}
else {
    env = detect(navigator.userAgent);
}

var env$1 = env;

// Zepto.js
// (c) 2010-2013 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.

function detect(ua) {
    var os = {};
    var browser = {};
    // var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/);
    // var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
    // var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
    // var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
    // var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
    // var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/);
    // var touchpad = webos && ua.match(/TouchPad/);
    // var kindle = ua.match(/Kindle\/([\d.]+)/);
    // var silk = ua.match(/Silk\/([\d._]+)/);
    // var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/);
    // var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/);
    // var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/);
    // var playbook = ua.match(/PlayBook/);
    // var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/);
    var firefox = ua.match(/Firefox\/([\d.]+)/);
    // var safari = webkit && ua.match(/Mobile\//) && !chrome;
    // var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome;
    var ie = ua.match(/MSIE\s([\d.]+)/)
        // IE 11 Trident/7.0; rv:11.0
        || ua.match(/Trident\/.+?rv:(([\d.]+))/);
    var edge = ua.match(/Edge\/([\d.]+)/); // IE 12 and 12+

    var weChat = (/micromessenger/i).test(ua);

    // Todo: clean this up with a better OS/browser seperation:
    // - discern (more) between multiple browsers on android
    // - decide if kindle fire in silk mode is android or not
    // - Firefox on Android doesn't specify the Android version
    // - possibly devide in os, device and browser hashes

    // if (browser.webkit = !!webkit) browser.version = webkit[1];

    // if (android) os.android = true, os.version = android[2];
    // if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');
    // if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');
    // if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
    // if (webos) os.webos = true, os.version = webos[2];
    // if (touchpad) os.touchpad = true;
    // if (blackberry) os.blackberry = true, os.version = blackberry[2];
    // if (bb10) os.bb10 = true, os.version = bb10[2];
    // if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2];
    // if (playbook) browser.playbook = true;
    // if (kindle) os.kindle = true, os.version = kindle[1];
    // if (silk) browser.silk = true, browser.version = silk[1];
    // if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;
    // if (chrome) browser.chrome = true, browser.version = chrome[1];
    if (firefox) {
        browser.firefox = true;
        browser.version = firefox[1];
    }
    // if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true;
    // if (webview) browser.webview = true;

    if (ie) {
        browser.ie = true;
        browser.version = ie[1];
    }

    if (edge) {
        browser.edge = true;
        browser.version = edge[1];
    }

    // It is difficult to detect WeChat in Win Phone precisely, because ua can
    // not be set on win phone. So we do not consider Win Phone.
    if (weChat) {
        browser.weChat = true;
    }

    // os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||
    //     (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)));
    // os.phone  = !!(!os.tablet && !os.ipod && (android || iphone || webos ||
    //     (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) ||
    //     (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))));

    return {
        browser: browser,
        os: os,
        node: false,
        // 原生canvas支持，改极端点了
        // canvasSupported : !(browser.ie && parseFloat(browser.version) < 9)
        canvasSupported: !!document.createElement('canvas').getContext,
        svgSupported: typeof SVGRect !== 'undefined',
        // works on most browsers
        // IE10/11 does not support touch event, and MS Edge supports them but not by
        // default, so we dont check navigator.maxTouchPoints for them here.
        touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge,
        // <http://caniuse.com/#search=pointer%20event>.
        pointerEventsSupported: 'onpointerdown' in window
            // Firefox supports pointer but not by default, only MS browsers are reliable on pointer
            // events currently. So we dont use that on other browsers unless tested sufficiently.
            // Although IE 10 supports pointer event, it use old style and is different from the
            // standard. So we exclude that. (IE 10 is hardly used on touch device)
            && (browser.edge || (browser.ie && browser.version >= 11)),
        // passiveSupported: detectPassiveSupport()
        domSupported: typeof document !== 'undefined'
    };
}

// See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
// function detectPassiveSupport() {
//     // Test via a getter in the options object to see if the passive property is accessed
//     var supportsPassive = false;
//     try {
//         var opts = Object.defineProperty({}, 'passive', {
//             get: function() {
//                 supportsPassive = true;
//             }
//         });
//         window.addEventListener('testPassive', function() {}, opts);
//     } catch (e) {
//     }
//     return supportsPassive;
// }

/**
 * @module zrender/core/util
 */

// 用于处理merge时无法遍历Date等对象的问题
var BUILTIN_OBJECT = {
    '[object Function]': 1,
    '[object RegExp]': 1,
    '[object Date]': 1,
    '[object Error]': 1,
    '[object CanvasGradient]': 1,
    '[object CanvasPattern]': 1,
    // For node-canvas
    '[object Image]': 1,
    '[object Canvas]': 1
};

var TYPED_ARRAY = {
    '[object Int8Array]': 1,
    '[object Uint8Array]': 1,
    '[object Uint8ClampedArray]': 1,
    '[object Int16Array]': 1,
    '[object Uint16Array]': 1,
    '[object Int32Array]': 1,
    '[object Uint32Array]': 1,
    '[object Float32Array]': 1,
    '[object Float64Array]': 1
};

var objToString = Object.prototype.toString;

var arrayProto = Array.prototype;
var nativeForEach = arrayProto.forEach;
var nativeFilter = arrayProto.filter;
var nativeSlice = arrayProto.slice;
var nativeMap = arrayProto.map;
var nativeReduce = arrayProto.reduce;

// Avoid assign to an exported variable, for transforming to cjs.
var methods = {};

function $override(name, fn) {
    // Clear ctx instance for different environment
    if (name === 'createCanvas') {
        _ctx = null;
    }

    methods[name] = fn;
}

/**
 * Those data types can be cloned:
 *     Plain object, Array, TypedArray, number, string, null, undefined.
 * Those data types will be assgined using the orginal data:
 *     BUILTIN_OBJECT
 * Instance of user defined class will be cloned to a plain object, without
 * properties in prototype.
 * Other data types is not supported (not sure what will happen).
 *
 * Caution: do not support clone Date, for performance consideration.
 * (There might be a large number of date in `series.data`).
 * So date should not be modified in and out of echarts.
 *
 * @param {*} source
 * @return {*} new
 */
function clone(source) {
    if (source == null || typeof source !== 'object') {
        return source;
    }

    var result = source;
    var typeStr = objToString.call(source);

    if (typeStr === '[object Array]') {
        if (!isPrimitive(source)) {
            result = [];
            for (var i = 0, len = source.length; i < len; i++) {
                result[i] = clone(source[i]);
            }
        }
    }
    else if (TYPED_ARRAY[typeStr]) {
        if (!isPrimitive(source)) {
            var Ctor = source.constructor;
            if (source.constructor.from) {
                result = Ctor.from(source);
            }
            else {
                result = new Ctor(source.length);
                for (var i = 0, len = source.length; i < len; i++) {
                    result[i] = clone(source[i]);
                }
            }
        }
    }
    else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
        result = {};
        for (var key in source) {
            if (source.hasOwnProperty(key)) {
                result[key] = clone(source[key]);
            }
        }
    }

    return result;
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} target
 * @param {*} source
 * @param {boolean} [overwrite=false]
 */
function merge(target, source, overwrite) {
    // We should escapse that source is string
    // and enter for ... in ...
    if (!isObject$1(source) || !isObject$1(target)) {
        return overwrite ? clone(source) : target;
    }

    for (var key in source) {
        if (source.hasOwnProperty(key)) {
            var targetProp = target[key];
            var sourceProp = source[key];

            if (isObject$1(sourceProp)
                && isObject$1(targetProp)
                && !isArray(sourceProp)
                && !isArray(targetProp)
                && !isDom(sourceProp)
                && !isDom(targetProp)
                && !isBuiltInObject(sourceProp)
                && !isBuiltInObject(targetProp)
                && !isPrimitive(sourceProp)
                && !isPrimitive(targetProp)
            ) {
                // 如果需要递归覆盖，就递归调用merge
                merge(targetProp, sourceProp, overwrite);
            }
            else if (overwrite || !(key in target)) {
                // 否则只处理overwrite为true，或者在目标对象中没有此属性的情况
                // NOTE，在 target[key] 不存在的时候也是直接覆盖
                target[key] = clone(source[key], true);
            }
        }
    }

    return target;
}

/**
 * @param {Array} targetAndSources The first item is target, and the rests are source.
 * @param {boolean} [overwrite=false]
 * @return {*} target
 */
function mergeAll(targetAndSources, overwrite) {
    var result = targetAndSources[0];
    for (var i = 1, len = targetAndSources.length; i < len; i++) {
        result = merge(result, targetAndSources[i], overwrite);
    }
    return result;
}

/**
 * @param {*} target
 * @param {*} source
 * @memberOf module:zrender/core/util
 */
function extend(target, source) {
    for (var key in source) {
        if (source.hasOwnProperty(key)) {
            target[key] = source[key];
        }
    }
    return target;
}

/**
 * @param {*} target
 * @param {*} source
 * @param {boolean} [overlay=false]
 * @memberOf module:zrender/core/util
 */
function defaults(target, source, overlay) {
    for (var key in source) {
        if (source.hasOwnProperty(key)
            && (overlay ? source[key] != null : target[key] == null)
        ) {
            target[key] = source[key];
        }
    }
    return target;
}

var createCanvas = function () {
    return methods.createCanvas();
};

methods.createCanvas = function () {
    return document.createElement('canvas');
};

// FIXME
var _ctx;

function getContext() {
    if (!_ctx) {
        // Use util.createCanvas instead of createCanvas
        // because createCanvas may be overwritten in different environment
        _ctx = createCanvas().getContext('2d');
    }
    return _ctx;
}

/**
 * 查询数组中元素的index
 * @memberOf module:zrender/core/util
 */
function indexOf(array, value) {
    if (array) {
        if (array.indexOf) {
            return array.indexOf(value);
        }
        for (var i = 0, len = array.length; i < len; i++) {
            if (array[i] === value) {
                return i;
            }
        }
    }
    return -1;
}

/**
 * 构造类继承关系
 *
 * @memberOf module:zrender/core/util
 * @param {Function} clazz 源类
 * @param {Function} baseClazz 基类
 */
function inherits(clazz, baseClazz) {
    var clazzPrototype = clazz.prototype;
    function F() {}
    F.prototype = baseClazz.prototype;
    clazz.prototype = new F();

    for (var prop in clazzPrototype) {
        if (clazzPrototype.hasOwnProperty(prop)) {
            clazz.prototype[prop] = clazzPrototype[prop];
        }
    }
    clazz.prototype.constructor = clazz;
    clazz.superClass = baseClazz;
}

/**
 * @memberOf module:zrender/core/util
 * @param {Object|Function} target
 * @param {Object|Function} sorce
 * @param {boolean} overlay
 */
function mixin(target, source, overlay) {
    target = 'prototype' in target ? target.prototype : target;
    source = 'prototype' in source ? source.prototype : source;

    defaults(target, source, overlay);
}

/**
 * Consider typed array.
 * @param {Array|TypedArray} data
 */
function isArrayLike(data) {
    if (!data) {
        return;
    }
    if (typeof data === 'string') {
        return false;
    }
    return typeof data.length === 'number';
}

/**
 * 数组或对象遍历
 * @memberOf module:zrender/core/util
 * @param {Object|Array} obj
 * @param {Function} cb
 * @param {*} [context]
 */
function each$1(obj, cb, context) {
    if (!(obj && cb)) {
        return;
    }
    if (obj.forEach && obj.forEach === nativeForEach) {
        obj.forEach(cb, context);
    }
    else if (obj.length === +obj.length) {
        for (var i = 0, len = obj.length; i < len; i++) {
            cb.call(context, obj[i], i, obj);
        }
    }
    else {
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                cb.call(context, obj[key], key, obj);
            }
        }
    }
}

/**
 * 数组映射
 * @memberOf module:zrender/core/util
 * @param {Array} obj
 * @param {Function} cb
 * @param {*} [context]
 * @return {Array}
 */
function map(obj, cb, context) {
    if (!(obj && cb)) {
        return;
    }
    if (obj.map && obj.map === nativeMap) {
        return obj.map(cb, context);
    }
    else {
        var result = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            result.push(cb.call(context, obj[i], i, obj));
        }
        return result;
    }
}

/**
 * @memberOf module:zrender/core/util
 * @param {Array} obj
 * @param {Function} cb
 * @param {Object} [memo]
 * @param {*} [context]
 * @return {Array}
 */
function reduce(obj, cb, memo, context) {
    if (!(obj && cb)) {
        return;
    }
    if (obj.reduce && obj.reduce === nativeReduce) {
        return obj.reduce(cb, memo, context);
    }
    else {
        for (var i = 0, len = obj.length; i < len; i++) {
            memo = cb.call(context, memo, obj[i], i, obj);
        }
        return memo;
    }
}

/**
 * 数组过滤
 * @memberOf module:zrender/core/util
 * @param {Array} obj
 * @param {Function} cb
 * @param {*} [context]
 * @return {Array}
 */
function filter(obj, cb, context) {
    if (!(obj && cb)) {
        return;
    }
    if (obj.filter && obj.filter === nativeFilter) {
        return obj.filter(cb, context);
    }
    else {
        var result = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            if (cb.call(context, obj[i], i, obj)) {
                result.push(obj[i]);
            }
        }
        return result;
    }
}

/**
 * 数组项查找
 * @memberOf module:zrender/core/util
 * @param {Array} obj
 * @param {Function} cb
 * @param {*} [context]
 * @return {*}
 */
function find(obj, cb, context) {
    if (!(obj && cb)) {
        return;
    }
    for (var i = 0, len = obj.length; i < len; i++) {
        if (cb.call(context, obj[i], i, obj)) {
            return obj[i];
        }
    }
}

/**
 * @memberOf module:zrender/core/util
 * @param {Function} func
 * @param {*} context
 * @return {Function}
 */
function bind(func, context) {
    var args = nativeSlice.call(arguments, 2);
    return function () {
        return func.apply(context, args.concat(nativeSlice.call(arguments)));
    };
}

/**
 * @memberOf module:zrender/core/util
 * @param {Function} func
 * @return {Function}
 */
function curry(func) {
    var args = nativeSlice.call(arguments, 1);
    return function () {
        return func.apply(this, args.concat(nativeSlice.call(arguments)));
    };
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isArray(value) {
    return objToString.call(value) === '[object Array]';
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isFunction$1(value) {
    return typeof value === 'function';
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isString(value) {
    return objToString.call(value) === '[object String]';
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isObject$1(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return type === 'function' || (!!value && type === 'object');
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isBuiltInObject(value) {
    return !!BUILTIN_OBJECT[objToString.call(value)];
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isTypedArray(value) {
    return !!TYPED_ARRAY[objToString.call(value)];
}

/**
 * @memberOf module:zrender/core/util
 * @param {*} value
 * @return {boolean}
 */
function isDom(value) {
    return typeof value === 'object'
        && typeof value.nodeType === 'number'
        && typeof value.ownerDocument === 'object';
}

/**
 * Whether is exactly NaN. Notice isNaN('a') returns true.
 * @param {*} value
 * @return {boolean}
 */
function eqNaN(value) {
    /* eslint-disable-next-line no-self-compare */
    return value !== value;
}

/**
 * If value1 is not null, then return value1, otherwise judget rest of values.
 * Low performance.
 * @memberOf module:zrender/core/util
 * @return {*} Final value
 */
function retrieve(values) {
    for (var i = 0, len = arguments.length; i < len; i++) {
        if (arguments[i] != null) {
            return arguments[i];
        }
    }
}

function retrieve2(value0, value1) {
    return value0 != null
        ? value0
        : value1;
}

function retrieve3(value0, value1, value2) {
    return value0 != null
        ? value0
        : value1 != null
        ? value1
        : value2;
}

/**
 * @memberOf module:zrender/core/util
 * @param {Array} arr
 * @param {number} startIndex
 * @param {number} endIndex
 * @return {Array}
 */
function slice() {
    return Function.call.apply(nativeSlice, arguments);
}

/**
 * Normalize css liked array configuration
 * e.g.
 *  3 => [3, 3, 3, 3]
 *  [4, 2] => [4, 2, 4, 2]
 *  [4, 3, 2] => [4, 3, 2, 3]
 * @param {number|Array.<number>} val
 * @return {Array.<number>}
 */
function normalizeCssArray(val) {
    if (typeof (val) === 'number') {
        return [val, val, val, val];
    }
    var len = val.length;
    if (len === 2) {
        // vertical | horizontal
        return [val[0], val[1], val[0], val[1]];
    }
    else if (len === 3) {
        // top | horizontal | bottom
        return [val[0], val[1], val[2], val[1]];
    }
    return val;
}

/**
 * @memberOf module:zrender/core/util
 * @param {boolean} condition
 * @param {string} message
 */
function assert$1(condition, message) {
    if (!condition) {
        throw new Error(message);
    }
}

/**
 * @memberOf module:zrender/core/util
 * @param {string} str string to be trimed
 * @return {string} trimed string
 */
function trim(str) {
    if (str == null) {
        return null;
    }
    else if (typeof str.trim === 'function') {
        return str.trim();
    }
    else {
        return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    }
}

var primitiveKey = '__ec_primitive__';
/**
 * Set an object as primitive to be ignored traversing children in clone or merge
 */
function setAsPrimitive(obj) {
    obj[primitiveKey] = true;
}

function isPrimitive(obj) {
    return obj[primitiveKey];
}

/**
 * @constructor
 * @param {Object} obj Only apply `ownProperty`.
 */
function HashMap(obj) {
    var isArr = isArray(obj);
    // Key should not be set on this, otherwise
    // methods get/set/... may be overrided.
    this.data = {};
    var thisMap = this;

    (obj instanceof HashMap)
        ? obj.each(visit)
        : (obj && each$1(obj, visit));

    function visit(value, key) {
        isArr ? thisMap.set(value, key) : thisMap.set(key, value);
    }
}

HashMap.prototype = {
    constructor: HashMap,
    // Do not provide `has` method to avoid defining what is `has`.
    // (We usually treat `null` and `undefined` as the same, different
    // from ES6 Map).
    get: function (key) {
        return this.data.hasOwnProperty(key) ? this.data[key] : null;
    },
    set: function (key, value) {
        // Comparing with invocation chaining, `return value` is more commonly
        // used in this case: `var someVal = map.set('a', genVal());`
        return (this.data[key] = value);
    },
    // Although util.each can be performed on this hashMap directly, user
    // should not use the exposed keys, who are prefixed.
    each: function (cb, context) {
        context !== void 0 && (cb = bind(cb, context));
        /* eslint-disable guard-for-in */
        for (var key in this.data) {
            this.data.hasOwnProperty(key) && cb(this.data[key], key);
        }
        /* eslint-enable guard-for-in */
    },
    // Do not use this method if performance sensitive.
    removeKey: function (key) {
        delete this.data[key];
    }
};

function createHashMap(obj) {
    return new HashMap(obj);
}

function concatArray(a, b) {
    var newArray = new a.constructor(a.length + b.length);
    for (var i = 0; i < a.length; i++) {
        newArray[i] = a[i];
    }
    var offset = a.length;
    for (i = 0; i < b.length; i++) {
        newArray[i + offset] = b[i];
    }
    return newArray;
}


function noop() {}


var zrUtil = (Object.freeze || Object)({
	$override: $override,
	clone: clone,
	merge: merge,
	mergeAll: mergeAll,
	extend: extend,
	defaults: defaults,
	createCanvas: createCanvas,
	getContext: getContext,
	indexOf: indexOf,
	inherits: inherits,
	mixin: mixin,
	isArrayLike: isArrayLike,
	each: each$1,
	map: map,
	reduce: reduce,
	filter: filter,
	find: find,
	bind: bind,
	curry: curry,
	isArray: isArray,
	isFunction: isFunction$1,
	isString: isString,
	isObject: isObject$1,
	isBuiltInObject: isBuiltInObject,
	isTypedArray: isTypedArray,
	isDom: isDom,
	eqNaN: eqNaN,
	retrieve: retrieve,
	retrieve2: retrieve2,
	retrieve3: retrieve3,
	slice: slice,
	normalizeCssArray: normalizeCssArray,
	assert: assert$1,
	trim: trim,
	setAsPrimitive: setAsPrimitive,
	isPrimitive: isPrimitive,
	createHashMap: createHashMap,
	concatArray: concatArray,
	noop: noop
});

/* global Float32Array */

var ArrayCtor = typeof Float32Array === 'undefined'
    ? Array
    : Float32Array;

/**
 * 创建一个向量
 * @param {number} [x=0]
 * @param {number} [y=0]
 * @return {Vector2}
 */
function create(x, y) {
    var out = new ArrayCtor(2);
    if (x == null) {
        x = 0;
    }
    if (y == null) {
        y = 0;
    }
    out[0] = x;
    out[1] = y;
    return out;
}

/**
 * 复制向量数据
 * @param {Vector2} out
 * @param {Vector2} v
 * @return {Vector2}
 */
function copy(out, v) {
    out[0] = v[0];
    out[1] = v[1];
    return out;
}

/**
 * 克隆一个向量
 * @param {Vector2} v
 * @return {Vector2}
 */
function clone$1(v) {
    var out = new ArrayCtor(2);
    out[0] = v[0];
    out[1] = v[1];
    return out;
}

/**
 * 设置向量的两个项
 * @param {Vector2} out
 * @param {number} a
 * @param {number} b
 * @return {Vector2} 结果
 */
function set(out, a, b) {
    out[0] = a;
    out[1] = b;
    return out;
}

/**
 * 向量相加
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 */
function add(out, v1, v2) {
    out[0] = v1[0] + v2[0];
    out[1] = v1[1] + v2[1];
    return out;
}

/**
 * 向量缩放后相加
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 * @param {number} a
 */
function scaleAndAdd(out, v1, v2, a) {
    out[0] = v1[0] + v2[0] * a;
    out[1] = v1[1] + v2[1] * a;
    return out;
}

/**
 * 向量相减
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 */
function sub(out, v1, v2) {
    out[0] = v1[0] - v2[0];
    out[1] = v1[1] - v2[1];
    return out;
}

/**
 * 向量长度
 * @param {Vector2} v
 * @return {number}
 */
function len(v) {
    return Math.sqrt(lenSquare(v));
}
var length = len; // jshint ignore:line

/**
 * 向量长度平方
 * @param {Vector2} v
 * @return {number}
 */
function lenSquare(v) {
    return v[0] * v[0] + v[1] * v[1];
}
var lengthSquare = lenSquare;

/**
 * 向量乘法
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 */
function mul(out, v1, v2) {
    out[0] = v1[0] * v2[0];
    out[1] = v1[1] * v2[1];
    return out;
}

/**
 * 向量除法
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 */
function div(out, v1, v2) {
    out[0] = v1[0] / v2[0];
    out[1] = v1[1] / v2[1];
    return out;
}

/**
 * 向量点乘
 * @param {Vector2} v1
 * @param {Vector2} v2
 * @return {number}
 */
function dot(v1, v2) {
    return v1[0] * v2[0] + v1[1] * v2[1];
}

/**
 * 向量缩放
 * @param {Vector2} out
 * @param {Vector2} v
 * @param {number} s
 */
function scale(out, v, s) {
    out[0] = v[0] * s;
    out[1] = v[1] * s;
    return out;
}

/**
 * 向量归一化
 * @param {Vector2} out
 * @param {Vector2} v
 */
function normalize(out, v) {
    var d = len(v);
    if (d === 0) {
        out[0] = 0;
        out[1] = 0;
    }
    else {
        out[0] = v[0] / d;
        out[1] = v[1] / d;
    }
    return out;
}

/**
 * 计算向量间距离
 * @param {Vector2} v1
 * @param {Vector2} v2
 * @return {number}
 */
function distance(v1, v2) {
    return Math.sqrt(
        (v1[0] - v2[0]) * (v1[0] - v2[0])
        + (v1[1] - v2[1]) * (v1[1] - v2[1])
    );
}
var dist = distance;

/**
 * 向量距离平方
 * @param {Vector2} v1
 * @param {Vector2} v2
 * @return {number}
 */
function distanceSquare(v1, v2) {
    return (v1[0] - v2[0]) * (v1[0] - v2[0])
        + (v1[1] - v2[1]) * (v1[1] - v2[1]);
}
var distSquare = distanceSquare;

/**
 * 求负向量
 * @param {Vector2} out
 * @param {Vector2} v
 */
function negate(out, v) {
    out[0] = -v[0];
    out[1] = -v[1];
    return out;
}

/**
 * 插值两个点
 * @param {Vector2} out
 * @param {Vector2} v1
 * @param {Vector2} v2
 * @param {number} t
 */
function lerp(out, v1, v2, t) {
    out[0] = v1[0] + t * (v2[0] - v1[0]);
    out[1] = v1[1] + t * (v2[1] - v1[1]);
    return out;
}

/**
 * 矩阵左乘向量
 * @param {Vector2} out
 * @param {Vector2} v
 * @param {Vector2} m
 */
function applyTransform(out, v, m) {
    var x = v[0];
    var y = v[1];
    out[0] = m[0] * x + m[2] * y + m[4];
    out[1] = m[1] * x + m[3] * y + m[5];
    return out;
}

/**
 * 求两个向量最小值
 * @param  {Vector2} out
 * @param  {Vector2} v1
 * @param  {Vector2} v2
 */
function min(out, v1, v2) {
    out[0] = Math.min(v1[0], v2[0]);
    out[1] = Math.min(v1[1], v2[1]);
    return out;
}

/**
 * 求两个向量最大值
 * @param  {Vector2} out
 * @param  {Vector2} v1
 * @param  {Vector2} v2
 */
function max(out, v1, v2) {
    out[0] = Math.max(v1[0], v2[0]);
    out[1] = Math.max(v1[1], v2[1]);
    return out;
}


var vector = (Object.freeze || Object)({
	create: create,
	copy: copy,
	clone: clone$1,
	set: set,
	add: add,
	scaleAndAdd: scaleAndAdd,
	sub: sub,
	len: len,
	length: length,
	lenSquare: lenSquare,
	lengthSquare: lengthSquare,
	mul: mul,
	div: div,
	dot: dot,
	scale: scale,
	normalize: normalize,
	distance: distance,
	dist: dist,
	distanceSquare: distanceSquare,
	distSquare: distSquare,
	negate: negate,
	lerp: lerp,
	applyTransform: applyTransform,
	min: min,
	max: max
});

// TODO Draggable for group
// FIXME Draggable on element which has parent rotation or scale
function Draggable() {

    this.on('mousedown', this._dragStart, this);
    this.on('mousemove', this._drag, this);
    this.on('mouseup', this._dragEnd, this);
    this.on('globalout', this._dragEnd, this);
    // this._dropTarget = null;
    // this._draggingTarget = null;

    // this._x = 0;
    // this._y = 0;
}

Draggable.prototype = {

    constructor: Draggable,

    _dragStart: function (e) {
        var draggingTarget = e.target;
        if (draggingTarget && draggingTarget.draggable) {
            this._draggingTarget = draggingTarget;
            draggingTarget.dragging = true;
            this._x = e.offsetX;
            this._y = e.offsetY;

            this.dispatchToElement(param(draggingTarget, e), 'dragstart', e.event);
        }
    },

    _drag: function (e) {
        var draggingTarget = this._draggingTarget;
        if (draggingTarget) {

            var x = e.offsetX;
            var y = e.offsetY;

            var dx = x - this._x;
            var dy = y - this._y;
            this._x = x;
            this._y = y;

            draggingTarget.drift(dx, dy, e);
            this.dispatchToElement(param(draggingTarget, e), 'drag', e.event);

            var dropTarget = this.findHover(x, y, draggingTarget).target;
            var lastDropTarget = this._dropTarget;
            this._dropTarget = dropTarget;

            if (draggingTarget !== dropTarget) {
                if (lastDropTarget && dropTarget !== lastDropTarget) {
                    this.dispatchToElement(param(lastDropTarget, e), 'dragleave', e.event);
                }
                if (dropTarget && dropTarget !== lastDropTarget) {
                    this.dispatchToElement(param(dropTarget, e), 'dragenter', e.event);
                }
            }
        }
    },

    _dragEnd: function (e) {
        var draggingTarget = this._draggingTarget;

        if (draggingTarget) {
            draggingTarget.dragging = false;
        }

        this.dispatchToElement(param(draggingTarget, e), 'dragend', e.event);

        if (this._dropTarget) {
            this.dispatchToElement(param(this._dropTarget, e), 'drop', e.event);
        }

        this._draggingTarget = null;
        this._dropTarget = null;
    }

};

function param(target, e) {
    return {target: target, topTarget: e && e.topTarget};
}

/**
 * Event Mixin
 * @module zrender/mixin/Eventful
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *         pissang (https://www.github.com/pissang)
 */

var arrySlice = Array.prototype.slice;

/**
 * Event dispatcher.
 *
 * @alias module:zrender/mixin/Eventful
 * @constructor
 * @param {Object} [eventProcessor] The object eventProcessor is the scope when
 *        `eventProcessor.xxx` called.
 * @param {Function} [eventProcessor.normalizeQuery]
 *        param: {string|Object} Raw query.
 *        return: {string|Object} Normalized query.
 * @param {Function} [eventProcessor.filter] Event will be dispatched only
 *        if it returns `true`.
 *        param: {string} eventType
 *        param: {string|Object} query
 *        return: {boolean}
 * @param {Function} [eventProcessor.afterTrigger] Call after all handlers called.
 *        param: {string} eventType
 */
var Eventful = function (eventProcessor) {
    this._$handlers = {};
    this._$eventProcessor = eventProcessor;
};

Eventful.prototype = {

    constructor: Eventful,

    /**
     * The handler can only be triggered once, then removed.
     *
     * @param {string} event The event name.
     * @param {string|Object} [query] Condition used on event filter.
     * @param {Function} handler The event handler.
     * @param {Object} context
     */
    one: function (event, query, handler, context) {
        return on(this, event, query, handler, context, true);
    },

    /**
     * Bind a handler.
     *
     * @param {string} event The event name.
     * @param {string|Object} [query] Condition used on event filter.
     * @param {Function} handler The event handler.
     * @param {Object} [context]
     */
    on: function (event, query, handler, context) {
        return on(this, event, query, handler, context, false);
    },

    /**
     * Whether any handler has bound.
     *
     * @param  {string}  event
     * @return {boolean}
     */
    isSilent: function (event) {
        var _h = this._$handlers;
        return !_h[event] || !_h[event].length;
    },

    /**
     * Unbind a event.
     *
     * @param {string} event The event name.
     * @param {Function} [handler] The event handler.
     */
    off: function (event, handler) {
        var _h = this._$handlers;

        if (!event) {
            this._$handlers = {};
            return this;
        }

        if (handler) {
            if (_h[event]) {
                var newList = [];
                for (var i = 0, l = _h[event].length; i < l; i++) {
                    if (_h[event][i].h !== handler) {
                        newList.push(_h[event][i]);
                    }
                }
                _h[event] = newList;
            }

            if (_h[event] && _h[event].length === 0) {
                delete _h[event];
            }
        }
        else {
            delete _h[event];
        }

        return this;
    },

    /**
     * Dispatch a event.
     *
     * @param {string} type The event name.
     */
    trigger: function (type) {
        var _h = this._$handlers[type];
        var eventProcessor = this._$eventProcessor;

        if (_h) {
            var args = arguments;
            var argLen = args.length;

            if (argLen > 3) {
                args = arrySlice.call(args, 1);
            }

            var len = _h.length;
            for (var i = 0; i < len;) {
                var hItem = _h[i];
                if (eventProcessor
                    && eventProcessor.filter
                    && hItem.query != null
                    && !eventProcessor.filter(type, hItem.query)
                ) {
                    i++;
                    continue;
                }

                // Optimize advise from backbone
                switch (argLen) {
                    case 1:
                        hItem.h.call(hItem.ctx);
                        break;
                    case 2:
                        hItem.h.call(hItem.ctx, args[1]);
                        break;
                    case 3:
                        hItem.h.call(hItem.ctx, args[1], args[2]);
                        break;
                    default:
                        // have more than 2 given arguments
                        hItem.h.apply(hItem.ctx, args);
                        break;
                }

                if (hItem.one) {
                    _h.splice(i, 1);
                    len--;
                }
                else {
                    i++;
                }
            }
        }

        eventProcessor && eventProcessor.afterTrigger
            && eventProcessor.afterTrigger(type);

        return this;
    },

    /**
     * Dispatch a event with context, which is specified at the last parameter.
     *
     * @param {string} type The event name.
     */
    triggerWithContext: function (type) {
        var _h = this._$handlers[type];
        var eventProcessor = this._$eventProcessor;

        if (_h) {
            var args = arguments;
            var argLen = args.length;

            if (argLen > 4) {
                args = arrySlice.call(args, 1, args.length - 1);
            }
            var ctx = args[args.length - 1];

            var len = _h.length;
            for (var i = 0; i < len;) {
                var hItem = _h[i];
                if (eventProcessor
                    && eventProcessor.filter
                    && hItem.query != null
                    && !eventProcessor.filter(type, hItem.query)
                ) {
                    i++;
                    continue;
                }

                // Optimize advise from backbone
                switch (argLen) {
                    case 1:
                        hItem.h.call(ctx);
                        break;
                    case 2:
                        hItem.h.call(ctx, args[1]);
                        break;
                    case 3:
                        hItem.h.call(ctx, args[1], args[2]);
                        break;
                    default:
                        // have more than 2 given arguments
                        hItem.h.apply(ctx, args);
                        break;
                }

                if (hItem.one) {
                    _h.splice(i, 1);
                    len--;
                }
                else {
                    i++;
                }
            }
        }

        eventProcessor && eventProcessor.afterTrigger
            && eventProcessor.afterTrigger(type);

        return this;
    }
};

function normalizeQuery(host, query) {
    var eventProcessor = host._$eventProcessor;
    if (query != null && eventProcessor && eventProcessor.normalizeQuery) {
        query = eventProcessor.normalizeQuery(query);
    }
    return query;
}

function on(eventful, event, query, handler, context, isOnce) {
    var _h = eventful._$handlers;

    if (typeof query === 'function') {
        context = handler;
        handler = query;
        query = null;
    }

    if (!handler || !event) {
        return eventful;
    }

    query = normalizeQuery(eventful, query);

    if (!_h[event]) {
        _h[event] = [];
    }

    for (var i = 0; i < _h[event].length; i++) {
        if (_h[event][i].h === handler) {
            return eventful;
        }
    }

    var wrap = {
        h: handler,
        one: isOnce,
        query: query,
        ctx: context || eventful,
        // FIXME
        // Do not publish this feature util it is proved that it makes sense.
        callAtLast: handler.zrEventfulCallAtLast
    };

    var lastIndex = _h[event].length - 1;
    var lastWrap = _h[event][lastIndex];
    (lastWrap && lastWrap.callAtLast)
        ? _h[event].splice(lastIndex, 0, wrap)
        : _h[event].push(wrap);

    return eventful;
}

/**
 * The algoritm is learnt from
 * https://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/
 * And we made some optimization for matrix inversion.
 * Other similar approaches:
 * "cv::getPerspectiveTransform", "Direct Linear Transformation".
 */

var LN2 = Math.log(2);

function determinant(rows, rank, rowStart, rowMask, colMask, detCache) {
    var cacheKey = rowMask + '-' + colMask;
    var fullRank = rows.length;

    if (detCache.hasOwnProperty(cacheKey)) {
        return detCache[cacheKey];
    }

    if (rank === 1) {
        // In this case the colMask must be like: `11101111`. We can find the place of `0`.
        var colStart = Math.round(Math.log(((1 << fullRank) - 1) & ~colMask) / LN2);
        return rows[rowStart][colStart];
    }

    var subRowMask = rowMask | (1 << rowStart);
    var subRowStart = rowStart + 1;
    while (rowMask & (1 << subRowStart)) {
        subRowStart++;
    }

    var sum = 0;
    for (var j = 0, colLocalIdx = 0; j < fullRank; j++) {
        var colTag = 1 << j;
        if (!(colTag & colMask)) {
            sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j]
                // det(subMatrix(0, j))
                * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache);
            colLocalIdx++;
        }
    }

    detCache[cacheKey] = sum;

    return sum;
}

/**
 * Usage:
 * ```js
 * var transformer = buildTransformer(
 *     [10, 44, 100, 44, 100, 300, 10, 300],
 *     [50, 54, 130, 14, 140, 330, 14, 220]
 * );
 * var out = [];
 * transformer && transformer([11, 33], out);
 * ```
 *
 * Notice: `buildTransformer` may take more than 10ms in some Android device.
 *
 * @param {Array.<number>} src source four points, [x0, y0, x1, y1, x2, y2, x3, y3]
 * @param {Array.<number>} dest destination four points, [x0, y0, x1, y1, x2, y2, x3, y3]
 * @return {Function} transformer If fail, return null/undefined.
 */
function buildTransformer(src, dest) {
    var mA = [
        [src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]],
        [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]],
        [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]],
        [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]],
        [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]],
        [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]],
        [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]],
        [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]]
    ];

    var detCache = {};
    var det = determinant(mA, 8, 0, 0, 0, detCache);
    if (det === 0) {
        return;
    }

    // `invert(mA) * dest`, that is, `adj(mA) / det * dest`.
    var vh = [];
    for (var i = 0; i < 8; i++) {
        for (var j = 0; j < 8; j++) {
            vh[j] == null && (vh[j] = 0);
            vh[j] += ((i + j) % 2 ? -1 : 1)
                // det(subMatrix(i, j))
                * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache)
                / det * dest[i];
        }
    }

    return function (out, srcPointX, srcPointY) {
        var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1;
        out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk;
        out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk;
    };
}

/**
 * Utilities for mouse or touch events.
 */

var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;

var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
var EVENT_SAVED_PROP = '___zrEVENTSAVED';
var _calcOut = [];

/**
 * Get the `zrX` and `zrY`, which are relative to the top-left of
 * the input `el`.
 * CSS transform (2D & 3D) is supported.
 *
 * The strategy to fetch the coords:
 * + If `calculate` is not set as `true`, users of this method should
 * ensure that `el` is the same or the same size & location as `e.target`.
 * Otherwise the result coords are probably not expected. Because we
 * firstly try to get coords from e.offsetX/e.offsetY.
 * + If `calculate` is set as `true`, the input `el` can be any element
 * and we force to calculate the coords based on `el`.
 * + The input `el` should be positionable (not position:static).
 *
 * The force `calculate` can be used in case like:
 * When mousemove event triggered on ec tooltip, `e.target` is not `el`(zr painter.dom).
 *
 * @param {HTMLElement} el DOM element.
 * @param {Event} e Mouse event or touch event.
 * @param {Object} out Get `out.zrX` and `out.zrY` as the result.
 * @param {boolean} [calculate=false] Whether to force calculate
 *        the coordinates but not use ones provided by browser.
 */
function clientToLocal(el, e, out, calculate) {
    out = out || {};

    // According to the W3C Working Draft, offsetX and offsetY should be relative
    // to the padding edge of the target element. The only browser using this convention
    // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does
    // not support the properties.
    // (see http://www.jacklmoore.com/notes/mouse-position/)
    // In zr painter.dom, padding edge equals to border edge.

    if (calculate || !env$1.canvasSupported) {
        calculateZrXY(el, e, out);
    }
    // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned
    // ancestor element, so we should make sure el is positioned (e.g., not position:static).
    // BTW1, Webkit don't return the same results as FF in non-simple cases (like add
    // zoom-factor, overflow / opacity layers, transforms ...)
    // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.
    // <https://bugs.jquery.com/ticket/8523#comment:14>
    // BTW3, In ff, offsetX/offsetY is always 0.
    else if (env$1.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) {
        out.zrX = e.layerX;
        out.zrY = e.layerY;
    }
    // For IE6+, chrome, safari, opera. (When will ff support offsetX?)
    else if (e.offsetX != null) {
        out.zrX = e.offsetX;
        out.zrY = e.offsetY;
    }
    // For some other device, e.g., IOS safari.
    else {
        calculateZrXY(el, e, out);
    }

    return out;
}

function calculateZrXY(el, e, out) {
    // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect.
    if (el.getBoundingClientRect && env$1.domSupported) {
        var ex = e.clientX;
        var ey = e.clientY;

        if (el.nodeName.toUpperCase() === 'CANVAS') {
            // Original approach, which do not support CSS transform.
            // marker can not be locationed in a canvas container
            // (getBoundingClientRect is always 0). We do not support
            // that input a pre-created canvas to zr while using css
            // transform in iOS.
            var box = el.getBoundingClientRect();
            out.zrX = ex - box.left;
            out.zrY = ey - box.top;
            return;
        }
        else {
            var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
            var transformer = preparePointerTransformer(prepareCoordMarkers(el, saved), saved);
            if (transformer) {
                transformer(_calcOut, ex, ey);
                out.zrX = _calcOut[0];
                out.zrY = _calcOut[1];
                return;
            }
        }
    }
    out.zrX = out.zrY = 0;
}

function prepareCoordMarkers(el, saved) {
    var markers = saved.markers;
    if (markers) {
        return markers;
    }

    markers = saved.markers = [];
    var propLR = ['left', 'right'];
    var propTB = ['top', 'bottom'];

    for (var i = 0; i < 4; i++) {
        var marker = document.createElement('div');
        var stl = marker.style;
        var idxLR = i % 2;
        var idxTB = (i >> 1) % 2;
        stl.cssText = [
            'position:absolute',
            'visibility: hidden',
            'padding: 0',
            'margin: 0',
            'border-width: 0',
            'width:0',
            'height:0',
            // 'width: 5px',
            // 'height: 5px',
            propLR[idxLR] + ':0',
            propTB[idxTB] + ':0',
            propLR[1 - idxLR] + ':auto',
            propTB[1 - idxTB] + ':auto',
            ''
        ].join('!important;');
        el.appendChild(marker);
        markers.push(marker);
    }

    return markers;
}

function preparePointerTransformer(markers, saved) {
    var transformer = saved.transformer;
    var oldSrcCoords = saved.srcCoords;
    var useOld = true;
    var srcCoords = [];
    var destCoords = [];

    for (var i = 0; i < 4; i++) {
        var rect = markers[i].getBoundingClientRect();
        var ii = 2 * i;
        var x = rect.left;
        var y = rect.top;
        srcCoords.push(x, y);
        useOld &= oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
    }

    // Cache to avoid time consuming of `buildTransformer`.
    return useOld
        ? transformer
        : (
            saved.srcCoords = srcCoords,
            saved.transformer = buildTransformer(srcCoords, destCoords)
        );
}

/**
 * Normalize the coordinates of the input event.
 *
 * Get the `e.zrX` and `e.zrY`, which are relative to the top-left of
 * the input `el`.
 * Get `e.zrDelta` if using mouse wheel.
 * Get `e.which`, see the comment inside this function.
 *
 * Do not calculate repeatly if `zrX` and `zrY` already exist.
 *
 * Notice: see comments in `clientToLocal`. check the relationship
 * between the result coords and the parameters `el` and `calculate`.
 *
 * @param {HTMLElement} el DOM element.
 * @param {Event} [e] Mouse event or touch event. For lagency IE,
 *        do not need to input it and `window.event` is used.
 * @param {boolean} [calculate=false] Whether to force calculate
 *        the coordinates but not use ones provided by browser.
 */
function normalizeEvent(el, e, calculate) {

    e = e || window.event;

    if (e.zrX != null) {
        return e;
    }

    var eventType = e.type;
    var isTouch = eventType && eventType.indexOf('touch') >= 0;

    if (!isTouch) {
        clientToLocal(el, e, e, calculate);
        e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3;
    }
    else {
        var touch = eventType !== 'touchend'
            ? e.targetTouches[0]
            : e.changedTouches[0];
        touch && clientToLocal(el, touch, e, calculate);
    }

    // Add which for click: 1 === left; 2 === middle; 3 === right; otherwise: 0;
    // See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js
    // If e.which has been defined, it may be readonly,
    // see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
    var button = e.button;
    if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) {
        e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
    }
    // [Caution]: `e.which` from browser is not always reliable. For example,
    // when press left button and `mousemove (pointermove)` in Edge, the `e.which`
    // is 65536 and the `e.button` is -1. But the `mouseup (pointerup)` and
    // `mousedown (pointerdown)` is the same as Chrome does.

    return e;
}

/**
 * @param {HTMLElement} el
 * @param {string} name
 * @param {Function} handler
 */
function addEventListener(el, name, handler) {
    if (isDomLevel2) {
        // Reproduct the console warning:
        // [Violation] Added non-passive event listener to a scroll-blocking <some> event.
        // Consider marking event handler as 'passive' to make the page more responsive.
        // Just set console log level: verbose in chrome dev tool.
        // then the warning log will be printed when addEventListener called.
        // See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
        // We have not yet found a neat way to using passive. Because in zrender the dom event
        // listener delegate all of the upper events of element. Some of those events need
        // to prevent default. For example, the feature `preventDefaultMouseMove` of echarts.
        // Before passive can be adopted, these issues should be considered:
        // (1) Whether and how a zrender user specifies an event listener passive. And by default,
        // passive or not.
        // (2) How to tread that some zrender event listener is passive, and some is not. If
        // we use other way but not preventDefault of mousewheel and touchmove, browser
        // compatibility should be handled.

        // var opts = (env.passiveSupported && name === 'mousewheel')
        //     ? {passive: true}
        //     // By default, the third param of el.addEventListener is `capture: false`.
        //     : void 0;
        // el.addEventListener(name, handler /* , opts */);
        el.addEventListener(name, handler);
    }
    else {
        el.attachEvent('on' + name, handler);
    }
}

function removeEventListener(el, name, handler) {
    if (isDomLevel2) {
        el.removeEventListener(name, handler);
    }
    else {
        el.detachEvent('on' + name, handler);
    }
}

/**
 * preventDefault and stopPropagation.
 * Notice: do not use this method in zrender. It can only be
 * used by upper applications if necessary.
 *
 * @param {Event} e A mouse or touch event.
 */
var stop = isDomLevel2
    ? function (e) {
        e.preventDefault();
        e.stopPropagation();
        e.cancelBubble = true;
    }
    : function (e) {
        e.returnValue = false;
        e.cancelBubble = true;
    };

/**
 * This method only works for mouseup and mousedown. The functionality is restricted
 * for fault tolerance, See the `e.which` compatibility above.
 *
 * @param {MouseEvent} e
 * @return {boolean}
 */
function isMiddleOrRightButtonOnMouseUpDown(e) {
    return e.which === 2 || e.which === 3;
}

/**
 * To be removed.
 * @deprecated
 */

/**
 * Only implements needed gestures for mobile.
 */

var GestureMgr = function () {

    /**
     * @private
     * @type {Array.<Object>}
     */
    this._track = [];
};

GestureMgr.prototype = {

    constructor: GestureMgr,

    recognize: function (event, target, root) {
        this._doTrack(event, target, root);
        return this._recognize(event);
    },

    clear: function () {
        this._track.length = 0;
        return this;
    },

    _doTrack: function (event, target, root) {
        var touches = event.touches;

        if (!touches) {
            return;
        }

        var trackItem = {
            points: [],
            touches: [],
            target: target,
            event: event
        };

        for (var i = 0, len = touches.length; i < len; i++) {
            var touch = touches[i];
            var pos = clientToLocal(root, touch, {});
            trackItem.points.push([pos.zrX, pos.zrY]);
            trackItem.touches.push(touch);
        }

        this._track.push(trackItem);
    },

    _recognize: function (event) {
        for (var eventName in recognizers) {
            if (recognizers.hasOwnProperty(eventName)) {
                var gestureInfo = recognizers[eventName](this._track, event);
                if (gestureInfo) {
                    return gestureInfo;
                }
            }
        }
    }
};

function dist$1(pointPair) {
    var dx = pointPair[1][0] - pointPair[0][0];
    var dy = pointPair[1][1] - pointPair[0][1];

    return Math.sqrt(dx * dx + dy * dy);
}

function center(pointPair) {
    return [
        (pointPair[0][0] + pointPair[1][0]) / 2,
        (pointPair[0][1] + pointPair[1][1]) / 2
    ];
}

var recognizers = {

    pinch: function (track, event) {
        var trackLen = track.length;

        if (!trackLen) {
            return;
        }

        var pinchEnd = (track[trackLen - 1] || {}).points;
        var pinchPre = (track[trackLen - 2] || {}).points || pinchEnd;

        if (pinchPre
            && pinchPre.length > 1
            && pinchEnd
            && pinchEnd.length > 1
        ) {
            var pinchScale = dist$1(pinchEnd) / dist$1(pinchPre);
            !isFinite(pinchScale) && (pinchScale = 1);

            event.pinchScale = pinchScale;

            var pinchCenter = center(pinchEnd);
            event.pinchX = pinchCenter[0];
            event.pinchY = pinchCenter[1];

            return {
                type: 'pinch',
                target: track[0].target,
                event: event
            };
        }
    }

    // Only pinch currently.
};

var SILENT = 'silent';

function makeEventPacket(eveType, targetInfo, event) {
    return {
        type: eveType,
        event: event,
        // target can only be an element that is not silent.
        target: targetInfo.target,
        // topTarget can be a silent element.
        topTarget: targetInfo.topTarget,
        cancelBubble: false,
        offsetX: event.zrX,
        offsetY: event.zrY,
        gestureEvent: event.gestureEvent,
        pinchX: event.pinchX,
        pinchY: event.pinchY,
        pinchScale: event.pinchScale,
        wheelDelta: event.zrDelta,
        zrByTouch: event.zrByTouch,
        which: event.which,
        stop: stopEvent
    };
}

function stopEvent(event) {
    stop(this.event);
}

function EmptyProxy() {}
EmptyProxy.prototype.dispose = function () {};

var handlerNames = [
    'click', 'dblclick', 'mousewheel', 'mouseout',
    'mouseup', 'mousedown', 'mousemove', 'contextmenu'
];
/**
 * @alias module:zrender/Handler
 * @constructor
 * @extends module:zrender/mixin/Eventful
 * @param {module:zrender/Storage} storage Storage instance.
 * @param {module:zrender/Painter} painter Painter instance.
 * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance.
 * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()).
 */
var Handler = function (storage, painter, proxy, painterRoot) {
    Eventful.call(this);

    this.storage = storage;

    this.painter = painter;

    this.painterRoot = painterRoot;

    proxy = proxy || new EmptyProxy();

    /**
     * Proxy of event. can be Dom, WebGLSurface, etc.
     */
    this.proxy = null;

    /**
     * {target, topTarget, x, y}
     * @private
     * @type {Object}
     */
    this._hovered = {};

    /**
     * @private
     * @type {Date}
     */
    this._lastTouchMoment;

    /**
     * @private
     * @type {number}
     */
    this._lastX;

    /**
     * @private
     * @type {number}
     */
    this._lastY;

    /**
     * @private
     * @type {module:zrender/core/GestureMgr}
     */
    this._gestureMgr;


    Draggable.call(this);

    this.setHandlerProxy(proxy);
};

Handler.prototype = {

    constructor: Handler,

    setHandlerProxy: function (proxy) {
        if (this.proxy) {
            this.proxy.dispose();
        }

        if (proxy) {
            each$1(handlerNames, function (name) {
                proxy.on && proxy.on(name, this[name], this);
            }, this);
            // Attach handler
            proxy.handler = this;
        }
        this.proxy = proxy;
    },

    mousemove: function (event) {
        var x = event.zrX;
        var y = event.zrY;

        var lastHovered = this._hovered;
        var lastHoveredTarget = lastHovered.target;

        // If lastHoveredTarget is removed from zr (detected by '__zr') by some API call
        // (like 'setOption' or 'dispatchAction') in event handlers, we should find
        // lastHovered again here. Otherwise 'mouseout' can not be triggered normally.
        // See #6198.
        if (lastHoveredTarget && !lastHoveredTarget.__zr) {
            lastHovered = this.findHover(lastHovered.x, lastHovered.y);
            lastHoveredTarget = lastHovered.target;
        }

        var hovered = this._hovered = this.findHover(x, y);
        var hoveredTarget = hovered.target;

        var proxy = this.proxy;
        proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default');

        // Mouse out on previous hovered element
        if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) {
            this.dispatchToElement(lastHovered, 'mouseout', event);
        }

        // Mouse moving on one element
        this.dispatchToElement(hovered, 'mousemove', event);

        // Mouse over on a new element
        if (hoveredTarget && hoveredTarget !== lastHoveredTarget) {
            this.dispatchToElement(hovered, 'mouseover', event);
        }
    },

    mouseout: function (event) {
        this.dispatchToElement(this._hovered, 'mouseout', event);

        // There might be some doms created by upper layer application
        // at the same level of painter.getViewportRoot() (e.g., tooltip
        // dom created by echarts), where 'globalout' event should not
        // be triggered when mouse enters these doms. (But 'mouseout'
        // should be triggered at the original hovered element as usual).
        var element = event.toElement || event.relatedTarget;
        var innerDom;
        do {
            element = element && element.parentNode;
        }
        while (element && element.nodeType !== 9 && !(
            innerDom = element === this.painterRoot
        ));

        !innerDom && this.trigger('globalout', {event: event});
    },

    /**
     * Resize
     */
    resize: function (event) {
        this._hovered = {};
    },

    /**
     * Dispatch event
     * @param {string} eventName
     * @param {event=} eventArgs
     */
    dispatch: function (eventName, eventArgs) {
        var handler = this[eventName];
        handler && handler.call(this, eventArgs);
    },

    /**
     * Dispose
     */
    dispose: function () {

        this.proxy.dispose();

        this.storage =
        this.proxy =
        this.painter = null;
    },

    /**
     * 设置默认的cursor style
     * @param {string} [cursorStyle='default'] 例如 crosshair
     */
    setCursorStyle: function (cursorStyle) {
        var proxy = this.proxy;
        proxy.setCursor && proxy.setCursor(cursorStyle);
    },

    /**
     * 事件分发代理
     *
     * @private
     * @param {Object} targetInfo {target, topTarget} 目标图形元素
     * @param {string} eventName 事件名称
     * @param {Object} event 事件对象
     */
    dispatchToElement: function (targetInfo, eventName, event) {
        targetInfo = targetInfo || {};
        var el = targetInfo.target;
        if (el && el.silent) {
            return;
        }
        var eventHandler = 'on' + eventName;
        var eventPacket = makeEventPacket(eventName, targetInfo, event);

        while (el) {
            el[eventHandler]
                && (eventPacket.cancelBubble = el[eventHandler].call(el, eventPacket));

            el.trigger(eventName, eventPacket);

            el = el.parent;

            if (eventPacket.cancelBubble) {
                break;
            }
        }

        if (!eventPacket.cancelBubble) {
            // 冒泡到顶级 zrender 对象
            this.trigger(eventName, eventPacket);
            // 分发事件到用户自定义层
            // 用户有可能在全局 click 事件中 dispose，所以需要判断下 painter 是否存在
            this.painter && this.painter.eachOtherLayer(function (layer) {
                if (typeof (layer[eventHandler]) === 'function') {
                    layer[eventHandler].call(layer, eventPacket);
                }
                if (layer.trigger) {
                    layer.trigger(eventName, eventPacket);
                }
            });
        }
    },

    /**
     * @private
     * @param {number} x
     * @param {number} y
     * @param {module:zrender/graphic/Displayable} exclude
     * @return {model:zrender/Element}
     * @method
     */
    findHover: function (x, y, exclude) {
        var list = this.storage.getDisplayList();
        var out = {x: x, y: y};

        for (var i = list.length - 1; i >= 0; i--) {
            var hoverCheckResult;
            if (list[i] !== exclude
                // getDisplayList may include ignored item in VML mode
                && !list[i].ignore
                && (hoverCheckResult = isHover(list[i], x, y))
            ) {
                !out.topTarget && (out.topTarget = list[i]);
                if (hoverCheckResult !== SILENT) {
                    out.target = list[i];
                    break;
                }
            }
        }

        return out;
    },

    processGesture: function (event, stage) {
        if (!this._gestureMgr) {
            this._gestureMgr = new GestureMgr();
        }
        var gestureMgr = this._gestureMgr;

        stage === 'start' && gestureMgr.clear();

        var gestureInfo = gestureMgr.recognize(
            event,
            this.findHover(event.zrX, event.zrY, null).target,
            this.proxy.dom
        );

        stage === 'end' && gestureMgr.clear();

        // Do not do any preventDefault here. Upper application do that if necessary.
        if (gestureInfo) {
            var type = gestureInfo.type;
            event.gestureEvent = type;

            this.dispatchToElement({target: gestureInfo.target}, type, gestureInfo.event);
        }
    }
};

// Common handlers
each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
    Handler.prototype[name] = function (event) {
        // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover
        var hovered = this.findHover(event.zrX, event.zrY);
        var hoveredTarget = hovered.target;

        if (name === 'mousedown') {
            this._downEl = hoveredTarget;
            this._downPoint = [event.zrX, event.zrY];
            // In case click triggered before mouseup
            this._upEl = hoveredTarget;
        }
        else if (name === 'mouseup') {
            this._upEl = hoveredTarget;
        }
        else if (name === 'click') {
            if (this._downEl !== this._upEl
                // Original click event is triggered on the whole canvas element,
                // including the case that `mousedown` - `mousemove` - `mouseup`,
                // which should be filtered, otherwise it will bring trouble to
                // pan and zoom.
                || !this._downPoint
                // Arbitrary value
                || dist(this._downPoint, [event.zrX, event.zrY]) > 4
            ) {
                return;
            }
            this._downPoint = null;
        }

        this.dispatchToElement(hovered, name, event);
    };
});

function isHover(displayable, x, y) {
    if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) {
        var el = displayable;
        var isSilent;
        while (el) {
            // If clipped by ancestor.
            // FIXME: If clipPath has neither stroke nor fill,
            // el.clipPath.contain(x, y) will always return false.
            if (el.clipPath && !el.clipPath.contain(x, y)) {
                return false;
            }
            if (el.silent) {
                isSilent = true;
            }
            el = el.parent;
        }
        return isSilent ? SILENT : true;
    }

    return false;
}

mixin(Handler, Eventful);
mixin(Handler, Draggable);

/**
 * 3x2矩阵操作类
 * @exports zrender/tool/matrix
 */

/* global Float32Array */

var ArrayCtor$1 = typeof Float32Array === 'undefined'
    ? Array
    : Float32Array;

/**
 * Create a identity matrix.
 * @return {Float32Array|Array.<number>}
 */
function create$1() {
    var out = new ArrayCtor$1(6);
    identity(out);

    return out;
}

/**
 * 设置矩阵为单位矩阵
 * @param {Float32Array|Array.<number>} out
 */
function identity(out) {
    out[0] = 1;
    out[1] = 0;
    out[2] = 0;
    out[3] = 1;
    out[4] = 0;
    out[5] = 0;
    return out;
}

/**
 * 复制矩阵
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} m
 */
function copy$1(out, m) {
    out[0] = m[0];
    out[1] = m[1];
    out[2] = m[2];
    out[3] = m[3];
    out[4] = m[4];
    out[5] = m[5];
    return out;
}

/**
 * 矩阵相乘
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} m1
 * @param {Float32Array|Array.<number>} m2
 */
function mul$1(out, m1, m2) {
    // Consider matrix.mul(m, m2, m);
    // where out is the same as m2.
    // So use temp variable to escape error.
    var out0 = m1[0] * m2[0] + m1[2] * m2[1];
    var out1 = m1[1] * m2[0] + m1[3] * m2[1];
    var out2 = m1[0] * m2[2] + m1[2] * m2[3];
    var out3 = m1[1] * m2[2] + m1[3] * m2[3];
    var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
    var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
    out[0] = out0;
    out[1] = out1;
    out[2] = out2;
    out[3] = out3;
    out[4] = out4;
    out[5] = out5;
    return out;
}

/**
 * 平移变换
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} a
 * @param {Float32Array|Array.<number>} v
 */
function translate(out, a, v) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4] + v[0];
    out[5] = a[5] + v[1];
    return out;
}

/**
 * 旋转变换
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} a
 * @param {number} rad
 */
function rotate(out, a, rad) {
    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];
    var st = Math.sin(rad);
    var ct = Math.cos(rad);

    out[0] = aa * ct + ab * st;
    out[1] = -aa * st + ab * ct;
    out[2] = ac * ct + ad * st;
    out[3] = -ac * st + ct * ad;
    out[4] = ct * atx + st * aty;
    out[5] = ct * aty - st * atx;
    return out;
}

/**
 * 缩放变换
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} a
 * @param {Float32Array|Array.<number>} v
 */
function scale$1(out, a, v) {
    var vx = v[0];
    var vy = v[1];
    out[0] = a[0] * vx;
    out[1] = a[1] * vy;
    out[2] = a[2] * vx;
    out[3] = a[3] * vy;
    out[4] = a[4] * vx;
    out[5] = a[5] * vy;
    return out;
}

/**
 * 求逆矩阵
 * @param {Float32Array|Array.<number>} out
 * @param {Float32Array|Array.<number>} a
 */
function invert(out, a) {

    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];

    var det = aa * ad - ab * ac;
    if (!det) {
        return null;
    }
    det = 1.0 / det;

    out[0] = ad * det;
    out[1] = -ab * det;
    out[2] = -ac * det;
    out[3] = aa * det;
    out[4] = (ac * aty - ad * atx) * det;
    out[5] = (ab * atx - aa * aty) * det;
    return out;
}

/**
 * Clone a new matrix.
 * @param {Float32Array|Array.<number>} a
 */
function clone$2(a) {
    var b = create$1();
    copy$1(b, a);
    return b;
}

var matrix = (Object.freeze || Object)({
	create: create$1,
	identity: identity,
	copy: copy$1,
	mul: mul$1,
	translate: translate,
	rotate: rotate,
	scale: scale$1,
	invert: invert,
	clone: clone$2
});

/**
 * 提供变换扩展
 * @module zrender/mixin/Transformable
 * @author pissang (https://www.github.com/pissang)
 */

var mIdentity = identity;

var EPSILON = 5e-5;

function isNotAroundZero(val) {
    return val > EPSILON || val < -EPSILON;
}

/**
 * @alias module:zrender/mixin/Transformable
 * @constructor
 */
var Transformable = function (opts) {
    opts = opts || {};
    // If there are no given position, rotation, scale
    if (!opts.position) {
        /**
         * 平移
         * @type {Array.<number>}
         * @default [0, 0]
         */
        this.position = [0, 0];
    }
    if (opts.rotation == null) {
        /**
         * 旋转
         * @type {Array.<number>}
         * @default 0
         */
        this.rotation = 0;
    }
    if (!opts.scale) {
        /**
         * 缩放
         * @type {Array.<number>}
         * @default [1, 1]
         */
        this.scale = [1, 1];
    }
    /**
     * 旋转和缩放的原点
     * @type {Array.<number>}
     * @default null
     */
    this.origin = this.origin || null;
};

var transformableProto = Transformable.prototype;
transformableProto.transform = null;

/**
 * 判断是否需要有坐标变换
 * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵
 */
transformableProto.needLocalTransform = function () {
    return isNotAroundZero(this.rotation)
        || isNotAroundZero(this.position[0])
        || isNotAroundZero(this.position[1])
        || isNotAroundZero(this.scale[0] - 1)
        || isNotAroundZero(this.scale[1] - 1);
};

var scaleTmp = [];
transformableProto.updateTransform = function () {
    var parent = this.parent;
    var parentHasTransform = parent && parent.transform;
    var needLocalTransform = this.needLocalTransform();

    var m = this.transform;
    if (!(needLocalTransform || parentHasTransform)) {
        m && mIdentity(m);
        return;
    }

    m = m || create$1();

    if (needLocalTransform) {
        this.getLocalTransform(m);
    }
    else {
        mIdentity(m);
    }

    // 应用父节点变换
    if (parentHasTransform) {
        if (needLocalTransform) {
            mul$1(m, parent.transform, m);
        }
        else {
            copy$1(m, parent.transform);
        }
    }
    // 保存这个变换矩阵
    this.transform = m;

    var globalScaleRatio = this.globalScaleRatio;
    if (globalScaleRatio != null && globalScaleRatio !== 1) {
        this.getGlobalScale(scaleTmp);
        var relX = scaleTmp[0] < 0 ? -1 : 1;
        var relY = scaleTmp[1] < 0 ? -1 : 1;
        var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0;
        var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0;

        m[0] *= sx;
        m[1] *= sx;
        m[2] *= sy;
        m[3] *= sy;
    }

    this.invTransform = this.invTransform || create$1();
    invert(this.invTransform, m);
};

transformableProto.getLocalTransform = function (m) {
    return Transformable.getLocalTransform(this, m);
};

/**
 * 将自己的transform应用到context上
 * @param {CanvasRenderingContext2D} ctx
 */
transformableProto.setTransform = function (ctx) {
    var m = this.transform;
    var dpr = ctx.dpr || 1;
    if (m) {
        ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
    }
    else {
        ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
};

transformableProto.restoreTransform = function (ctx) {
    var dpr = ctx.dpr || 1;
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
};

var tmpTransform = [];
var originTransform = create$1();

transformableProto.setLocalTransform = function (m) {
    if (!m) {
        // TODO return or set identity?
        return;
    }
    var sx = m[0] * m[0] + m[1] * m[1];
    var sy = m[2] * m[2] + m[3] * m[3];
    var position = this.position;
    var scale$$1 = this.scale;
    if (isNotAroundZero(sx - 1)) {
        sx = Math.sqrt(sx);
    }
    if (isNotAroundZero(sy - 1)) {
        sy = Math.sqrt(sy);
    }
    if (m[0] < 0) {
        sx = -sx;
    }
    if (m[3] < 0) {
        sy = -sy;
    }

    position[0] = m[4];
    position[1] = m[5];
    scale$$1[0] = sx;
    scale$$1[1] = sy;
    this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);
};
/**
 * 分解`transform`矩阵到`position`, `rotation`, `scale`
 */
transformableProto.decomposeTransform = function () {
    if (!this.transform) {
        return;
    }
    var parent = this.parent;
    var m = this.transform;
    if (parent && parent.transform) {
        // Get local transform and decompose them to position, scale, rotation
        mul$1(tmpTransform, parent.invTransform, m);
        m = tmpTransform;
    }
    var origin = this.origin;
    if (origin && (origin[0] || origin[1])) {
        originTransform[4] = origin[0];
        originTransform[5] = origin[1];
        mul$1(tmpTransform, m, originTransform);
        tmpTransform[4] -= origin[0];
        tmpTransform[5] -= origin[1];
        m = tmpTransform;
    }

    this.setLocalTransform(m);
};

/**
 * Get global scale
 * @return {Array.<number>}
 */
transformableProto.getGlobalScale = function (out) {
    var m = this.transform;
    out = out || [];
    if (!m) {
        out[0] = 1;
        out[1] = 1;
        return out;
    }
    out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
    out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]);
    if (m[0] < 0) {
        out[0] = -out[0];
    }
    if (m[3] < 0) {
        out[1] = -out[1];
    }
    return out;
};
/**
 * 变换坐标位置到 shape 的局部坐标空间
 * @method
 * @param {number} x
 * @param {number} y
 * @return {Array.<number>}
 */
transformableProto.transformCoordToLocal = function (x, y) {
    var v2 = [x, y];
    var invTransform = this.invTransform;
    if (invTransform) {
        applyTransform(v2, v2, invTransform);
    }
    return v2;
};

/**
 * 变换局部坐标位置到全局坐标空间
 * @method
 * @param {number} x
 * @param {number} y
 * @return {Array.<number>}
 */
transformableProto.transformCoordToGlobal = function (x, y) {
    var v2 = [x, y];
    var transform = this.transform;
    if (transform) {
        applyTransform(v2, v2, transform);
    }
    return v2;
};

/**
 * @static
 * @param {Object} target
 * @param {Array.<number>} target.origin
 * @param {number} target.rotation
 * @param {Array.<number>} target.position
 * @param {Array.<number>} [m]
 */
Transformable.getLocalTransform = function (target, m) {
    m = m || [];
    mIdentity(m);

    var origin = target.origin;
    var scale$$1 = target.scale || [1, 1];
    var rotation = target.rotation || 0;
    var position = target.position || [0, 0];

    if (origin) {
        // Translate to origin
        m[4] -= origin[0];
        m[5] -= origin[1];
    }
    scale$1(m, m, scale$$1);
    if (rotation) {
        rotate(m, m, rotation);
    }
    if (origin) {
        // Translate back from origin
        m[4] += origin[0];
        m[5] += origin[1];
    }

    m[4] += position[0];
    m[5] += position[1];

    return m;
};

/**
 * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js
 * @see http://sole.github.io/tween.js/examples/03_graphs.html
 * @exports zrender/animation/easing
 */
var easing = {
    /**
    * @param {number} k
    * @return {number}
    */
    linear: function (k) {
        return k;
    },

    /**
    * @param {number} k
    * @return {number}
    */
    quadraticIn: function (k) {
        return k * k;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quadraticOut: function (k) {
        return k * (2 - k);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quadraticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k;
        }
        return -0.5 * (--k * (k - 2) - 1);
    },

    // 三次方的缓动（t^3）
    /**
    * @param {number} k
    * @return {number}
    */
    cubicIn: function (k) {
        return k * k * k;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    cubicOut: function (k) {
        return --k * k * k + 1;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    cubicInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k;
        }
        return 0.5 * ((k -= 2) * k * k + 2);
    },

    // 四次方的缓动（t^4）
    /**
    * @param {number} k
    * @return {number}
    */
    quarticIn: function (k) {
        return k * k * k * k;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quarticOut: function (k) {
        return 1 - (--k * k * k * k);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quarticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k * k;
        }
        return -0.5 * ((k -= 2) * k * k * k - 2);
    },

    // 五次方的缓动（t^5）
    /**
    * @param {number} k
    * @return {number}
    */
    quinticIn: function (k) {
        return k * k * k * k * k;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quinticOut: function (k) {
        return --k * k * k * k * k + 1;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    quinticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k * k * k;
        }
        return 0.5 * ((k -= 2) * k * k * k * k + 2);
    },

    // 正弦曲线的缓动（sin(t)）
    /**
    * @param {number} k
    * @return {number}
    */
    sinusoidalIn: function (k) {
        return 1 - Math.cos(k * Math.PI / 2);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    sinusoidalOut: function (k) {
        return Math.sin(k * Math.PI / 2);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    sinusoidalInOut: function (k) {
        return 0.5 * (1 - Math.cos(Math.PI * k));
    },

    // 指数曲线的缓动（2^t）
    /**
    * @param {number} k
    * @return {number}
    */
    exponentialIn: function (k) {
        return k === 0 ? 0 : Math.pow(1024, k - 1);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    exponentialOut: function (k) {
        return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    exponentialInOut: function (k) {
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if ((k *= 2) < 1) {
            return 0.5 * Math.pow(1024, k - 1);
        }
        return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
    },

    // 圆形曲线的缓动（sqrt(1-t^2)）
    /**
    * @param {number} k
    * @return {number}
    */
    circularIn: function (k) {
        return 1 - Math.sqrt(1 - k * k);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    circularOut: function (k) {
        return Math.sqrt(1 - (--k * k));
    },
    /**
    * @param {number} k
    * @return {number}
    */
    circularInOut: function (k) {
        if ((k *= 2) < 1) {
            return -0.5 * (Math.sqrt(1 - k * k) - 1);
        }
        return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
    },

    // 创建类似于弹簧在停止前来回振荡的动画
    /**
    * @param {number} k
    * @return {number}
    */
    elasticIn: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        return -(a * Math.pow(2, 10 * (k -= 1))
                    * Math.sin((k - s) * (2 * Math.PI) / p));
    },
    /**
    * @param {number} k
    * @return {number}
    */
    elasticOut: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        return (a * Math.pow(2, -10 * k)
                    * Math.sin((k - s) * (2 * Math.PI) / p) + 1);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    elasticInOut: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        if ((k *= 2) < 1) {
            return -0.5 * (a * Math.pow(2, 10 * (k -= 1))
                * Math.sin((k - s) * (2 * Math.PI) / p));
        }
        return a * Math.pow(2, -10 * (k -= 1))
                * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;

    },

    // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动
    /**
    * @param {number} k
    * @return {number}
    */
    backIn: function (k) {
        var s = 1.70158;
        return k * k * ((s + 1) * k - s);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    backOut: function (k) {
        var s = 1.70158;
        return --k * k * ((s + 1) * k + s) + 1;
    },
    /**
    * @param {number} k
    * @return {number}
    */
    backInOut: function (k) {
        var s = 1.70158 * 1.525;
        if ((k *= 2) < 1) {
            return 0.5 * (k * k * ((s + 1) * k - s));
        }
        return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
    },

    // 创建弹跳效果
    /**
    * @param {number} k
    * @return {number}
    */
    bounceIn: function (k) {
        return 1 - easing.bounceOut(1 - k);
    },
    /**
    * @param {number} k
    * @return {number}
    */
    bounceOut: function (k) {
        if (k < (1 / 2.75)) {
            return 7.5625 * k * k;
        }
        else if (k < (2 / 2.75)) {
            return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
        }
        else if (k < (2.5 / 2.75)) {
            return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
        }
        else {
            return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
        }
    },
    /**
    * @param {number} k
    * @return {number}
    */
    bounceInOut: function (k) {
        if (k < 0.5) {
            return easing.bounceIn(k * 2) * 0.5;
        }
        return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5;
    }
};

/**
 * 动画主控制器
 * @config target 动画对象，可以是数组，如果是数组的话会批量分发onframe等事件
 * @config life(1000) 动画时长
 * @config delay(0) 动画延迟时间
 * @config loop(true)
 * @config gap(0) 循环的间隔时间
 * @config onframe
 * @config easing(optional)
 * @config ondestroy(optional)
 * @config onrestart(optional)
 *
 * TODO pause
 */

function Clip(options) {

    this._target = options.target;

    // 生命周期
    this._life = options.life || 1000;
    // 延时
    this._delay = options.delay || 0;
    // 开始时间
    // this._startTime = new Date().getTime() + this._delay;// 单位毫秒
    this._initialized = false;

    // 是否循环
    this.loop = options.loop == null ? false : options.loop;

    this.gap = options.gap || 0;

    this.easing = options.easing || 'Linear';

    this.onframe = options.onframe;
    this.ondestroy = options.ondestroy;
    this.onrestart = options.onrestart;

    this._pausedTime = 0;
    this._paused = false;
}

Clip.prototype = {

    constructor: Clip,

    step: function (globalTime, deltaTime) {
        // Set startTime on first step, or _startTime may has milleseconds different between clips
        // PENDING
        if (!this._initialized) {
            this._startTime = globalTime + this._delay;
            this._initialized = true;
        }

        if (this._paused) {
            this._pausedTime += deltaTime;
            return;
        }

        var percent = (globalTime - this._startTime - this._pausedTime) / this._life;

        // 还没开始
        if (percent < 0) {
            return;
        }

        percent = Math.min(percent, 1);

        var easing$$1 = this.easing;
        var easingFunc = typeof easing$$1 === 'string' ? easing[easing$$1] : easing$$1;
        var schedule = typeof easingFunc === 'function'
            ? easingFunc(percent)
            : percent;

        this.fire('frame', schedule);

        // 结束
        if (percent === 1) {
            if (this.loop) {
                this.restart(globalTime);
                // 重新开始周期
                // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件
                return 'restart';
            }

            // 动画完成将这个控制器标识为待删除
            // 在Animation.update中进行批量删除
            this._needsRemove = true;
            return 'destroy';
        }

        return null;
    },

    restart: function (globalTime) {
        var remainder = (globalTime - this._startTime - this._pausedTime) % this._life;
        this._startTime = globalTime - remainder + this.gap;
        this._pausedTime = 0;

        this._needsRemove = false;
    },

    fire: function (eventType, arg) {
        eventType = 'on' + eventType;
        if (this[eventType]) {
            this[eventType](this._target, arg);
        }
    },

    pause: function () {
        this._paused = true;
    },

    resume: function () {
        this._paused = false;
    }
};

// Simple LRU cache use doubly linked list
// @module zrender/core/LRU

/**
 * Simple double linked list. Compared with array, it has O(1) remove operation.
 * @constructor
 */
var LinkedList = function () {

    /**
     * @type {module:zrender/core/LRU~Entry}
     */
    this.head = null;

    /**
     * @type {module:zrender/core/LRU~Entry}
     */
    this.tail = null;

    this._len = 0;
};

var linkedListProto = LinkedList.prototype;
/**
 * Insert a new value at the tail
 * @param  {} val
 * @return {module:zrender/core/LRU~Entry}
 */
linkedListProto.insert = function (val) {
    var entry = new Entry(val);
    this.insertEntry(entry);
    return entry;
};

/**
 * Insert an entry at the tail
 * @param  {module:zrender/core/LRU~Entry} entry
 */
linkedListProto.insertEntry = function (entry) {
    if (!this.head) {
        this.head = this.tail = entry;
    }
    else {
        this.tail.next = entry;
        entry.prev = this.tail;
        entry.next = null;
        this.tail = entry;
    }
    this._len++;
};

/**
 * Remove entry.
 * @param  {module:zrender/core/LRU~Entry} entry
 */
linkedListProto.remove = function (entry) {
    var prev = entry.prev;
    var next = entry.next;
    if (prev) {
        prev.next = next;
    }
    else {
        // Is head
        this.head = next;
    }
    if (next) {
        next.prev = prev;
    }
    else {
        // Is tail
        this.tail = prev;
    }
    entry.next = entry.prev = null;
    this._len--;
};

/**
 * @return {number}
 */
linkedListProto.len = function () {
    return this._len;
};

/**
 * Clear list
 */
linkedListProto.clear = function () {
    this.head = this.tail = null;
    this._len = 0;
};

/**
 * @constructor
 * @param {} val
 */
var Entry = function (val) {
    /**
     * @type {}
     */
    this.value = val;

    /**
     * @type {module:zrender/core/LRU~Entry}
     */
    this.next;

    /**
     * @type {module:zrender/core/LRU~Entry}
     */
    this.prev;
};

/**
 * LRU Cache
 * @constructor
 * @alias module:zrender/core/LRU
 */
var LRU = function (maxSize) {

    this._list = new LinkedList();

    this._map = {};

    this._maxSize = maxSize || 10;

    this._lastRemovedEntry = null;
};

var LRUProto = LRU.prototype;

/**
 * @param  {string} key
 * @param  {} value
 * @return {} Removed value
 */
LRUProto.put = function (key, value) {
    var list = this._list;
    var map = this._map;
    var removed = null;
    if (map[key] == null) {
        var len = list.len();
        // Reuse last removed entry
        var entry = this._lastRemovedEntry;

        if (len >= this._maxSize && len > 0) {
            // Remove the least recently used
            var leastUsedEntry = list.head;
            list.remove(leastUsedEntry);
            delete map[leastUsedEntry.key];

            removed = leastUsedEntry.value;
            this._lastRemovedEntry = leastUsedEntry;
        }

        if (entry) {
            entry.value = value;
        }
        else {
            entry = new Entry(value);
        }
        entry.key = key;
        list.insertEntry(entry);
        map[key] = entry;
    }

    return removed;
};

/**
 * @param  {string} key
 * @return {}
 */
LRUProto.get = function (key) {
    var entry = this._map[key];
    var list = this._list;
    if (entry != null) {
        // Put the latest used entry in the tail
        if (entry !== list.tail) {
            list.remove(entry);
            list.insertEntry(entry);
        }

        return entry.value;
    }
};

/**
 * Clear the cache
 */
LRUProto.clear = function () {
    this._list.clear();
    this._map = {};
};

var kCSSColorTable = {
    'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1],
    'antiquewhite': [250, 235, 215, 1], 'aqua': [0, 255, 255, 1],
    'aquamarine': [127, 255, 212, 1], 'azure': [240, 255, 255, 1],
    'beige': [245, 245, 220, 1], 'bisque': [255, 228, 196, 1],
    'black': [0, 0, 0, 1], 'blanchedalmond': [255, 235, 205, 1],
    'blue': [0, 0, 255, 1], 'blueviolet': [138, 43, 226, 1],
    'brown': [165, 42, 42, 1], 'burlywood': [222, 184, 135, 1],
    'cadetblue': [95, 158, 160, 1], 'chartreuse': [127, 255, 0, 1],
    'chocolate': [210, 105, 30, 1], 'coral': [255, 127, 80, 1],
    'cornflowerblue': [100, 149, 237, 1], 'cornsilk': [255, 248, 220, 1],
    'crimson': [220, 20, 60, 1], 'cyan': [0, 255, 255, 1],
    'darkblue': [0, 0, 139, 1], 'darkcyan': [0, 139, 139, 1],
    'darkgoldenrod': [184, 134, 11, 1], 'darkgray': [169, 169, 169, 1],
    'darkgreen': [0, 100, 0, 1], 'darkgrey': [169, 169, 169, 1],
    'darkkhaki': [189, 183, 107, 1], 'darkmagenta': [139, 0, 139, 1],
    'darkolivegreen': [85, 107, 47, 1], 'darkorange': [255, 140, 0, 1],
    'darkorchid': [153, 50, 204, 1], 'darkred': [139, 0, 0, 1],
    'darksalmon': [233, 150, 122, 1], 'darkseagreen': [143, 188, 143, 1],
    'darkslateblue': [72, 61, 139, 1], 'darkslategray': [47, 79, 79, 1],
    'darkslategrey': [47, 79, 79, 1], 'darkturquoise': [0, 206, 209, 1],
    'darkviolet': [148, 0, 211, 1], 'deeppink': [255, 20, 147, 1],
    'deepskyblue': [0, 191, 255, 1], 'dimgray': [105, 105, 105, 1],
    'dimgrey': [105, 105, 105, 1], 'dodgerblue': [30, 144, 255, 1],
    'firebrick': [178, 34, 34, 1], 'floralwhite': [255, 250, 240, 1],
    'forestgreen': [34, 139, 34, 1], 'fuchsia': [255, 0, 255, 1],
    'gainsboro': [220, 220, 220, 1], 'ghostwhite': [248, 248, 255, 1],
    'gold': [255, 215, 0, 1], 'goldenrod': [218, 165, 32, 1],
    'gray': [128, 128, 128, 1], 'green': [0, 128, 0, 1],
    'greenyellow': [173, 255, 47, 1], 'grey': [128, 128, 128, 1],
    'honeydew': [240, 255, 240, 1], 'hotpink': [255, 105, 180, 1],
    'indianred': [205, 92, 92, 1], 'indigo': [75, 0, 130, 1],
    'ivory': [255, 255, 240, 1], 'khaki': [240, 230, 140, 1],
    'lavender': [230, 230, 250, 1], 'lavenderblush': [255, 240, 245, 1],
    'lawngreen': [124, 252, 0, 1], 'lemonchiffon': [255, 250, 205, 1],
    'lightblue': [173, 216, 230, 1], 'lightcoral': [240, 128, 128, 1],
    'lightcyan': [224, 255, 255, 1], 'lightgoldenrodyellow': [250, 250, 210, 1],
    'lightgray': [211, 211, 211, 1], 'lightgreen': [144, 238, 144, 1],
    'lightgrey': [211, 211, 211, 1], 'lightpink': [255, 182, 193, 1],
    'lightsalmon': [255, 160, 122, 1], 'lightseagreen': [32, 178, 170, 1],
    'lightskyblue': [135, 206, 250, 1], 'lightslategray': [119, 136, 153, 1],
    'lightslategrey': [119, 136, 153, 1], 'lightsteelblue': [176, 196, 222, 1],
    'lightyellow': [255, 255, 224, 1], 'lime': [0, 255, 0, 1],
    'limegreen': [50, 205, 50, 1], 'linen': [250, 240, 230, 1],
    'magenta': [255, 0, 255, 1], 'maroon': [128, 0, 0, 1],
    'mediumaquamarine': [102, 205, 170, 1], 'mediumblue': [0, 0, 205, 1],
    'mediumorchid': [186, 85, 211, 1], 'mediumpurple': [147, 112, 219, 1],
    'mediumseagreen': [60, 179, 113, 1], 'mediumslateblue': [123, 104, 238, 1],
    'mediumspringgreen': [0, 250, 154, 1], 'mediumturquoise': [72, 209, 204, 1],
    'mediumvioletred': [199, 21, 133, 1], 'midnightblue': [25, 25, 112, 1],
    'mintcream': [245, 255, 250, 1], 'mistyrose': [255, 228, 225, 1],
    'moccasin': [255, 228, 181, 1], 'navajowhite': [255, 222, 173, 1],
    'navy': [0, 0, 128, 1], 'oldlace': [253, 245, 230, 1],
    'olive': [128, 128, 0, 1], 'olivedrab': [107, 142, 35, 1],
    'orange': [255, 165, 0, 1], 'orangered': [255, 69, 0, 1],
    'orchid': [218, 112, 214, 1], 'palegoldenrod': [238, 232, 170, 1],
    'palegreen': [152, 251, 152, 1], 'paleturquoise': [175, 238, 238, 1],
    'palevioletred': [219, 112, 147, 1], 'papayawhip': [255, 239, 213, 1],
    'peachpuff': [255, 218, 185, 1], 'peru': [205, 133, 63, 1],
    'pink': [255, 192, 203, 1], 'plum': [221, 160, 221, 1],
    'powderblue': [176, 224, 230, 1], 'purple': [128, 0, 128, 1],
    'red': [255, 0, 0, 1], 'rosybrown': [188, 143, 143, 1],
    'royalblue': [65, 105, 225, 1], 'saddlebrown': [139, 69, 19, 1],
    'salmon': [250, 128, 114, 1], 'sandybrown': [244, 164, 96, 1],
    'seagreen': [46, 139, 87, 1], 'seashell': [255, 245, 238, 1],
    'sienna': [160, 82, 45, 1], 'silver': [192, 192, 192, 1],
    'skyblue': [135, 206, 235, 1], 'slateblue': [106, 90, 205, 1],
    'slategray': [112, 128, 144, 1], 'slategrey': [112, 128, 144, 1],
    'snow': [255, 250, 250, 1], 'springgreen': [0, 255, 127, 1],
    'steelblue': [70, 130, 180, 1], 'tan': [210, 180, 140, 1],
    'teal': [0, 128, 128, 1], 'thistle': [216, 191, 216, 1],
    'tomato': [255, 99, 71, 1], 'turquoise': [64, 224, 208, 1],
    'violet': [238, 130, 238, 1], 'wheat': [245, 222, 179, 1],
    'white': [255, 255, 255, 1], 'whitesmoke': [245, 245, 245, 1],
    'yellow': [255, 255, 0, 1], 'yellowgreen': [154, 205, 50, 1]
};

function clampCssByte(i) {  // Clamp to integer 0 .. 255.
    i = Math.round(i);  // Seems to be what Chrome does (vs truncation).
    return i < 0 ? 0 : i > 255 ? 255 : i;
}

function clampCssAngle(i) {  // Clamp to integer 0 .. 360.
    i = Math.round(i);  // Seems to be what Chrome does (vs truncation).
    return i < 0 ? 0 : i > 360 ? 360 : i;
}

function clampCssFloat(f) {  // Clamp to float 0.0 .. 1.0.
    return f < 0 ? 0 : f > 1 ? 1 : f;
}

function parseCssInt(str) {  // int or percentage.
    if (str.length && str.charAt(str.length - 1) === '%') {
        return clampCssByte(parseFloat(str) / 100 * 255);
    }
    return clampCssByte(parseInt(str, 10));
}

function parseCssFloat(str) {  // float or percentage.
    if (str.length && str.charAt(str.length - 1) === '%') {
        return clampCssFloat(parseFloat(str) / 100);
    }
    return clampCssFloat(parseFloat(str));
}

function cssHueToRgb(m1, m2, h) {
    if (h < 0) {
        h += 1;
    }
    else if (h > 1) {
        h -= 1;
    }

    if (h * 6 < 1) {
        return m1 + (m2 - m1) * h * 6;
    }
    if (h * 2 < 1) {
        return m2;
    }
    if (h * 3 < 2) {
        return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }
    return m1;
}

function lerpNumber(a, b, p) {
    return a + (b - a) * p;
}

function setRgba(out, r, g, b, a) {
    out[0] = r;
    out[1] = g;
    out[2] = b;
    out[3] = a;
    return out;
}
function copyRgba(out, a) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    return out;
}

var colorCache = new LRU(20);
var lastRemovedArr = null;

function putToCache(colorStr, rgbaArr) {
    // Reuse removed array
    if (lastRemovedArr) {
        copyRgba(lastRemovedArr, rgbaArr);
    }
    lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice()));
}

/**
 * @param {string} colorStr
 * @param {Array.<number>} out
 * @return {Array.<number>}
 * @memberOf module:zrender/util/color
 */
function parse(colorStr, rgbaArr) {
    if (!colorStr) {
        return;
    }
    rgbaArr = rgbaArr || [];

    var cached = colorCache.get(colorStr);
    if (cached) {
        return copyRgba(rgbaArr, cached);
    }

    // colorStr may be not string
    colorStr = colorStr + '';
    // Remove all whitespace, not compliant, but should just be more accepting.
    var str = colorStr.replace(/ /g, '').toLowerCase();

    // Color keywords (and transparent) lookup.
    if (str in kCSSColorTable) {
        copyRgba(rgbaArr, kCSSColorTable[str]);
        putToCache(colorStr, rgbaArr);
        return rgbaArr;
    }

    // #abc and #abc123 syntax.
    if (str.charAt(0) === '#') {
        if (str.length === 4) {
            var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.
            if (!(iv >= 0 && iv <= 0xfff)) {
                setRgba(rgbaArr, 0, 0, 0, 1);
                return;  // Covers NaN.
            }
            setRgba(rgbaArr,
                ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
                (iv & 0xf0) | ((iv & 0xf0) >> 4),
                (iv & 0xf) | ((iv & 0xf) << 4),
                1
            );
            putToCache(colorStr, rgbaArr);
            return rgbaArr;
        }
        else if (str.length === 7) {
            var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.
            if (!(iv >= 0 && iv <= 0xffffff)) {
                setRgba(rgbaArr, 0, 0, 0, 1);
                return;  // Covers NaN.
            }
            setRgba(rgbaArr,
                (iv & 0xff0000) >> 16,
                (iv & 0xff00) >> 8,
                iv & 0xff,
                1
            );
            putToCache(colorStr, rgbaArr);
            return rgbaArr;
        }

        return;
    }
    var op = str.indexOf('(');
    var ep = str.indexOf(')');
    if (op !== -1 && ep + 1 === str.length) {
        var fname = str.substr(0, op);
        var params = str.substr(op + 1, ep - (op + 1)).split(',');
        var alpha = 1;  // To allow case fallthrough.
        switch (fname) {
            case 'rgba':
                if (params.length !== 4) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                alpha = parseCssFloat(params.pop()); // jshint ignore:line
            // Fall through.
            case 'rgb':
                if (params.length !== 3) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                setRgba(rgbaArr,
                    parseCssInt(params[0]),
                    parseCssInt(params[1]),
                    parseCssInt(params[2]),
                    alpha
                );
                putToCache(colorStr, rgbaArr);
                return rgbaArr;
            case 'hsla':
                if (params.length !== 4) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                params[3] = parseCssFloat(params[3]);
                hsla2rgba(params, rgbaArr);
                putToCache(colorStr, rgbaArr);
                return rgbaArr;
            case 'hsl':
                if (params.length !== 3) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                hsla2rgba(params, rgbaArr);
                putToCache(colorStr, rgbaArr);
                return rgbaArr;
            default:
                return;
        }
    }

    setRgba(rgbaArr, 0, 0, 0, 1);
    return;
}

/**
 * @param {Array.<number>} hsla
 * @param {Array.<number>} rgba
 * @return {Array.<number>} rgba
 */
function hsla2rgba(hsla, rgba) {
    var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360;  // 0 .. 1
    // NOTE(deanm): According to the CSS spec s/l should only be
    // percentages, but we don't bother and let float or percentage.
    var s = parseCssFloat(hsla[1]);
    var l = parseCssFloat(hsla[2]);
    var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
    var m1 = l * 2 - m2;

    rgba = rgba || [];
    setRgba(rgba,
        clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255),
        clampCssByte(cssHueToRgb(m1, m2, h) * 255),
        clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255),
        1
    );

    if (hsla.length === 4) {
        rgba[3] = hsla[3];
    }

    return rgba;
}

/**
 * @param {Array.<number>} rgba
 * @return {Array.<number>} hsla
 */
function rgba2hsla(rgba) {
    if (!rgba) {
        return;
    }

    // RGB from 0 to 255
    var R = rgba[0] / 255;
    var G = rgba[1] / 255;
    var B = rgba[2] / 255;

    var vMin = Math.min(R, G, B); // Min. value of RGB
    var vMax = Math.max(R, G, B); // Max. value of RGB
    var delta = vMax - vMin; // Delta RGB value

    var L = (vMax + vMin) / 2;
    var H;
    var S;
    // HSL results from 0 to 1
    if (delta === 0) {
        H = 0;
        S = 0;
    }
    else {
        if (L < 0.5) {
            S = delta / (vMax + vMin);
        }
        else {
            S = delta / (2 - vMax - vMin);
        }

        var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta;
        var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta;
        var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta;

        if (R === vMax) {
            H = deltaB - deltaG;
        }
        else if (G === vMax) {
            H = (1 / 3) + deltaR - deltaB;
        }
        else if (B === vMax) {
            H = (2 / 3) + deltaG - deltaR;
        }

        if (H < 0) {
            H += 1;
        }

        if (H > 1) {
            H -= 1;
        }
    }

    var hsla = [H * 360, S, L];

    if (rgba[3] != null) {
        hsla.push(rgba[3]);
    }

    return hsla;
}

/**
 * @param {string} color
 * @param {number} level
 * @return {string}
 * @memberOf module:zrender/util/color
 */
function lift(color, level) {
    var colorArr = parse(color);
    if (colorArr) {
        for (var i = 0; i < 3; i++) {
            if (level < 0) {
                colorArr[i] = colorArr[i] * (1 - level) | 0;
            }
            else {
                colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0;
            }
            if (colorArr[i] > 255) {
                colorArr[i] = 255;
            }
            else if (color[i] < 0) {
                colorArr[i] = 0;
            }
        }
        return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
    }
}

/**
 * @param {string} color
 * @return {string}
 * @memberOf module:zrender/util/color
 */
function toHex(color) {
    var colorArr = parse(color);
    if (colorArr) {
        return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1);
    }
}

/**
 * Map value to color. Faster than lerp methods because color is represented by rgba array.
 * @param {number} normalizedValue A float between 0 and 1.
 * @param {Array.<Array.<number>>} colors List of rgba color array
 * @param {Array.<number>} [out] Mapped gba color array
 * @return {Array.<number>} will be null/undefined if input illegal.
 */
function fastLerp(normalizedValue, colors, out) {
    if (!(colors && colors.length)
        || !(normalizedValue >= 0 && normalizedValue <= 1)
    ) {
        return;
    }

    out = out || [];

    var value = normalizedValue * (colors.length - 1);
    var leftIndex = Math.floor(value);
    var rightIndex = Math.ceil(value);
    var leftColor = colors[leftIndex];
    var rightColor = colors[rightIndex];
    var dv = value - leftIndex;
    out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv));
    out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv));
    out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv));
    out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv));

    return out;
}

/**
 * @deprecated
 */
var fastMapToColor = fastLerp;

/**
 * @param {number} normalizedValue A float between 0 and 1.
 * @param {Array.<string>} colors Color list.
 * @param {boolean=} fullOutput Default false.
 * @return {(string|Object)} Result color. If fullOutput,
 *                           return {color: ..., leftIndex: ..., rightIndex: ..., value: ...},
 * @memberOf module:zrender/util/color
 */
function lerp$1(normalizedValue, colors, fullOutput) {
    if (!(colors && colors.length)
        || !(normalizedValue >= 0 && normalizedValue <= 1)
    ) {
        return;
    }

    var value = normalizedValue * (colors.length - 1);
    var leftIndex = Math.floor(value);
    var rightIndex = Math.ceil(value);
    var leftColor = parse(colors[leftIndex]);
    var rightColor = parse(colors[rightIndex]);
    var dv = value - leftIndex;

    var color = stringify(
        [
            clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)),
            clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)),
            clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)),
            clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv))
        ],
        'rgba'
    );

    return fullOutput
        ? {
            color: color,
            leftIndex: leftIndex,
            rightIndex: rightIndex,
            value: value
        }
        : color;
}

/**
 * @deprecated
 */
var mapToColor = lerp$1;

/**
 * @param {string} color
 * @param {number=} h 0 ~ 360, ignore when null.
 * @param {number=} s 0 ~ 1, ignore when null.
 * @param {number=} l 0 ~ 1, ignore when null.
 * @return {string} Color string in rgba format.
 * @memberOf module:zrender/util/color
 */
function modifyHSL(color, h, s, l) {
    color = parse(color);

    if (color) {
        color = rgba2hsla(color);
        h != null && (color[0] = clampCssAngle(h));
        s != null && (color[1] = parseCssFloat(s));
        l != null && (color[2] = parseCssFloat(l));

        return stringify(hsla2rgba(color), 'rgba');
    }
}

/**
 * @param {string} color
 * @param {number=} alpha 0 ~ 1
 * @return {string} Color string in rgba format.
 * @memberOf module:zrender/util/color
 */
function modifyAlpha(color, alpha) {
    color = parse(color);

    if (color && alpha != null) {
        color[3] = clampCssFloat(alpha);
        return stringify(color, 'rgba');
    }
}

/**
 * @param {Array.<number>} arrColor like [12,33,44,0.4]
 * @param {string} type 'rgba', 'hsva', ...
 * @return {string} Result color. (If input illegal, return undefined).
 */
function stringify(arrColor, type) {
    if (!arrColor || !arrColor.length) {
        return;
    }
    var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];
    if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
        colorStr += ',' + arrColor[3];
    }
    return type + '(' + colorStr + ')';
}


var color = (Object.freeze || Object)({
	parse: parse,
	lift: lift,
	toHex: toHex,
	fastLerp: fastLerp,
	fastMapToColor: fastMapToColor,
	lerp: lerp$1,
	mapToColor: mapToColor,
	modifyHSL: modifyHSL,
	modifyAlpha: modifyAlpha,
	stringify: stringify
});

/**
 * @module echarts/animation/Animator
 */

var arraySlice = Array.prototype.slice;

function defaultGetter(target, key) {
    return target[key];
}

function defaultSetter(target, key, value) {
    target[key] = value;
}

/**
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} percent
 * @return {number}
 */
function interpolateNumber(p0, p1, percent) {
    return (p1 - p0) * percent + p0;
}

/**
 * @param  {string} p0
 * @param  {string} p1
 * @param  {number} percent
 * @return {string}
 */
function interpolateString(p0, p1, percent) {
    return percent > 0.5 ? p1 : p0;
}

/**
 * @param  {Array} p0
 * @param  {Array} p1
 * @param  {number} percent
 * @param  {Array} out
 * @param  {number} arrDim
 */
function interpolateArray(p0, p1, percent, out, arrDim) {
    var len = p0.length;
    if (arrDim === 1) {
        for (var i = 0; i < len; i++) {
            out[i] = interpolateNumber(p0[i], p1[i], percent);
        }
    }
    else {
        var len2 = len && p0[0].length;
        for (var i = 0; i < len; i++) {
            for (var j = 0; j < len2; j++) {
                out[i][j] = interpolateNumber(
                    p0[i][j], p1[i][j], percent
                );
            }
        }
    }
}

// arr0 is source array, arr1 is target array.
// Do some preprocess to avoid error happened when interpolating from arr0 to arr1
function fillArr(arr0, arr1, arrDim) {
    var arr0Len = arr0.length;
    var arr1Len = arr1.length;
    if (arr0Len !== arr1Len) {
        // FIXME Not work for TypedArray
        var isPreviousLarger = arr0Len > arr1Len;
        if (isPreviousLarger) {
            // Cut the previous
            arr0.length = arr1Len;
        }
        else {
            // Fill the previous
            for (var i = arr0Len; i < arr1Len; i++) {
                arr0.push(
                    arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])
                );
            }
        }
    }
    // Handling NaN value
    var len2 = arr0[0] && arr0[0].length;
    for (var i = 0; i < arr0.length; i++) {
        if (arrDim === 1) {
            if (isNaN(arr0[i])) {
                arr0[i] = arr1[i];
            }
        }
        else {
            for (var j = 0; j < len2; j++) {
                if (isNaN(arr0[i][j])) {
                    arr0[i][j] = arr1[i][j];
                }
            }
        }
    }
}

/**
 * @param  {Array} arr0
 * @param  {Array} arr1
 * @param  {number} arrDim
 * @return {boolean}
 */
function isArraySame(arr0, arr1, arrDim) {
    if (arr0 === arr1) {
        return true;
    }
    var len = arr0.length;
    if (len !== arr1.length) {
        return false;
    }
    if (arrDim === 1) {
        for (var i = 0; i < len; i++) {
            if (arr0[i] !== arr1[i]) {
                return false;
            }
        }
    }
    else {
        var len2 = arr0[0].length;
        for (var i = 0; i < len; i++) {
            for (var j = 0; j < len2; j++) {
                if (arr0[i][j] !== arr1[i][j]) {
                    return false;
                }
            }
        }
    }
    return true;
}

/**
 * Catmull Rom interpolate array
 * @param  {Array} p0
 * @param  {Array} p1
 * @param  {Array} p2
 * @param  {Array} p3
 * @param  {number} t
 * @param  {number} t2
 * @param  {number} t3
 * @param  {Array} out
 * @param  {number} arrDim
 */
function catmullRomInterpolateArray(
    p0, p1, p2, p3, t, t2, t3, out, arrDim
) {
    var len = p0.length;
    if (arrDim === 1) {
        for (var i = 0; i < len; i++) {
            out[i] = catmullRomInterpolate(
                p0[i], p1[i], p2[i], p3[i], t, t2, t3
            );
        }
    }
    else {
        var len2 = p0[0].length;
        for (var i = 0; i < len; i++) {
            for (var j = 0; j < len2; j++) {
                out[i][j] = catmullRomInterpolate(
                    p0[i][j], p1[i][j], p2[i][j], p3[i][j],
                    t, t2, t3
                );
            }
        }
    }
}

/**
 * Catmull Rom interpolate number
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {number} t
 * @param  {number} t2
 * @param  {number} t3
 * @return {number}
 */
function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
    var v0 = (p2 - p0) * 0.5;
    var v1 = (p3 - p1) * 0.5;
    return (2 * (p1 - p2) + v0 + v1) * t3
            + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
            + v0 * t + p1;
}

function cloneValue(value) {
    if (isArrayLike(value)) {
        var len = value.length;
        if (isArrayLike(value[0])) {
            var ret = [];
            for (var i = 0; i < len; i++) {
                ret.push(arraySlice.call(value[i]));
            }
            return ret;
        }

        return arraySlice.call(value);
    }

    return value;
}

function rgba2String(rgba) {
    rgba[0] = Math.floor(rgba[0]);
    rgba[1] = Math.floor(rgba[1]);
    rgba[2] = Math.floor(rgba[2]);

    return 'rgba(' + rgba.join(',') + ')';
}

function getArrayDim(keyframes) {
    var lastValue = keyframes[keyframes.length - 1].value;
    return isArrayLike(lastValue && lastValue[0]) ? 2 : 1;
}

function createTrackClip(animator, easing, oneTrackDone, keyframes, propName, forceAnimate) {
    var getter = animator._getter;
    var setter = animator._setter;
    var useSpline = easing === 'spline';

    var trackLen = keyframes.length;
    if (!trackLen) {
        return;
    }
    // Guess data type
    var firstVal = keyframes[0].value;
    var isValueArray = isArrayLike(firstVal);
    var isValueColor = false;
    var isValueString = false;

    // For vertices morphing
    var arrDim = isValueArray ? getArrayDim(keyframes) : 0;

    var trackMaxTime;
    // Sort keyframe as ascending
    keyframes.sort(function (a, b) {
        return a.time - b.time;
    });

    trackMaxTime = keyframes[trackLen - 1].time;
    // Percents of each keyframe
    var kfPercents = [];
    // Value of each keyframe
    var kfValues = [];
    var prevValue = keyframes[0].value;
    var isAllValueEqual = true;
    for (var i = 0; i < trackLen; i++) {
        kfPercents.push(keyframes[i].time / trackMaxTime);
        // Assume value is a color when it is a string
        var value = keyframes[i].value;

        // Check if value is equal, deep check if value is array
        if (!((isValueArray && isArraySame(value, prevValue, arrDim))
            || (!isValueArray && value === prevValue))) {
            isAllValueEqual = false;
        }
        prevValue = value;

        // Try converting a string to a color array
        if (typeof value === 'string') {
            var colorArray = parse(value);
            if (colorArray) {
                value = colorArray;
                isValueColor = true;
            }
            else {
                isValueString = true;
            }
        }
        kfValues.push(value);
    }
    if (!forceAnimate && isAllValueEqual) {
        return;
    }

    var lastValue = kfValues[trackLen - 1];
    // Polyfill array and NaN value
    for (var i = 0; i < trackLen - 1; i++) {
        if (isValueArray) {
            fillArr(kfValues[i], lastValue, arrDim);
        }
        else {
            if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) {
                kfValues[i] = lastValue;
            }
        }
    }
    isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim);

    // Cache the key of last frame to speed up when
    // animation playback is sequency
    var lastFrame = 0;
    var lastFramePercent = 0;
    var start;
    var w;
    var p0;
    var p1;
    var p2;
    var p3;

    if (isValueColor) {
        var rgba = [0, 0, 0, 0];
    }

    var onframe = function (target, percent) {
        // Find the range keyframes
        // kf1-----kf2---------current--------kf3
        // find kf2 and kf3 and do interpolation
        var frame;
        // In the easing function like elasticOut, percent may less than 0
        if (percent < 0) {
            frame = 0;
        }
        else if (percent < lastFramePercent) {
            // Start from next key
            // PENDING start from lastFrame ?
            start = Math.min(lastFrame + 1, trackLen - 1);
            for (frame = start; frame >= 0; frame--) {
                if (kfPercents[frame] <= percent) {
                    break;
                }
            }
            // PENDING really need to do this ?
            frame = Math.min(frame, trackLen - 2);
        }
        else {
            for (frame = lastFrame; frame < trackLen; frame++) {
                if (kfPercents[frame] > percent) {
                    break;
                }
            }
            frame = Math.min(frame - 1, trackLen - 2);
        }
        lastFrame = frame;
        lastFramePercent = percent;

        var range = (kfPercents[frame + 1] - kfPercents[frame]);
        if (range === 0) {
            return;
        }
        else {
            w = (percent - kfPercents[frame]) / range;
        }
        if (useSpline) {
            p1 = kfValues[frame];
            p0 = kfValues[frame === 0 ? frame : frame - 1];
            p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1];
            p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2];
            if (isValueArray) {
                catmullRomInterpolateArray(
                    p0, p1, p2, p3, w, w * w, w * w * w,
                    getter(target, propName),
                    arrDim
                );
            }
            else {
                var value;
                if (isValueColor) {
                    value = catmullRomInterpolateArray(
                        p0, p1, p2, p3, w, w * w, w * w * w,
                        rgba, 1
                    );
                    value = rgba2String(rgba);
                }
                else if (isValueString) {
                    // String is step(0.5)
                    return interpolateString(p1, p2, w);
                }
                else {
                    value = catmullRomInterpolate(
                        p0, p1, p2, p3, w, w * w, w * w * w
                    );
                }
                setter(
                    target,
                    propName,
                    value
                );
            }
        }
        else {
            if (isValueArray) {
                interpolateArray(
                    kfValues[frame], kfValues[frame + 1], w,
                    getter(target, propName),
                    arrDim
                );
            }
            else {
                var value;
                if (isValueColor) {
                    interpolateArray(
                        kfValues[frame], kfValues[frame + 1], w,
                        rgba, 1
                    );
                    value = rgba2String(rgba);
                }
                else if (isValueString) {
                    // String is step(0.5)
                    return interpolateString(kfValues[frame], kfValues[frame + 1], w);
                }
                else {
                    value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w);
                }
                setter(
                    target,
                    propName,
                    value
                );
            }
        }
    };

    var clip = new Clip({
        target: animator._target,
        life: trackMaxTime,
        loop: animator._loop,
        delay: animator._delay,
        onframe: onframe,
        ondestroy: oneTrackDone
    });

    if (easing && easing !== 'spline') {
        clip.easing = easing;
    }

    return clip;
}

/**
 * @alias module:zrender/animation/Animator
 * @constructor
 * @param {Object} target
 * @param {boolean} loop
 * @param {Function} getter
 * @param {Function} setter
 */
var Animator = function (target, loop, getter, setter) {
    this._tracks = {};
    this._target = target;

    this._loop = loop || false;

    this._getter = getter || defaultGetter;
    this._setter = setter || defaultSetter;

    this._clipCount = 0;

    this._delay = 0;

    this._doneList = [];

    this._onframeList = [];

    this._clipList = [];
};

Animator.prototype = {
    /**
     * 设置动画关键帧
     * @param  {number} time 关键帧时间，单位是ms
     * @param  {Object} props 关键帧的属性值，key-value表示
     * @return {module:zrender/animation/Animator}
     */
    when: function (time /* ms */, props) {
        var tracks = this._tracks;
        for (var propName in props) {
            if (!props.hasOwnProperty(propName)) {
                continue;
            }

            if (!tracks[propName]) {
                tracks[propName] = [];
                // Invalid value
                var value = this._getter(this._target, propName);
                if (value == null) {
                    // zrLog('Invalid property ' + propName);
                    continue;
                }
                // If time is 0
                //  Then props is given initialize value
                // Else
                //  Initialize value from current prop value
                if (time !== 0) {
                    tracks[propName].push({
                        time: 0,
                        value: cloneValue(value)
                    });
                }
            }
            tracks[propName].push({
                time: time,
                value: props[propName]
            });
        }
        return this;
    },
    /**
     * 添加动画每一帧的回调函数
     * @param  {Function} callback
     * @return {module:zrender/animation/Animator}
     */
    during: function (callback) {
        this._onframeList.push(callback);
        return this;
    },

    pause: function () {
        for (var i = 0; i < this._clipList.length; i++) {
            this._clipList[i].pause();
        }
        this._paused = true;
    },

    resume: function () {
        for (var i = 0; i < this._clipList.length; i++) {
            this._clipList[i].resume();
        }
        this._paused = false;
    },

    isPaused: function () {
        return !!this._paused;
    },

    _doneCallback: function () {
        // Clear all tracks
        this._tracks = {};
        // Clear all clips
        this._clipList.length = 0;

        var doneList = this._doneList;
        var len = doneList.length;
        for (var i = 0; i < len; i++) {
            doneList[i].call(this);
        }
    },
    /**
     * 开始执行动画
     * @param  {string|Function} [easing]
     *         动画缓动函数，详见{@link module:zrender/animation/easing}
     * @param  {boolean} forceAnimate
     * @return {module:zrender/animation/Animator}
     */
    start: function (easing, forceAnimate) {

        var self = this;
        var clipCount = 0;

        var oneTrackDone = function () {
            clipCount--;
            if (!clipCount) {
                self._doneCallback();
            }
        };

        var lastClip;
        for (var propName in this._tracks) {
            if (!this._tracks.hasOwnProperty(propName)) {
                continue;
            }
            var clip = createTrackClip(
                this, easing, oneTrackDone,
                this._tracks[propName], propName, forceAnimate
            );
            if (clip) {
                this._clipList.push(clip);
                clipCount++;

                // If start after added to animation
                if (this.animation) {
                    this.animation.addClip(clip);
                }

                lastClip = clip;
            }
        }

        // Add during callback on the last clip
        if (lastClip) {
            var oldOnFrame = lastClip.onframe;
            lastClip.onframe = function (target, percent) {
                oldOnFrame(target, percent);

                for (var i = 0; i < self._onframeList.length; i++) {
                    self._onframeList[i](target, percent);
                }
            };
        }

        // This optimization will help the case that in the upper application
        // the view may be refreshed frequently, where animation will be
        // called repeatly but nothing changed.
        if (!clipCount) {
            this._doneCallback();
        }
        return this;
    },
    /**
     * 停止动画
     * @param {boolean} forwardToLast If move to last frame before stop
     */
    stop: function (forwardToLast) {
        var clipList = this._clipList;
        var animation = this.animation;
        for (var i = 0; i < clipList.length; i++) {
            var clip = clipList[i];
            if (forwardToLast) {
                // Move to last frame before stop
                clip.onframe(this._target, 1);
            }
            animation && animation.removeClip(clip);
        }
        clipList.length = 0;
    },
    /**
     * 设置动画延迟开始的时间
     * @param  {number} time 单位ms
     * @return {module:zrender/animation/Animator}
     */
    delay: function (time) {
        this._delay = time;
        return this;
    },
    /**
     * 添加动画结束的回调
     * @param  {Function} cb
     * @return {module:zrender/animation/Animator}
     */
    done: function (cb) {
        if (cb) {
            this._doneList.push(cb);
        }
        return this;
    },

    /**
     * @return {Array.<module:zrender/animation/Clip>}
     */
    getClips: function () {
        return this._clipList;
    }
};

var dpr = 1;

// If in browser environment
if (typeof window !== 'undefined') {
    dpr = Math.max(window.devicePixelRatio || 1, 1);
}

/**
 * config默认配置项
 * @exports zrender/config
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 */

/**
 * Debug log mode:
 * 0: Do nothing, for release.
 * 1: console.error, for debug.
 */
var debugMode = 0;

// retina 屏幕优化
var devicePixelRatio = dpr;

var logError = function () {
};

if (debugMode === 1) {
    logError = console.error;
}

var logError$1 = logError;

/**
 * @alias modue:zrender/mixin/Animatable
 * @constructor
 */
var Animatable = function () {

    /**
     * @type {Array.<module:zrender/animation/Animator>}
     * @readOnly
     */
    this.animators = [];
};

Animatable.prototype = {

    constructor: Animatable,

    /**
     * 动画
     *
     * @param {string} path The path to fetch value from object, like 'a.b.c'.
     * @param {boolean} [loop] Whether to loop animation.
     * @return {module:zrender/animation/Animator}
     * @example:
     *     el.animate('style', false)
     *         .when(1000, {x: 10} )
     *         .done(function(){ // Animation done })
     *         .start()
     */
    animate: function (path, loop) {
        var target;
        var animatingShape = false;
        var el = this;
        var zr = this.__zr;
        if (path) {
            var pathSplitted = path.split('.');
            var prop = el;
            // If animating shape
            animatingShape = pathSplitted[0] === 'shape';
            for (var i = 0, l = pathSplitted.length; i < l; i++) {
                if (!prop) {
                    continue;
                }
                prop = prop[pathSplitted[i]];
            }
            if (prop) {
                target = prop;
            }
        }
        else {
            target = el;
        }

        if (!target) {
            logError$1(
                'Property "'
                + path
                + '" is not existed in element '
                + el.id
            );
            return;
        }

        var animators = el.animators;

        var animator = new Animator(target, loop);

        animator.during(function (target) {
            el.dirty(animatingShape);
        })
        .done(function () {
            // FIXME Animator will not be removed if use `Animator#stop` to stop animation
            animators.splice(indexOf(animators, animator), 1);
        });

        animators.push(animator);

        // If animate after added to the zrender
        if (zr) {
            zr.animation.addAnimator(animator);
        }

        return animator;
    },

    /**
     * 停止动画
     * @param {boolean} forwardToLast If move to last frame before stop
     */
    stopAnimation: function (forwardToLast) {
        var animators = this.animators;
        var len = animators.length;
        for (var i = 0; i < len; i++) {
            animators[i].stop(forwardToLast);
        }
        animators.length = 0;

        return this;
    },

    /**
     * Caution: this method will stop previous animation.
     * So do not use this method to one element twice before
     * animation starts, unless you know what you are doing.
     * @param {Object} target
     * @param {number} [time=500] Time in ms
     * @param {string} [easing='linear']
     * @param {number} [delay=0]
     * @param {Function} [callback]
     * @param {Function} [forceAnimate] Prevent stop animation and callback
     *        immediently when target values are the same as current values.
     *
     * @example
     *  // Animate position
     *  el.animateTo({
     *      position: [10, 10]
     *  }, function () { // done })
     *
     *  // Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing
     *  el.animateTo({
     *      shape: {
     *          width: 500
     *      },
     *      style: {
     *          fill: 'red'
     *      }
     *      position: [10, 10]
     *  }, 100, 100, 'cubicOut', function () { // done })
     */
    // TODO Return animation key
    animateTo: function (target, time, delay, easing, callback, forceAnimate) {
        animateTo(this, target, time, delay, easing, callback, forceAnimate);
    },

    /**
     * Animate from the target state to current state.
     * The params and the return value are the same as `this.animateTo`.
     */
    animateFrom: function (target, time, delay, easing, callback, forceAnimate) {
        animateTo(this, target, time, delay, easing, callback, forceAnimate, true);
    }
};

function animateTo(animatable, target, time, delay, easing, callback, forceAnimate, reverse) {
    // animateTo(target, time, easing, callback);
    if (isString(delay)) {
        callback = easing;
        easing = delay;
        delay = 0;
    }
    // animateTo(target, time, delay, callback);
    else if (isFunction$1(easing)) {
        callback = easing;
        easing = 'linear';
        delay = 0;
    }
    // animateTo(target, time, callback);
    else if (isFunction$1(delay)) {
        callback = delay;
        delay = 0;
    }
    // animateTo(target, callback)
    else if (isFunction$1(time)) {
        callback = time;
        time = 500;
    }
    // animateTo(target)
    else if (!time) {
        time = 500;
    }
    // Stop all previous animations
    animatable.stopAnimation();
    animateToShallow(animatable, '', animatable, target, time, delay, reverse);

    // Animators may be removed immediately after start
    // if there is nothing to animate
    var animators = animatable.animators.slice();
    var count = animators.length;
    function done() {
        count--;
        if (!count) {
            callback && callback();
        }
    }

    // No animators. This should be checked before animators[i].start(),
    // because 'done' may be executed immediately if no need to animate.
    if (!count) {
        callback && callback();
    }
    // Start after all animators created
    // Incase any animator is done immediately when all animation properties are not changed
    for (var i = 0; i < animators.length; i++) {
        animators[i]
            .done(done)
            .start(easing, forceAnimate);
    }
}

/**
 * @param {string} path=''
 * @param {Object} source=animatable
 * @param {Object} target
 * @param {number} [time=500]
 * @param {number} [delay=0]
 * @param {boolean} [reverse] If `true`, animate
 *        from the `target` to current state.
 *
 * @example
 *  // Animate position
 *  el._animateToShallow({
 *      position: [10, 10]
 *  })
 *
 *  // Animate shape, style and position in 100ms, delayed 100ms
 *  el._animateToShallow({
 *      shape: {
 *          width: 500
 *      },
 *      style: {
 *          fill: 'red'
 *      }
 *      position: [10, 10]
 *  }, 100, 100)
 */
function animateToShallow(animatable, path, source, target, time, delay, reverse) {
    var objShallow = {};
    var propertyCount = 0;
    for (var name in target) {
        if (!target.hasOwnProperty(name)) {
            continue;
        }

        if (source[name] != null) {
            if (isObject$1(target[name]) && !isArrayLike(target[name])) {
                animateToShallow(
                    animatable,
                    path ? path + '.' + name : name,
                    source[name],
                    target[name],
                    time,
                    delay,
                    reverse
                );
            }
            else {
                if (reverse) {
                    objShallow[name] = source[name];
                    setAttrByPath(animatable, path, name, target[name]);
                }
                else {
                    objShallow[name] = target[name];
                }
                propertyCount++;
            }
        }
        else if (target[name] != null && !reverse) {
            setAttrByPath(animatable, path, name, target[name]);
        }
    }

    if (propertyCount > 0) {
        animatable.animate(path, false)
            .when(time == null ? 500 : time, objShallow)
            .delay(delay || 0);
    }
}

function setAttrByPath(el, path, name, value) {
    // Attr directly if not has property
    // FIXME, if some property not needed for element ?
    if (!path) {
        el.attr(name, value);
    }
    else {
        // Only support set shape or style
        var props = {};
        props[path] = {};
        props[path][name] = value;
        el.attr(props);
    }
}

/**
 * @alias module:zrender/Element
 * @constructor
 * @extends {module:zrender/mixin/Animatable}
 * @extends {module:zrender/mixin/Transformable}
 * @extends {module:zrender/mixin/Eventful}
 */
var Element = function (opts) { // jshint ignore:line

    Transformable.call(this, opts);
    Eventful.call(this, opts);
    Animatable.call(this, opts);

    /**
     * 画布元素ID
     * @type {string}
     */
    this.id = opts.id || guid();
};

Element.prototype = {

    /**
     * 元素类型
     * Element type
     * @type {string}
     */
    type: 'element',

    /**
     * 元素名字
     * Element name
     * @type {string}
     */
    name: '',

    /**
     * ZRender 实例对象，会在 element 添加到 zrender 实例中后自动赋值
     * ZRender instance will be assigned when element is associated with zrender
     * @name module:/zrender/Element#__zr
     * @type {module:zrender/ZRender}
     */
    __zr: null,

    /**
     * 图形是否忽略，为true时忽略图形的绘制以及事件触发
     * If ignore drawing and events of the element object
     * @name module:/zrender/Element#ignore
     * @type {boolean}
     * @default false
     */
    ignore: false,

    /**
     * 用于裁剪的路径(shape)，所有 Group 内的路径在绘制时都会被这个路径裁剪
     * 该路径会继承被裁减对象的变换
     * @type {module:zrender/graphic/Path}
     * @see http://www.w3.org/TR/2dcontext/#clipping-region
     * @readOnly
     */
    clipPath: null,

    /**
     * 是否是 Group
     * @type {boolean}
     */
    isGroup: false,

    /**
     * Drift element
     * @param  {number} dx dx on the global space
     * @param  {number} dy dy on the global space
     */
    drift: function (dx, dy) {
        switch (this.draggable) {
            case 'horizontal':
                dy = 0;
                break;
            case 'vertical':
                dx = 0;
                break;
        }

        var m = this.transform;
        if (!m) {
            m = this.transform = [1, 0, 0, 1, 0, 0];
        }
        m[4] += dx;
        m[5] += dy;

        this.decomposeTransform();
        this.dirty(false);
    },

    /**
     * Hook before update
     */
    beforeUpdate: function () {},
    /**
     * Hook after update
     */
    afterUpdate: function () {},
    /**
     * Update each frame
     */
    update: function () {
        this.updateTransform();
    },

    /**
     * @param  {Function} cb
     * @param  {}   context
     */
    traverse: function (cb, context) {},

    /**
     * @protected
     */
    attrKV: function (key, value) {
        if (key === 'position' || key === 'scale' || key === 'origin') {
            // Copy the array
            if (value) {
                var target = this[key];
                if (!target) {
                    target = this[key] = [];
                }
                target[0] = value[0];
                target[1] = value[1];
            }
        }
        else {
            this[key] = value;
        }
    },

    /**
     * Hide the element
     */
    hide: function () {
        this.ignore = true;
        this.__zr && this.__zr.refresh();
    },

    /**
     * Show the element
     */
    show: function () {
        this.ignore = false;
        this.__zr && this.__zr.refresh();
    },

    /**
     * @param {string|Object} key
     * @param {*} value
     */
    attr: function (key, value) {
        if (typeof key === 'string') {
            this.attrKV(key, value);
        }
        else if (isObject$1(key)) {
            for (var name in key) {
                if (key.hasOwnProperty(name)) {
                    this.attrKV(name, key[name]);
                }
            }
        }

        this.dirty(false);

        return this;
    },

    /**
     * @param {module:zrender/graphic/Path} clipPath
     */
    setClipPath: function (clipPath) {
        var zr = this.__zr;
        if (zr) {
            clipPath.addSelfToZr(zr);
        }

        // Remove previous clip path
        if (this.clipPath && this.clipPath !== clipPath) {
            this.removeClipPath();
        }

        this.clipPath = clipPath;
        clipPath.__zr = zr;
        clipPath.__clipTarget = this;

        this.dirty(false);
    },

    /**
     */
    removeClipPath: function () {
        var clipPath = this.clipPath;
        if (clipPath) {
            if (clipPath.__zr) {
                clipPath.removeSelfFromZr(clipPath.__zr);
            }

            clipPath.__zr = null;
            clipPath.__clipTarget = null;
            this.clipPath = null;

            this.dirty(false);
        }
    },

    /**
     * Add self from zrender instance.
     * Not recursively because it will be invoked when element added to storage.
     * @param {module:zrender/ZRender} zr
     */
    addSelfToZr: function (zr) {
        this.__zr = zr;
        // 添加动画
        var animators = this.animators;
        if (animators) {
            for (var i = 0; i < animators.length; i++) {
                zr.animation.addAnimator(animators[i]);
            }
        }

        if (this.clipPath) {
            this.clipPath.addSelfToZr(zr);
        }
    },

    /**
     * Remove self from zrender instance.
     * Not recursively because it will be invoked when element added to storage.
     * @param {module:zrender/ZRender} zr
     */
    removeSelfFromZr: function (zr) {
        this.__zr = null;
        // 移除动画
        var animators = this.animators;
        if (animators) {
            for (var i = 0; i < animators.length; i++) {
                zr.animation.removeAnimator(animators[i]);
            }
        }

        if (this.clipPath) {
            this.clipPath.removeSelfFromZr(zr);
        }
    }
};

mixin(Element, Animatable);
mixin(Element, Transformable);
mixin(Element, Eventful);

/**
 * @module echarts/core/BoundingRect
 */

var v2ApplyTransform = applyTransform;
var mathMin = Math.min;
var mathMax = Math.max;

/**
 * @alias module:echarts/core/BoundingRect
 */
function BoundingRect(x, y, width, height) {

    if (width < 0) {
        x = x + width;
        width = -width;
    }
    if (height < 0) {
        y = y + height;
        height = -height;
    }

    /**
     * @type {number}
     */
    this.x = x;
    /**
     * @type {number}
     */
    this.y = y;
    /**
     * @type {number}
     */
    this.width = width;
    /**
     * @type {number}
     */
    this.height = height;
}

BoundingRect.prototype = {

    constructor: BoundingRect,

    /**
     * @param {module:echarts/core/BoundingRect} other
     */
    union: function (other) {
        var x = mathMin(other.x, this.x);
        var y = mathMin(other.y, this.y);

        this.width = mathMax(
                other.x + other.width,
                this.x + this.width
            ) - x;
        this.height = mathMax(
                other.y + other.height,
                this.y + this.height
            ) - y;
        this.x = x;
        this.y = y;
    },

    /**
     * @param {Array.<number>} m
     * @methods
     */
    applyTransform: (function () {
        var lt = [];
        var rb = [];
        var lb = [];
        var rt = [];
        return function (m) {
            // In case usage like this
            // el.getBoundingRect().applyTransform(el.transform)
            // And element has no transform
            if (!m) {
                return;
            }
            lt[0] = lb[0] = this.x;
            lt[1] = rt[1] = this.y;
            rb[0] = rt[0] = this.x + this.width;
            rb[1] = lb[1] = this.y + this.height;

            v2ApplyTransform(lt, lt, m);
            v2ApplyTransform(rb, rb, m);
            v2ApplyTransform(lb, lb, m);
            v2ApplyTransform(rt, rt, m);

            this.x = mathMin(lt[0], rb[0], lb[0], rt[0]);
            this.y = mathMin(lt[1], rb[1], lb[1], rt[1]);
            var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]);
            var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]);
            this.width = maxX - this.x;
            this.height = maxY - this.y;
        };
    })(),

    /**
     * Calculate matrix of transforming from self to target rect
     * @param  {module:zrender/core/BoundingRect} b
     * @return {Array.<number>}
     */
    calculateTransform: function (b) {
        var a = this;
        var sx = b.width / a.width;
        var sy = b.height / a.height;

        var m = create$1();

        // 矩阵右乘
        translate(m, m, [-a.x, -a.y]);
        scale$1(m, m, [sx, sy]);
        translate(m, m, [b.x, b.y]);

        return m;
    },

    /**
     * @param {(module:echarts/core/BoundingRect|Object)} b
     * @return {boolean}
     */
    intersect: function (b) {
        if (!b) {
            return false;
        }

        if (!(b instanceof BoundingRect)) {
            // Normalize negative width/height.
            b = BoundingRect.create(b);
        }

        var a = this;
        var ax0 = a.x;
        var ax1 = a.x + a.width;
        var ay0 = a.y;
        var ay1 = a.y + a.height;

        var bx0 = b.x;
        var bx1 = b.x + b.width;
        var by0 = b.y;
        var by1 = b.y + b.height;

        return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
    },

    contain: function (x, y) {
        var rect = this;
        return x >= rect.x
            && x <= (rect.x + rect.width)
            && y >= rect.y
            && y <= (rect.y + rect.height);
    },

    /**
     * @return {module:echarts/core/BoundingRect}
     */
    clone: function () {
        return new BoundingRect(this.x, this.y, this.width, this.height);
    },

    /**
     * Copy from another rect
     */
    copy: function (other) {
        this.x = other.x;
        this.y = other.y;
        this.width = other.width;
        this.height = other.height;
    },

    plain: function () {
        return {
            x: this.x,
            y: this.y,
            width: this.width,
            height: this.height
        };
    }
};

/**
 * @param {Object|module:zrender/core/BoundingRect} rect
 * @param {number} rect.x
 * @param {number} rect.y
 * @param {number} rect.width
 * @param {number} rect.height
 * @return {module:zrender/core/BoundingRect}
 */
BoundingRect.create = function (rect) {
    return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
};

/**
 * Group是一个容器，可以插入子节点，Group的变换也会被应用到子节点上
 * @module zrender/graphic/Group
 * @example
 *     var Group = require('zrender/container/Group');
 *     var Circle = require('zrender/graphic/shape/Circle');
 *     var g = new Group();
 *     g.position[0] = 100;
 *     g.position[1] = 100;
 *     g.add(new Circle({
 *         style: {
 *             x: 100,
 *             y: 100,
 *             r: 20,
 *         }
 *     }));
 *     zr.add(g);
 */

/**
 * @alias module:zrender/graphic/Group
 * @constructor
 * @extends module:zrender/mixin/Transformable
 * @extends module:zrender/mixin/Eventful
 */
var Group = function (opts) {

    opts = opts || {};

    Element.call(this, opts);

    for (var key in opts) {
        if (opts.hasOwnProperty(key)) {
            this[key] = opts[key];
        }
    }

    this._children = [];

    this.__storage = null;

    this.__dirty = true;
};

Group.prototype = {

    constructor: Group,

    isGroup: true,

    /**
     * @type {string}
     */
    type: 'group',

    /**
     * 所有子孙元素是否响应鼠标事件
     * @name module:/zrender/container/Group#silent
     * @type {boolean}
     * @default false
     */
    silent: false,

    /**
     * @return {Array.<module:zrender/Element>}
     */
    children: function () {
        return this._children.slice();
    },

    /**
     * 获取指定 index 的儿子节点
     * @param  {number} idx
     * @return {module:zrender/Element}
     */
    childAt: function (idx) {
        return this._children[idx];
    },

    /**
     * 获取指定名字的儿子节点
     * @param  {string} name
     * @return {module:zrender/Element}
     */
    childOfName: function (name) {
        var children = this._children;
        for (var i = 0; i < children.length; i++) {
            if (children[i].name === name) {
                return children[i];
            }
            }
    },

    /**
     * @return {number}
     */
    childCount: function () {
        return this._children.length;
    },

    /**
     * 添加子节点到最后
     * @param {module:zrender/Element} child
     */
    add: function (child) {
        if (child && child !== this && child.parent !== this) {

            this._children.push(child);

            this._doAdd(child);
        }

        return this;
    },

    /**
     * 添加子节点在 nextSibling 之前
     * @param {module:zrender/Element} child
     * @param {module:zrender/Element} nextSibling
     */
    addBefore: function (child, nextSibling) {
        if (child && child !== this && child.parent !== this
            && nextSibling && nextSibling.parent === this) {

            var children = this._children;
            var idx = children.indexOf(nextSibling);

            if (idx >= 0) {
                children.splice(idx, 0, child);
                this._doAdd(child);
            }
        }

        return this;
    },

    _doAdd: function (child) {
        if (child.parent) {
            child.parent.remove(child);
        }

        child.parent = this;

        var storage = this.__storage;
        var zr = this.__zr;
        if (storage && storage !== child.__storage) {

            storage.addToStorage(child);

            if (child instanceof Group) {
                child.addChildrenToStorage(storage);
            }
        }

        zr && zr.refresh();
    },

    /**
     * 移除子节点
     * @param {module:zrender/Element} child
     */
    remove: function (child) {
        var zr = this.__zr;
        var storage = this.__storage;
        var children = this._children;

        var idx = indexOf(children, child);
        if (idx < 0) {
            return this;
        }
        children.splice(idx, 1);

        child.parent = null;

        if (storage) {

            storage.delFromStorage(child);

            if (child instanceof Group) {
                child.delChildrenFromStorage(storage);
            }
        }

        zr && zr.refresh();

        return this;
    },

    /**
     * 移除所有子节点
     */
    removeAll: function () {
        var children = this._children;
        var storage = this.__storage;
        var child;
        var i;
        for (i = 0; i < children.length; i++) {
            child = children[i];
            if (storage) {
                storage.delFromStorage(child);
                if (child instanceof Group) {
                    child.delChildrenFromStorage(storage);
                }
            }
            child.parent = null;
        }
        children.length = 0;

        return this;
    },

    /**
     * 遍历所有子节点
     * @param  {Function} cb
     * @param  {}   context
     */
    eachChild: function (cb, context) {
        var children = this._children;
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            cb.call(context, child, i);
        }
        return this;
    },

    /**
     * 深度优先遍历所有子孙节点
     * @param  {Function} cb
     * @param  {}   context
     */
    traverse: function (cb, context) {
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            cb.call(context, child);

            if (child.type === 'group') {
                child.traverse(cb, context);
            }
        }
        return this;
    },

    addChildrenToStorage: function (storage) {
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            storage.addToStorage(child);
            if (child instanceof Group) {
                child.addChildrenToStorage(storage);
            }
        }
    },

    delChildrenFromStorage: function (storage) {
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            storage.delFromStorage(child);
            if (child instanceof Group) {
                child.delChildrenFromStorage(storage);
            }
        }
    },

    dirty: function () {
        this.__dirty = true;
        this.__zr && this.__zr.refresh();
        return this;
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getBoundingRect: function (includeChildren) {
        // TODO Caching
        var rect = null;
        var tmpRect = new BoundingRect(0, 0, 0, 0);
        var children = includeChildren || this._children;
        var tmpMat = [];

        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            if (child.ignore || child.invisible) {
                continue;
            }

            var childRect = child.getBoundingRect();
            var transform = child.getLocalTransform(tmpMat);
            // TODO
            // The boundingRect cacluated by transforming original
            // rect may be bigger than the actual bundingRect when rotation
            // is used. (Consider a circle rotated aginst its center, where
            // the actual boundingRect should be the same as that not be
            // rotated.) But we can not find better approach to calculate
            // actual boundingRect yet, considering performance.
            if (transform) {
                tmpRect.copy(childRect);
                tmpRect.applyTransform(transform);
                rect = rect || tmpRect.clone();
                rect.union(tmpRect);
            }
            else {
                rect = rect || childRect.clone();
                rect.union(childRect);
            }
        }
        return rect || tmpRect;
    }
};

inherits(Group, Element);

// https://github.com/mziccard/node-timsort
var DEFAULT_MIN_MERGE = 32;

var DEFAULT_MIN_GALLOPING = 7;

function minRunLength(n) {
    var r = 0;

    while (n >= DEFAULT_MIN_MERGE) {
        r |= n & 1;
        n >>= 1;
    }

    return n + r;
}

function makeAscendingRun(array, lo, hi, compare) {
    var runHi = lo + 1;

    if (runHi === hi) {
        return 1;
    }

    if (compare(array[runHi++], array[lo]) < 0) {
        while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
            runHi++;
        }

        reverseRun(array, lo, runHi);
    }
    else {
        while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
            runHi++;
        }
    }

    return runHi - lo;
}

function reverseRun(array, lo, hi) {
    hi--;

    while (lo < hi) {
        var t = array[lo];
        array[lo++] = array[hi];
        array[hi--] = t;
    }
}

function binaryInsertionSort(array, lo, hi, start, compare) {
    if (start === lo) {
        start++;
    }

    for (; start < hi; start++) {
        var pivot = array[start];

        var left = lo;
        var right = start;
        var mid;

        while (left < right) {
            mid = left + right >>> 1;

            if (compare(pivot, array[mid]) < 0) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }

        var n = start - left;

        switch (n) {
            case 3:
                array[left + 3] = array[left + 2];

            case 2:
                array[left + 2] = array[left + 1];

            case 1:
                array[left + 1] = array[left];
                break;
            default:
                while (n > 0) {
                    array[left + n] = array[left + n - 1];
                    n--;
                }
        }

        array[left] = pivot;
    }
}

function gallopLeft(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;

    if (compare(value, array[start + hint]) > 0) {
        maxOffset = length - hint;

        while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;

            if (offset <= 0) {
                offset = maxOffset;
            }
        }

        if (offset > maxOffset) {
            offset = maxOffset;
        }

        lastOffset += hint;
        offset += hint;
    }
    else {
        maxOffset = hint + 1;
        while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;

            if (offset <= 0) {
                offset = maxOffset;
            }
        }
        if (offset > maxOffset) {
            offset = maxOffset;
        }

        var tmp = lastOffset;
        lastOffset = hint - offset;
        offset = hint - tmp;
    }

    lastOffset++;
    while (lastOffset < offset) {
        var m = lastOffset + (offset - lastOffset >>> 1);

        if (compare(value, array[start + m]) > 0) {
            lastOffset = m + 1;
        }
        else {
            offset = m;
        }
    }
    return offset;
}

function gallopRight(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;

    if (compare(value, array[start + hint]) < 0) {
        maxOffset = hint + 1;

        while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;

            if (offset <= 0) {
                offset = maxOffset;
            }
        }

        if (offset > maxOffset) {
            offset = maxOffset;
        }

        var tmp = lastOffset;
        lastOffset = hint - offset;
        offset = hint - tmp;
    }
    else {
        maxOffset = length - hint;

        while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;

            if (offset <= 0) {
                offset = maxOffset;
            }
        }

        if (offset > maxOffset) {
            offset = maxOffset;
        }

        lastOffset += hint;
        offset += hint;
    }

    lastOffset++;

    while (lastOffset < offset) {
        var m = lastOffset + (offset - lastOffset >>> 1);

        if (compare(value, array[start + m]) < 0) {
            offset = m;
        }
        else {
            lastOffset = m + 1;
        }
    }

    return offset;
}

function TimSort(array, compare) {
    var minGallop = DEFAULT_MIN_GALLOPING;
    var runStart;
    var runLength;
    var stackSize = 0;

    var tmp = [];

    runStart = [];
    runLength = [];

    function pushRun(_runStart, _runLength) {
        runStart[stackSize] = _runStart;
        runLength[stackSize] = _runLength;
        stackSize += 1;
    }

    function mergeRuns() {
        while (stackSize > 1) {
            var n = stackSize - 2;

            if (
                (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1])
                || (n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1])
            ) {
                if (runLength[n - 1] < runLength[n + 1]) {
                    n--;
                }
            }
            else if (runLength[n] > runLength[n + 1]) {
                break;
            }
            mergeAt(n);
        }
    }

    function forceMergeRuns() {
        while (stackSize > 1) {
            var n = stackSize - 2;

            if (n > 0 && runLength[n - 1] < runLength[n + 1]) {
                n--;
            }

            mergeAt(n);
        }
    }

    function mergeAt(i) {
        var start1 = runStart[i];
        var length1 = runLength[i];
        var start2 = runStart[i + 1];
        var length2 = runLength[i + 1];

        runLength[i] = length1 + length2;

        if (i === stackSize - 3) {
            runStart[i + 1] = runStart[i + 2];
            runLength[i + 1] = runLength[i + 2];
        }

        stackSize--;

        var k = gallopRight(array[start2], array, start1, length1, 0, compare);
        start1 += k;
        length1 -= k;

        if (length1 === 0) {
            return;
        }

        length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);

        if (length2 === 0) {
            return;
        }

        if (length1 <= length2) {
            mergeLow(start1, length1, start2, length2);
        }
        else {
            mergeHigh(start1, length1, start2, length2);
        }
    }

    function mergeLow(start1, length1, start2, length2) {
        var i = 0;

        for (i = 0; i < length1; i++) {
            tmp[i] = array[start1 + i];
        }

        var cursor1 = 0;
        var cursor2 = start2;
        var dest = start1;

        array[dest++] = array[cursor2++];

        if (--length2 === 0) {
            for (i = 0; i < length1; i++) {
                array[dest + i] = tmp[cursor1 + i];
            }
            return;
        }

        if (length1 === 1) {
            for (i = 0; i < length2; i++) {
                array[dest + i] = array[cursor2 + i];
            }
            array[dest + length2] = tmp[cursor1];
            return;
        }

        var _minGallop = minGallop;
        var count1;
        var count2;
        var exit;

        while (1) {
            count1 = 0;
            count2 = 0;
            exit = false;

            do {
                if (compare(array[cursor2], tmp[cursor1]) < 0) {
                    array[dest++] = array[cursor2++];
                    count2++;
                    count1 = 0;

                    if (--length2 === 0) {
                        exit = true;
                        break;
                    }
                }
                else {
                    array[dest++] = tmp[cursor1++];
                    count1++;
                    count2 = 0;
                    if (--length1 === 1) {
                        exit = true;
                        break;
                    }
                }
            } while ((count1 | count2) < _minGallop);

            if (exit) {
                break;
            }

            do {
                count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);

                if (count1 !== 0) {
                    for (i = 0; i < count1; i++) {
                        array[dest + i] = tmp[cursor1 + i];
                    }

                    dest += count1;
                    cursor1 += count1;
                    length1 -= count1;
                    if (length1 <= 1) {
                        exit = true;
                        break;
                    }
                }

                array[dest++] = array[cursor2++];

                if (--length2 === 0) {
                    exit = true;
                    break;
                }

                count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);

                if (count2 !== 0) {
                    for (i = 0; i < count2; i++) {
                        array[dest + i] = array[cursor2 + i];
                    }

                    dest += count2;
                    cursor2 += count2;
                    length2 -= count2;

                    if (length2 === 0) {
                        exit = true;
                        break;
                    }
                }
                array[dest++] = tmp[cursor1++];

                if (--length1 === 1) {
                    exit = true;
                    break;
                }

                _minGallop--;
            } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

            if (exit) {
                break;
            }

            if (_minGallop < 0) {
                _minGallop = 0;
            }

            _minGallop += 2;
        }

        minGallop = _minGallop;

        minGallop < 1 && (minGallop = 1);

        if (length1 === 1) {
            for (i = 0; i < length2; i++) {
                array[dest + i] = array[cursor2 + i];
            }
            array[dest + length2] = tmp[cursor1];
        }
        else if (length1 === 0) {
            throw new Error();
            // throw new Error('mergeLow preconditions were not respected');
        }
        else {
            for (i = 0; i < length1; i++) {
                array[dest + i] = tmp[cursor1 + i];
            }
        }
    }

    function mergeHigh(start1, length1, start2, length2) {
        var i = 0;

        for (i = 0; i < length2; i++) {
            tmp[i] = array[start2 + i];
        }

        var cursor1 = start1 + length1 - 1;
        var cursor2 = length2 - 1;
        var dest = start2 + length2 - 1;
        var customCursor = 0;
        var customDest = 0;

        array[dest--] = array[cursor1--];

        if (--length1 === 0) {
            customCursor = dest - (length2 - 1);

            for (i = 0; i < length2; i++) {
                array[customCursor + i] = tmp[i];
            }

            return;
        }

        if (length2 === 1) {
            dest -= length1;
            cursor1 -= length1;
            customDest = dest + 1;
            customCursor = cursor1 + 1;

            for (i = length1 - 1; i >= 0; i--) {
                array[customDest + i] = array[customCursor + i];
            }

            array[dest] = tmp[cursor2];
            return;
        }

        var _minGallop = minGallop;

        while (true) {
            var count1 = 0;
            var count2 = 0;
            var exit = false;

            do {
                if (compare(tmp[cursor2], array[cursor1]) < 0) {
                    array[dest--] = array[cursor1--];
                    count1++;
                    count2 = 0;
                    if (--length1 === 0) {
                        exit = true;
                        break;
                    }
                }
                else {
                    array[dest--] = tmp[cursor2--];
                    count2++;
                    count1 = 0;
                    if (--length2 === 1) {
                        exit = true;
                        break;
                    }
                }
            } while ((count1 | count2) < _minGallop);

            if (exit) {
                break;
            }

            do {
                count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);

                if (count1 !== 0) {
                    dest -= count1;
                    cursor1 -= count1;
                    length1 -= count1;
                    customDest = dest + 1;
                    customCursor = cursor1 + 1;

                    for (i = count1 - 1; i >= 0; i--) {
                        array[customDest + i] = array[customCursor + i];
                    }

                    if (length1 === 0) {
                        exit = true;
                        break;
                    }
                }

                array[dest--] = tmp[cursor2--];

                if (--length2 === 1) {
                    exit = true;
                    break;
                }

                count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);

                if (count2 !== 0) {
                    dest -= count2;
                    cursor2 -= count2;
                    length2 -= count2;
                    customDest = dest + 1;
                    customCursor = cursor2 + 1;

                    for (i = 0; i < count2; i++) {
                        array[customDest + i] = tmp[customCursor + i];
                    }

                    if (length2 <= 1) {
                        exit = true;
                        break;
                    }
                }

                array[dest--] = array[cursor1--];

                if (--length1 === 0) {
                    exit = true;
                    break;
                }

                _minGallop--;
            } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

            if (exit) {
                break;
            }

            if (_minGallop < 0) {
                _minGallop = 0;
            }

            _minGallop += 2;
        }

        minGallop = _minGallop;

        if (minGallop < 1) {
            minGallop = 1;
        }

        if (length2 === 1) {
            dest -= length1;
            cursor1 -= length1;
            customDest = dest + 1;
            customCursor = cursor1 + 1;

            for (i = length1 - 1; i >= 0; i--) {
                array[customDest + i] = array[customCursor + i];
            }

            array[dest] = tmp[cursor2];
        }
        else if (length2 === 0) {
            throw new Error();
            // throw new Error('mergeHigh preconditions were not respected');
        }
        else {
            customCursor = dest - (length2 - 1);
            for (i = 0; i < length2; i++) {
                array[customCursor + i] = tmp[i];
            }
        }
    }

    this.mergeRuns = mergeRuns;
    this.forceMergeRuns = forceMergeRuns;
    this.pushRun = pushRun;
}

function sort(array, compare, lo, hi) {
    if (!lo) {
        lo = 0;
    }
    if (!hi) {
        hi = array.length;
    }

    var remaining = hi - lo;

    if (remaining < 2) {
        return;
    }

    var runLength = 0;

    if (remaining < DEFAULT_MIN_MERGE) {
        runLength = makeAscendingRun(array, lo, hi, compare);
        binaryInsertionSort(array, lo, hi, lo + runLength, compare);
        return;
    }

    var ts = new TimSort(array, compare);

    var minRun = minRunLength(remaining);

    do {
        runLength = makeAscendingRun(array, lo, hi, compare);
        if (runLength < minRun) {
            var force = remaining;
            if (force > minRun) {
                force = minRun;
            }

            binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
            runLength = force;
        }

        ts.pushRun(lo, runLength);
        ts.mergeRuns();

        remaining -= runLength;
        lo += runLength;
    } while (remaining !== 0);

    ts.forceMergeRuns();
}

// Use timsort because in most case elements are partially sorted
// https://jsfiddle.net/pissang/jr4x7mdm/8/
function shapeCompareFunc(a, b) {
    if (a.zlevel === b.zlevel) {
        if (a.z === b.z) {
            // if (a.z2 === b.z2) {
            //     // FIXME Slow has renderidx compare
            //     // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement
            //     // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012
            //     return a.__renderidx - b.__renderidx;
            // }
            return a.z2 - b.z2;
        }
        return a.z - b.z;
    }
    return a.zlevel - b.zlevel;
}
/**
 * 内容仓库 (M)
 * @alias module:zrender/Storage
 * @constructor
 */
var Storage = function () { // jshint ignore:line
    this._roots = [];

    this._displayList = [];

    this._displayListLen = 0;
};

Storage.prototype = {

    constructor: Storage,

    /**
     * @param  {Function} cb
     *
     */
    traverse: function (cb, context) {
        for (var i = 0; i < this._roots.length; i++) {
            this._roots[i].traverse(cb, context);
        }
    },

    /**
     * 返回所有图形的绘制队列
     * @param {boolean} [update=false] 是否在返回前更新该数组
     * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效
     *
     * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}
     * @return {Array.<module:zrender/graphic/Displayable>}
     */
    getDisplayList: function (update, includeIgnore) {
        includeIgnore = includeIgnore || false;
        if (update) {
            this.updateDisplayList(includeIgnore);
        }
        return this._displayList;
    },

    /**
     * 更新图形的绘制队列。
     * 每次绘制前都会调用，该方法会先深度优先遍历整个树，更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中，
     * 最后根据绘制的优先级（zlevel > z > 插入顺序）排序得到绘制队列
     * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组
     */
    updateDisplayList: function (includeIgnore) {
        this._displayListLen = 0;

        var roots = this._roots;
        var displayList = this._displayList;
        for (var i = 0, len = roots.length; i < len; i++) {
            this._updateAndAddDisplayable(roots[i], null, includeIgnore);
        }

        displayList.length = this._displayListLen;

        env$1.canvasSupported && sort(displayList, shapeCompareFunc);
    },

    _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) {

        if (el.ignore && !includeIgnore) {
            return;
        }

        el.beforeUpdate();

        if (el.__dirty) {

            el.update();

        }

        el.afterUpdate();

        var userSetClipPath = el.clipPath;
        if (userSetClipPath) {

            // FIXME 效率影响
            if (clipPaths) {
                clipPaths = clipPaths.slice();
            }
            else {
                clipPaths = [];
            }

            var currentClipPath = userSetClipPath;
            var parentClipPath = el;
            // Recursively add clip path
            while (currentClipPath) {
                // clipPath 的变换是基于使用这个 clipPath 的元素
                currentClipPath.parent = parentClipPath;
                currentClipPath.updateTransform();

                clipPaths.push(currentClipPath);

                parentClipPath = currentClipPath;
                currentClipPath = currentClipPath.clipPath;
            }
        }

        if (el.isGroup) {
            var children = el._children;

            for (var i = 0; i < children.length; i++) {
                var child = children[i];

                // Force to mark as dirty if group is dirty
                // FIXME __dirtyPath ?
                if (el.__dirty) {
                    child.__dirty = true;
                }

                this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
            }

            // Mark group clean here
            el.__dirty = false;

        }
        else {
            el.__clipPaths = clipPaths;

            this._displayList[this._displayListLen++] = el;
        }
    },

    /**
     * 添加图形(Shape)或者组(Group)到根节点
     * @param {module:zrender/Element} el
     */
    addRoot: function (el) {
        if (el.__storage === this) {
            return;
        }

        if (el instanceof Group) {
            el.addChildrenToStorage(this);
        }

        this.addToStorage(el);
        this._roots.push(el);
    },

    /**
     * 删除指定的图形(Shape)或者组(Group)
     * @param {string|Array.<string>} [el] 如果为空清空整个Storage
     */
    delRoot: function (el) {
        if (el == null) {
            // 不指定el清空
            for (var i = 0; i < this._roots.length; i++) {
                var root = this._roots[i];
                if (root instanceof Group) {
                    root.delChildrenFromStorage(this);
                }
            }

            this._roots = [];
            this._displayList = [];
            this._displayListLen = 0;

            return;
        }

        if (el instanceof Array) {
            for (var i = 0, l = el.length; i < l; i++) {
                this.delRoot(el[i]);
            }
            return;
        }


        var idx = indexOf(this._roots, el);
        if (idx >= 0) {
            this.delFromStorage(el);
            this._roots.splice(idx, 1);
            if (el instanceof Group) {
                el.delChildrenFromStorage(this);
            }
        }
    },

    addToStorage: function (el) {
        if (el) {
            el.__storage = this;
            el.dirty(false);
        }
        return this;
    },

    delFromStorage: function (el) {
        if (el) {
            el.__storage = null;
        }

        return this;
    },

    /**
     * 清空并且释放Storage
     */
    dispose: function () {
        this._renderList =
        this._roots = null;
    },

    displayableSortFunc: shapeCompareFunc
};

var SHADOW_PROPS = {
    'shadowBlur': 1,
    'shadowOffsetX': 1,
    'shadowOffsetY': 1,
    'textShadowBlur': 1,
    'textShadowOffsetX': 1,
    'textShadowOffsetY': 1,
    'textBoxShadowBlur': 1,
    'textBoxShadowOffsetX': 1,
    'textBoxShadowOffsetY': 1
};

var fixShadow = function (ctx, propName, value) {
    if (SHADOW_PROPS.hasOwnProperty(propName)) {
        return value *= ctx.dpr;
    }
    return value;
};

var ContextCachedBy = {
    NONE: 0,
    STYLE_BIND: 1,
    PLAIN_TEXT: 2
};

// Avoid confused with 0/false.
var WILL_BE_RESTORED = 9;

var STYLE_COMMON_PROPS = [
    ['shadowBlur', 0], ['shadowOffsetX', 0], ['shadowOffsetY', 0], ['shadowColor', '#000'],
    ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]
];

// var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4);
// var LINE_PROPS = STYLE_COMMON_PROPS.slice(4);

var Style = function (opts) {
    this.extendFrom(opts, false);
};

function createLinearGradient(ctx, obj, rect) {
    var x = obj.x == null ? 0 : obj.x;
    var x2 = obj.x2 == null ? 1 : obj.x2;
    var y = obj.y == null ? 0 : obj.y;
    var y2 = obj.y2 == null ? 0 : obj.y2;

    if (!obj.global) {
        x = x * rect.width + rect.x;
        x2 = x2 * rect.width + rect.x;
        y = y * rect.height + rect.y;
        y2 = y2 * rect.height + rect.y;
    }

    // Fix NaN when rect is Infinity
    x = isNaN(x) ? 0 : x;
    x2 = isNaN(x2) ? 1 : x2;
    y = isNaN(y) ? 0 : y;
    y2 = isNaN(y2) ? 0 : y2;

    var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);

    return canvasGradient;
}

function createRadialGradient(ctx, obj, rect) {
    var width = rect.width;
    var height = rect.height;
    var min = Math.min(width, height);

    var x = obj.x == null ? 0.5 : obj.x;
    var y = obj.y == null ? 0.5 : obj.y;
    var r = obj.r == null ? 0.5 : obj.r;
    if (!obj.global) {
        x = x * width + rect.x;
        y = y * height + rect.y;
        r = r * min;
    }

    var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);

    return canvasGradient;
}


Style.prototype = {

    constructor: Style,

    /**
     * @type {string}
     */
    fill: '#000',

    /**
     * @type {string}
     */
    stroke: null,

    /**
     * @type {number}
     */
    opacity: 1,

    /**
     * @type {number}
     */
    fillOpacity: null,

    /**
     * @type {number}
     */
    strokeOpacity: null,

    /**
     * `true` is not supported.
     * `false`/`null`/`undefined` are the same.
     * `false` is used to remove lineDash in some
     * case that `null`/`undefined` can not be set.
     * (e.g., emphasis.lineStyle in echarts)
     * @type {Array.<number>|boolean}
     */
    lineDash: null,

    /**
     * @type {number}
     */
    lineDashOffset: 0,

    /**
     * @type {number}
     */
    shadowBlur: 0,

    /**
     * @type {number}
     */
    shadowOffsetX: 0,

    /**
     * @type {number}
     */
    shadowOffsetY: 0,

    /**
     * @type {number}
     */
    lineWidth: 1,

    /**
     * If stroke ignore scale
     * @type {Boolean}
     */
    strokeNoScale: false,

    // Bounding rect text configuration
    // Not affected by element transform
    /**
     * @type {string}
     */
    text: null,

    /**
     * If `fontSize` or `fontFamily` exists, `font` will be reset by
     * `fontSize`, `fontStyle`, `fontWeight`, `fontFamily`.
     * So do not visit it directly in upper application (like echarts),
     * but use `contain/text#makeFont` instead.
     * @type {string}
     */
    font: null,

    /**
     * The same as font. Use font please.
     * @deprecated
     * @type {string}
     */
    textFont: null,

    /**
     * It helps merging respectively, rather than parsing an entire font string.
     * @type {string}
     */
    fontStyle: null,

    /**
     * It helps merging respectively, rather than parsing an entire font string.
     * @type {string}
     */
    fontWeight: null,

    /**
     * It helps merging respectively, rather than parsing an entire font string.
     * Should be 12 but not '12px'.
     * @type {number}
     */
    fontSize: null,

    /**
     * It helps merging respectively, rather than parsing an entire font string.
     * @type {string}
     */
    fontFamily: null,

    /**
     * Reserved for special functinality, like 'hr'.
     * @type {string}
     */
    textTag: null,

    /**
     * @type {string}
     */
    textFill: '#000',

    /**
     * @type {string}
     */
    textStroke: null,

    /**
     * @type {number}
     */
    textWidth: null,

    /**
     * Only for textBackground.
     * @type {number}
     */
    textHeight: null,

    /**
     * textStroke may be set as some color as a default
     * value in upper applicaion, where the default value
     * of textStrokeWidth should be 0 to make sure that
     * user can choose to do not use text stroke.
     * @type {number}
     */
    textStrokeWidth: 0,

    /**
     * @type {number}
     */
    textLineHeight: null,

    /**
     * 'inside', 'left', 'right', 'top', 'bottom'
     * [x, y]
     * Based on x, y of rect.
     * @type {string|Array.<number>}
     * @default 'inside'
     */
    textPosition: 'inside',

    /**
     * If not specified, use the boundingRect of a `displayable`.
     * @type {Object}
     */
    textRect: null,

    /**
     * [x, y]
     * @type {Array.<number>}
     */
    textOffset: null,

    /**
     * @type {string}
     */
    textAlign: null,

    /**
     * @type {string}
     */
    textVerticalAlign: null,

    /**
     * @type {number}
     */
    textDistance: 5,

    /**
     * @type {string}
     */
    textShadowColor: 'transparent',

    /**
     * @type {number}
     */
    textShadowBlur: 0,

    /**
     * @type {number}
     */
    textShadowOffsetX: 0,

    /**
     * @type {number}
     */
    textShadowOffsetY: 0,

    /**
     * @type {string}
     */
    textBoxShadowColor: 'transparent',

    /**
     * @type {number}
     */
    textBoxShadowBlur: 0,

    /**
     * @type {number}
     */
    textBoxShadowOffsetX: 0,

    /**
     * @type {number}
     */
    textBoxShadowOffsetY: 0,

    /**
     * Whether transform text.
     * Only available in Path and Image element,
     * where the text is called as `RectText`.
     * @type {boolean}
     */
    transformText: false,

    /**
     * Text rotate around position of Path or Image.
     * The origin of the rotation can be specified by `textOrigin`.
     * Only available in Path and Image element,
     * where the text is called as `RectText`.
     */
    textRotation: 0,

    /**
     * Text origin of text rotation.
     * Useful in the case like label rotation of circular symbol.
     * Only available in Path and Image element, where the text is called
     * as `RectText` and the element is called as "host element".
     * The value can be:
     * + If specified as a coordinate like `[10, 40]`, it is the `[x, y]`
     * base on the left-top corner of the rect of its host element.
     * + If specified as a string `center`, it is the center of the rect of
     * its host element.
     * + By default, this origin is the `textPosition`.
     * @type {string|Array.<number>}
     */
    textOrigin: null,

    /**
     * @type {string}
     */
    textBackgroundColor: null,

    /**
     * @type {string}
     */
    textBorderColor: null,

    /**
     * @type {number}
     */
    textBorderWidth: 0,

    /**
     * @type {number}
     */
    textBorderRadius: 0,

    /**
     * Can be `2` or `[2, 4]` or `[2, 3, 4, 5]`
     * @type {number|Array.<number>}
     */
    textPadding: null,

    /**
     * Text styles for rich text.
     * @type {Object}
     */
    rich: null,

    /**
     * {outerWidth, outerHeight, ellipsis, placeholder}
     * @type {Object}
     */
    truncate: null,

    /**
     * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
     * @type {string}
     */
    blend: null,

    /**
     * @param {CanvasRenderingContext2D} ctx
     */
    bind: function (ctx, el, prevEl) {
        var style = this;
        var prevStyle = prevEl && prevEl.style;
        // If no prevStyle, it means first draw.
        // Only apply cache if the last time cachced by this function.
        var notCheckCache = !prevStyle || ctx.__attrCachedBy !== ContextCachedBy.STYLE_BIND;

        ctx.__attrCachedBy = ContextCachedBy.STYLE_BIND;

        for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
            var prop = STYLE_COMMON_PROPS[i];
            var styleName = prop[0];

            if (notCheckCache || style[styleName] !== prevStyle[styleName]) {
                // FIXME Invalid property value will cause style leak from previous element.
                ctx[styleName] =
                    fixShadow(ctx, styleName, style[styleName] || prop[1]);
            }
        }

        if ((notCheckCache || style.fill !== prevStyle.fill)) {
            ctx.fillStyle = style.fill;
        }
        if ((notCheckCache || style.stroke !== prevStyle.stroke)) {
            ctx.strokeStyle = style.stroke;
        }
        if ((notCheckCache || style.opacity !== prevStyle.opacity)) {
            ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
        }

        if ((notCheckCache || style.blend !== prevStyle.blend)) {
            ctx.globalCompositeOperation = style.blend || 'source-over';
        }
        if (this.hasStroke()) {
            var lineWidth = style.lineWidth;
            ctx.lineWidth = lineWidth / (
                (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1
            );
        }
    },

    hasFill: function () {
        var fill = this.fill;
        return fill != null && fill !== 'none';
    },

    hasStroke: function () {
        var stroke = this.stroke;
        return stroke != null && stroke !== 'none' && this.lineWidth > 0;
    },

    /**
     * Extend from other style
     * @param {zrender/graphic/Style} otherStyle
     * @param {boolean} overwrite true: overwrirte any way.
     *                            false: overwrite only when !target.hasOwnProperty
     *                            others: overwrite when property is not null/undefined.
     */
    extendFrom: function (otherStyle, overwrite) {
        if (otherStyle) {
            for (var name in otherStyle) {
                if (otherStyle.hasOwnProperty(name)
                    && (overwrite === true
                        || (
                            overwrite === false
                                ? !this.hasOwnProperty(name)
                                : otherStyle[name] != null
                        )
                    )
                ) {
                    this[name] = otherStyle[name];
                }
            }
        }
    },

    /**
     * Batch setting style with a given object
     * @param {Object|string} obj
     * @param {*} [obj]
     */
    set: function (obj, value) {
        if (typeof obj === 'string') {
            this[obj] = value;
        }
        else {
            this.extendFrom(obj, true);
        }
    },

    /**
     * Clone
     * @return {zrender/graphic/Style} [description]
     */
    clone: function () {
        var newStyle = new this.constructor();
        newStyle.extendFrom(this, true);
        return newStyle;
    },

    getGradient: function (ctx, obj, rect) {
        var method = obj.type === 'radial' ? createRadialGradient : createLinearGradient;
        var canvasGradient = method(ctx, obj, rect);
        var colorStops = obj.colorStops;
        for (var i = 0; i < colorStops.length; i++) {
            canvasGradient.addColorStop(
                colorStops[i].offset, colorStops[i].color
            );
        }
        return canvasGradient;
    }

};

var styleProto = Style.prototype;
for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
    var prop = STYLE_COMMON_PROPS[i];
    if (!(prop[0] in styleProto)) {
        styleProto[prop[0]] = prop[1];
    }
}

// Provide for others
Style.getGradient = styleProto.getGradient;

var Pattern = function (image, repeat) {
    // Should do nothing more in this constructor. Because gradient can be
    // declard by `color: {image: ...}`, where this constructor will not be called.

    this.image = image;
    this.repeat = repeat;

    // Can be cloned
    this.type = 'pattern';
};

Pattern.prototype.getCanvasPattern = function (ctx) {
    return ctx.createPattern(this.image, this.repeat || 'repeat');
};

/**
 * @module zrender/Layer
 * @author pissang(https://www.github.com/pissang)
 */

function returnFalse() {
    return false;
}

/**
 * 创建dom
 *
 * @inner
 * @param {string} id dom id 待用
 * @param {Painter} painter painter instance
 * @param {number} number
 */
function createDom(id, painter, dpr) {
    var newDom = createCanvas();
    var width = painter.getWidth();
    var height = painter.getHeight();

    var newDomStyle = newDom.style;
    if (newDomStyle) {  // In node or some other non-browser environment
        newDomStyle.position = 'absolute';
        newDomStyle.left = 0;
        newDomStyle.top = 0;
        newDomStyle.width = width + 'px';
        newDomStyle.height = height + 'px';

        newDom.setAttribute('data-zr-dom-id', id);
    }

    newDom.width = width * dpr;
    newDom.height = height * dpr;

    return newDom;
}

/**
 * @alias module:zrender/Layer
 * @constructor
 * @extends module:zrender/mixin/Transformable
 * @param {string} id
 * @param {module:zrender/Painter} painter
 * @param {number} [dpr]
 */
var Layer = function (id, painter, dpr) {
    var dom;
    dpr = dpr || devicePixelRatio;
    if (typeof id === 'string') {
        dom = createDom(id, painter, dpr);
    }
    // Not using isDom because in node it will return false
    else if (isObject$1(id)) {
        dom = id;
        id = dom.id;
    }
    this.id = id;
    this.dom = dom;

    var domStyle = dom.style;
    if (domStyle) { // Not in node
        dom.onselectstart = returnFalse; // 避免页面选中的尴尬
        domStyle['-webkit-user-select'] = 'none';
        domStyle['user-select'] = 'none';
        domStyle['-webkit-touch-callout'] = 'none';
        domStyle['-webkit-tap-highlight-color'] = 'rgba(0,0,0,0)';
        domStyle['padding'] = 0; // eslint-disable-line dot-notation
        domStyle['margin'] = 0; // eslint-disable-line dot-notation
        domStyle['border-width'] = 0;
    }

    this.domBack = null;
    this.ctxBack = null;

    this.painter = painter;

    this.config = null;

    // Configs
    /**
     * 每次清空画布的颜色
     * @type {string}
     * @default 0
     */
    this.clearColor = 0;
    /**
     * 是否开启动态模糊
     * @type {boolean}
     * @default false
     */
    this.motionBlur = false;
    /**
     * 在开启动态模糊的时候使用，与上一帧混合的alpha值，值越大尾迹越明显
     * @type {number}
     * @default 0.7
     */
    this.lastFrameAlpha = 0.7;

    /**
     * Layer dpr
     * @type {number}
     */
    this.dpr = dpr;
};

Layer.prototype = {

    constructor: Layer,

    __dirty: true,

    __used: false,

    __drawIndex: 0,
    __startIndex: 0,
    __endIndex: 0,

    incremental: false,

    getElementCount: function () {
        return this.__endIndex - this.__startIndex;
    },

    initContext: function () {
        this.ctx = this.dom.getContext('2d');
        this.ctx.dpr = this.dpr;
    },

    createBackBuffer: function () {
        var dpr = this.dpr;

        this.domBack = createDom('back-' + this.id, this.painter, dpr);
        this.ctxBack = this.domBack.getContext('2d');

        if (dpr !== 1) {
            this.ctxBack.scale(dpr, dpr);
        }
    },

    /**
     * @param  {number} width
     * @param  {number} height
     */
    resize: function (width, height) {
        var dpr = this.dpr;

        var dom = this.dom;
        var domStyle = dom.style;
        var domBack = this.domBack;

        if (domStyle) {
            domStyle.width = width + 'px';
            domStyle.height = height + 'px';
        }

        dom.width = width * dpr;
        dom.height = height * dpr;

        if (domBack) {
            domBack.width = width * dpr;
            domBack.height = height * dpr;

            if (dpr !== 1) {
                this.ctxBack.scale(dpr, dpr);
            }
        }
    },

    /**
     * 清空该层画布
     * @param {boolean} [clearAll]=false Clear all with out motion blur
     * @param {Color} [clearColor]
     */
    clear: function (clearAll, clearColor) {
        var dom = this.dom;
        var ctx = this.ctx;
        var width = dom.width;
        var height = dom.height;

        var clearColor = clearColor || this.clearColor;
        var haveMotionBLur = this.motionBlur && !clearAll;
        var lastFrameAlpha = this.lastFrameAlpha;

        var dpr = this.dpr;

        if (haveMotionBLur) {
            if (!this.domBack) {
                this.createBackBuffer();
            }

            this.ctxBack.globalCompositeOperation = 'copy';
            this.ctxBack.drawImage(
                dom, 0, 0,
                width / dpr,
                height / dpr
            );
        }

        ctx.clearRect(0, 0, width, height);
        if (clearColor && clearColor !== 'transparent') {
            var clearColorGradientOrPattern;
            // Gradient
            if (clearColor.colorStops) {
                // Cache canvas gradient
                clearColorGradientOrPattern = clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, {
                    x: 0,
                    y: 0,
                    width: width,
                    height: height
                });

                clearColor.__canvasGradient = clearColorGradientOrPattern;
            }
            // Pattern
            else if (clearColor.image) {
                clearColorGradientOrPattern = Pattern.prototype.getCanvasPattern.call(clearColor, ctx);
            }
            ctx.save();
            ctx.fillStyle = clearColorGradientOrPattern || clearColor;
            ctx.fillRect(0, 0, width, height);
            ctx.restore();
        }

        if (haveMotionBLur) {
            var domBack = this.domBack;
            ctx.save();
            ctx.globalAlpha = lastFrameAlpha;
            ctx.drawImage(domBack, 0, 0, width, height);
            ctx.restore();
        }
    }
};

var requestAnimationFrame = (
    typeof window !== 'undefined'
    && (
        (window.requestAnimationFrame && window.requestAnimationFrame.bind(window))
        // https://github.com/ecomfe/zrender/issues/189#issuecomment-224919809
        || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window))
        || window.mozRequestAnimationFrame
        || window.webkitRequestAnimationFrame
    )
) || function (func) {
    setTimeout(func, 16);
};

var globalImageCache = new LRU(50);

/**
 * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc
 * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image
 */
function findExistImage(newImageOrSrc) {
    if (typeof newImageOrSrc === 'string') {
        var cachedImgObj = globalImageCache.get(newImageOrSrc);
        return cachedImgObj && cachedImgObj.image;
    }
    else {
        return newImageOrSrc;
    }
}

/**
 * Caution: User should cache loaded images, but not just count on LRU.
 * Consider if required images more than LRU size, will dead loop occur?
 *
 * @param {string|HTMLImageElement|HTMLCanvasElement|Canvas} newImageOrSrc
 * @param {HTMLImageElement|HTMLCanvasElement|Canvas} image Existent image.
 * @param {module:zrender/Element} [hostEl] For calling `dirty`.
 * @param {Function} [cb] params: (image, cbPayload)
 * @param {Object} [cbPayload] Payload on cb calling.
 * @return {HTMLImageElement|HTMLCanvasElement|Canvas} image
 */
function createOrUpdateImage(newImageOrSrc, image, hostEl, cb, cbPayload) {
    if (!newImageOrSrc) {
        return image;
    }
    else if (typeof newImageOrSrc === 'string') {

        // Image should not be loaded repeatly.
        if ((image && image.__zrImageSrc === newImageOrSrc) || !hostEl) {
            return image;
        }

        // Only when there is no existent image or existent image src
        // is different, this method is responsible for load.
        var cachedImgObj = globalImageCache.get(newImageOrSrc);

        var pendingWrap = {hostEl: hostEl, cb: cb, cbPayload: cbPayload};

        if (cachedImgObj) {
            image = cachedImgObj.image;
            !isImageReady(image) && cachedImgObj.pending.push(pendingWrap);
        }
        else {
            image = new Image();
            image.onload = image.onerror = imageOnLoad;

            globalImageCache.put(
                newImageOrSrc,
                image.__cachedImgObj = {
                    image: image,
                    pending: [pendingWrap]
                }
            );

            image.src = image.__zrImageSrc = newImageOrSrc;
        }

        return image;
    }
    // newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvas
    else {
        return newImageOrSrc;
    }
}

function imageOnLoad() {
    var cachedImgObj = this.__cachedImgObj;
    this.onload = this.onerror = this.__cachedImgObj = null;

    for (var i = 0; i < cachedImgObj.pending.length; i++) {
        var pendingWrap = cachedImgObj.pending[i];
        var cb = pendingWrap.cb;
        cb && cb(this, pendingWrap.cbPayload);
        pendingWrap.hostEl.dirty();
    }
    cachedImgObj.pending.length = 0;
}

function isImageReady(image) {
    return image && image.width && image.height;
}

var textWidthCache = {};
var textWidthCacheCounter = 0;

var TEXT_CACHE_MAX = 5000;
var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g;

var DEFAULT_FONT$1 = '12px sans-serif';

// Avoid assign to an exported variable, for transforming to cjs.
var methods$1 = {};

function $override$1(name, fn) {
    methods$1[name] = fn;
}

/**
 * @public
 * @param {string} text
 * @param {string} font
 * @return {number} width
 */
function getWidth(text, font) {
    font = font || DEFAULT_FONT$1;
    var key = text + ':' + font;
    if (textWidthCache[key]) {
        return textWidthCache[key];
    }

    var textLines = (text + '').split('\n');
    var width = 0;

    for (var i = 0, l = textLines.length; i < l; i++) {
        // textContain.measureText may be overrided in SVG or VML
        width = Math.max(measureText(textLines[i], font).width, width);
    }

    if (textWidthCacheCounter > TEXT_CACHE_MAX) {
        textWidthCacheCounter = 0;
        textWidthCache = {};
    }
    textWidthCacheCounter++;
    textWidthCache[key] = width;

    return width;
}

/**
 * @public
 * @param {string} text
 * @param {string} font
 * @param {string} [textAlign='left']
 * @param {string} [textVerticalAlign='top']
 * @param {Array.<number>} [textPadding]
 * @param {Object} [rich]
 * @param {Object} [truncate]
 * @return {Object} {x, y, width, height, lineHeight}
 */
function getBoundingRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate) {
    return rich
        ? getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate)
        : getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, truncate);
}

function getPlainTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, truncate) {
    var contentBlock = parsePlainText(text, font, textPadding, textLineHeight, truncate);
    var outerWidth = getWidth(text, font);
    if (textPadding) {
        outerWidth += textPadding[1] + textPadding[3];
    }
    var outerHeight = contentBlock.outerHeight;

    var x = adjustTextX(0, outerWidth, textAlign);
    var y = adjustTextY(0, outerHeight, textVerticalAlign);

    var rect = new BoundingRect(x, y, outerWidth, outerHeight);
    rect.lineHeight = contentBlock.lineHeight;

    return rect;
}

function getRichTextRect(text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate) {
    var contentBlock = parseRichText(text, {
        rich: rich,
        truncate: truncate,
        font: font,
        textAlign: textAlign,
        textPadding: textPadding,
        textLineHeight: textLineHeight
    });
    var outerWidth = contentBlock.outerWidth;
    var outerHeight = contentBlock.outerHeight;

    var x = adjustTextX(0, outerWidth, textAlign);
    var y = adjustTextY(0, outerHeight, textVerticalAlign);

    return new BoundingRect(x, y, outerWidth, outerHeight);
}

/**
 * @public
 * @param {number} x
 * @param {number} width
 * @param {string} [textAlign='left']
 * @return {number} Adjusted x.
 */
function adjustTextX(x, width, textAlign) {
    // FIXME Right to left language
    if (textAlign === 'right') {
        x -= width;
    }
    else if (textAlign === 'center') {
        x -= width / 2;
    }
    return x;
}

/**
 * @public
 * @param {number} y
 * @param {number} height
 * @param {string} [textVerticalAlign='top']
 * @return {number} Adjusted y.
 */
function adjustTextY(y, height, textVerticalAlign) {
    if (textVerticalAlign === 'middle') {
        y -= height / 2;
    }
    else if (textVerticalAlign === 'bottom') {
        y -= height;
    }
    return y;
}

/**
 * Follow same interface to `Displayable.prototype.calculateTextPosition`.
 * @public
 * @param {Obejct} [out] Prepared out object. If not input, auto created in the method.
 * @param {module:zrender/graphic/Style} style where `textPosition` and `textDistance` are visited.
 * @param {Object} rect {x, y, width, height} Rect of the host elment, according to which the text positioned.
 * @return {Object} The input `out`. Set: {x, y, textAlign, textVerticalAlign}
 */
function calculateTextPosition(out, style, rect) {
    var textPosition = style.textPosition;
    var distance = style.textDistance;

    var x = rect.x;
    var y = rect.y;
    distance = distance || 0;

    var height = rect.height;
    var width = rect.width;
    var halfHeight = height / 2;

    var textAlign = 'left';
    var textVerticalAlign = 'top';

    switch (textPosition) {
        case 'left':
            x -= distance;
            y += halfHeight;
            textAlign = 'right';
            textVerticalAlign = 'middle';
            break;
        case 'right':
            x += distance + width;
            y += halfHeight;
            textVerticalAlign = 'middle';
            break;
        case 'top':
            x += width / 2;
            y -= distance;
            textAlign = 'center';
            textVerticalAlign = 'bottom';
            break;
        case 'bottom':
            x += width / 2;
            y += height + distance;
            textAlign = 'center';
            break;
        case 'inside':
            x += width / 2;
            y += halfHeight;
            textAlign = 'center';
            textVerticalAlign = 'middle';
            break;
        case 'insideLeft':
            x += distance;
            y += halfHeight;
            textVerticalAlign = 'middle';
            break;
        case 'insideRight':
            x += width - distance;
            y += halfHeight;
            textAlign = 'right';
            textVerticalAlign = 'middle';
            break;
        case 'insideTop':
            x += width / 2;
            y += distance;
            textAlign = 'center';
            break;
        case 'insideBottom':
            x += width / 2;
            y += height - distance;
            textAlign = 'center';
            textVerticalAlign = 'bottom';
            break;
        case 'insideTopLeft':
            x += distance;
            y += distance;
            break;
        case 'insideTopRight':
            x += width - distance;
            y += distance;
            textAlign = 'right';
            break;
        case 'insideBottomLeft':
            x += distance;
            y += height - distance;
            textVerticalAlign = 'bottom';
            break;
        case 'insideBottomRight':
            x += width - distance;
            y += height - distance;
            textAlign = 'right';
            textVerticalAlign = 'bottom';
            break;
    }

    out = out || {};
    out.x = x;
    out.y = y;
    out.textAlign = textAlign;
    out.textVerticalAlign = textVerticalAlign;

    return out;
}

/**
 * To be removed. But still do not remove in case that some one has imported it.
 * @deprecated
 * @public
 * @param {stirng} textPosition
 * @param {Object} rect {x, y, width, height}
 * @param {number} distance
 * @return {Object} {x, y, textAlign, textVerticalAlign}
 */


/**
 * Show ellipsis if overflow.
 *
 * @public
 * @param  {string} text
 * @param  {string} containerWidth
 * @param  {string} font
 * @param  {number} [ellipsis='...']
 * @param  {Object} [options]
 * @param  {number} [options.maxIterations=3]
 * @param  {number} [options.minChar=0] If truncate result are less
 *                  then minChar, ellipsis will not show, which is
 *                  better for user hint in some cases.
 * @param  {number} [options.placeholder=''] When all truncated, use the placeholder.
 * @return {string}
 */
function truncateText(text, containerWidth, font, ellipsis, options) {
    if (!containerWidth) {
        return '';
    }

    var textLines = (text + '').split('\n');
    options = prepareTruncateOptions(containerWidth, font, ellipsis, options);

    // FIXME
    // It is not appropriate that every line has '...' when truncate multiple lines.
    for (var i = 0, len = textLines.length; i < len; i++) {
        textLines[i] = truncateSingleLine(textLines[i], options);
    }

    return textLines.join('\n');
}

function prepareTruncateOptions(containerWidth, font, ellipsis, options) {
    options = extend({}, options);

    options.font = font;
    var ellipsis = retrieve2(ellipsis, '...');
    options.maxIterations = retrieve2(options.maxIterations, 2);
    var minChar = options.minChar = retrieve2(options.minChar, 0);
    // FIXME
    // Other languages?
    options.cnCharWidth = getWidth('国', font);
    // FIXME
    // Consider proportional font?
    var ascCharWidth = options.ascCharWidth = getWidth('a', font);
    options.placeholder = retrieve2(options.placeholder, '');

    // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'.
    // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'.
    var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap.
    for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
        contentWidth -= ascCharWidth;
    }

    var ellipsisWidth = getWidth(ellipsis, font);
    if (ellipsisWidth > contentWidth) {
        ellipsis = '';
        ellipsisWidth = 0;
    }

    contentWidth = containerWidth - ellipsisWidth;

    options.ellipsis = ellipsis;
    options.ellipsisWidth = ellipsisWidth;
    options.contentWidth = contentWidth;
    options.containerWidth = containerWidth;

    return options;
}

function truncateSingleLine(textLine, options) {
    var containerWidth = options.containerWidth;
    var font = options.font;
    var contentWidth = options.contentWidth;

    if (!containerWidth) {
        return '';
    }

    var lineWidth = getWidth(textLine, font);

    if (lineWidth <= containerWidth) {
        return textLine;
    }

    for (var j = 0; ; j++) {
        if (lineWidth <= contentWidth || j >= options.maxIterations) {
            textLine += options.ellipsis;
            break;
        }

        var subLength = j === 0
            ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth)
            : lineWidth > 0
            ? Math.floor(textLine.length * contentWidth / lineWidth)
            : 0;

        textLine = textLine.substr(0, subLength);
        lineWidth = getWidth(textLine, font);
    }

    if (textLine === '') {
        textLine = options.placeholder;
    }

    return textLine;
}

function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
    var width = 0;
    var i = 0;
    for (var len = text.length; i < len && width < contentWidth; i++) {
        var charCode = text.charCodeAt(i);
        width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth;
    }
    return i;
}

/**
 * @public
 * @param {string} font
 * @return {number} line height
 */
function getLineHeight(font) {
    // FIXME A rough approach.
    return getWidth('国', font);
}

/**
 * @public
 * @param {string} text
 * @param {string} font
 * @return {Object} width
 */
function measureText(text, font) {
    return methods$1.measureText(text, font);
}

// Avoid assign to an exported variable, for transforming to cjs.
methods$1.measureText = function (text, font) {
    var ctx = getContext();
    ctx.font = font || DEFAULT_FONT$1;
    return ctx.measureText(text);
};

/**
 * @public
 * @param {string} text
 * @param {string} font
 * @param {Object} [truncate]
 * @return {Object} block: {lineHeight, lines, height, outerHeight, canCacheByTextString}
 *  Notice: for performance, do not calculate outerWidth util needed.
 *  `canCacheByTextString` means the result `lines` is only determined by the input `text`.
 *  Thus we can simply comparing the `input` text to determin whether the result changed,
 *  without travel the result `lines`.
 */
function parsePlainText(text, font, padding, textLineHeight, truncate) {
    text != null && (text += '');

    var lineHeight = retrieve2(textLineHeight, getLineHeight(font));
    var lines = text ? text.split('\n') : [];
    var height = lines.length * lineHeight;
    var outerHeight = height;
    var canCacheByTextString = true;

    if (padding) {
        outerHeight += padding[0] + padding[2];
    }

    if (text && truncate) {
        canCacheByTextString = false;
        var truncOuterHeight = truncate.outerHeight;
        var truncOuterWidth = truncate.outerWidth;
        if (truncOuterHeight != null && outerHeight > truncOuterHeight) {
            text = '';
            lines = [];
        }
        else if (truncOuterWidth != null) {
            var options = prepareTruncateOptions(
                truncOuterWidth - (padding ? padding[1] + padding[3] : 0),
                font,
                truncate.ellipsis,
                {minChar: truncate.minChar, placeholder: truncate.placeholder}
            );

            // FIXME
            // It is not appropriate that every line has '...' when truncate multiple lines.
            for (var i = 0, len = lines.length; i < len; i++) {
                lines[i] = truncateSingleLine(lines[i], options);
            }
        }
    }

    return {
        lines: lines,
        height: height,
        outerHeight: outerHeight,
        lineHeight: lineHeight,
        canCacheByTextString: canCacheByTextString
    };
}

/**
 * For example: 'some text {a|some text}other text{b|some text}xxx{c|}xxx'
 * Also consider 'bbbb{a|xxx\nzzz}xxxx\naaaa'.
 *
 * @public
 * @param {string} text
 * @param {Object} style
 * @return {Object} block
 * {
 *      width,
 *      height,
 *      lines: [{
 *          lineHeight,
 *          width,
 *          tokens: [[{
 *              styleName,
 *              text,
 *              width,      // include textPadding
 *              height,     // include textPadding
 *              textWidth, // pure text width
 *              textHeight, // pure text height
 *              lineHeihgt,
 *              font,
 *              textAlign,
 *              textVerticalAlign
 *          }], [...], ...]
 *      }, ...]
 * }
 * If styleName is undefined, it is plain text.
 */
function parseRichText(text, style) {
    var contentBlock = {lines: [], width: 0, height: 0};

    text != null && (text += '');
    if (!text) {
        return contentBlock;
    }

    var lastIndex = STYLE_REG.lastIndex = 0;
    var result;
    while ((result = STYLE_REG.exec(text)) != null) {
        var matchedIndex = result.index;
        if (matchedIndex > lastIndex) {
            pushTokens(contentBlock, text.substring(lastIndex, matchedIndex));
        }
        pushTokens(contentBlock, result[2], result[1]);
        lastIndex = STYLE_REG.lastIndex;
    }

    if (lastIndex < text.length) {
        pushTokens(contentBlock, text.substring(lastIndex, text.length));
    }

    var lines = contentBlock.lines;
    var contentHeight = 0;
    var contentWidth = 0;
    // For `textWidth: 100%`
    var pendingList = [];

    var stlPadding = style.textPadding;

    var truncate = style.truncate;
    var truncateWidth = truncate && truncate.outerWidth;
    var truncateHeight = truncate && truncate.outerHeight;
    if (stlPadding) {
        truncateWidth != null && (truncateWidth -= stlPadding[1] + stlPadding[3]);
        truncateHeight != null && (truncateHeight -= stlPadding[0] + stlPadding[2]);
    }

    // Calculate layout info of tokens.
    for (var i = 0; i < lines.length; i++) {
        var line = lines[i];
        var lineHeight = 0;
        var lineWidth = 0;

        for (var j = 0; j < line.tokens.length; j++) {
            var token = line.tokens[j];
            var tokenStyle = token.styleName && style.rich[token.styleName] || {};
            // textPadding should not inherit from style.
            var textPadding = token.textPadding = tokenStyle.textPadding;

            // textFont has been asigned to font by `normalizeStyle`.
            var font = token.font = tokenStyle.font || style.font;

            // textHeight can be used when textVerticalAlign is specified in token.
            var tokenHeight = token.textHeight = retrieve2(
                // textHeight should not be inherited, consider it can be specified
                // as box height of the block.
                tokenStyle.textHeight, getLineHeight(font)
            );
            textPadding && (tokenHeight += textPadding[0] + textPadding[2]);
            token.height = tokenHeight;
            token.lineHeight = retrieve3(
                tokenStyle.textLineHeight, style.textLineHeight, tokenHeight
            );

            token.textAlign = tokenStyle && tokenStyle.textAlign || style.textAlign;
            token.textVerticalAlign = tokenStyle && tokenStyle.textVerticalAlign || 'middle';

            if (truncateHeight != null && contentHeight + token.lineHeight > truncateHeight) {
                return {lines: [], width: 0, height: 0};
            }

            token.textWidth = getWidth(token.text, font);
            var tokenWidth = tokenStyle.textWidth;
            var tokenWidthNotSpecified = tokenWidth == null || tokenWidth === 'auto';

            // Percent width, can be `100%`, can be used in drawing separate
            // line when box width is needed to be auto.
            if (typeof tokenWidth === 'string' && tokenWidth.charAt(tokenWidth.length - 1) === '%') {
                token.percentWidth = tokenWidth;
                pendingList.push(token);
                tokenWidth = 0;
                // Do not truncate in this case, because there is no user case
                // and it is too complicated.
            }
            else {
                if (tokenWidthNotSpecified) {
                    tokenWidth = token.textWidth;

                    // FIXME: If image is not loaded and textWidth is not specified, calling
                    // `getBoundingRect()` will not get correct result.
                    var textBackgroundColor = tokenStyle.textBackgroundColor;
                    var bgImg = textBackgroundColor && textBackgroundColor.image;

                    // Use cases:
                    // (1) If image is not loaded, it will be loaded at render phase and call
                    // `dirty()` and `textBackgroundColor.image` will be replaced with the loaded
                    // image, and then the right size will be calculated here at the next tick.
                    // See `graphic/helper/text.js`.
                    // (2) If image loaded, and `textBackgroundColor.image` is image src string,
                    // use `imageHelper.findExistImage` to find cached image.
                    // `imageHelper.findExistImage` will always be called here before
                    // `imageHelper.createOrUpdateImage` in `graphic/helper/text.js#renderRichText`
                    // which ensures that image will not be rendered before correct size calcualted.
                    if (bgImg) {
                        bgImg = findExistImage(bgImg);
                        if (isImageReady(bgImg)) {
                            tokenWidth = Math.max(tokenWidth, bgImg.width * tokenHeight / bgImg.height);
                        }
                    }
                }

                var paddingW = textPadding ? textPadding[1] + textPadding[3] : 0;
                tokenWidth += paddingW;

                var remianTruncWidth = truncateWidth != null ? truncateWidth - lineWidth : null;

                if (remianTruncWidth != null && remianTruncWidth < tokenWidth) {
                    if (!tokenWidthNotSpecified || remianTruncWidth < paddingW) {
                        token.text = '';
                        token.textWidth = tokenWidth = 0;
                    }
                    else {
                        token.text = truncateText(
                            token.text, remianTruncWidth - paddingW, font, truncate.ellipsis,
                            {minChar: truncate.minChar}
                        );
                        token.textWidth = getWidth(token.text, font);
                        tokenWidth = token.textWidth + paddingW;
                    }
                }
            }

            lineWidth += (token.width = tokenWidth);
            tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight));
        }

        line.width = lineWidth;
        line.lineHeight = lineHeight;
        contentHeight += lineHeight;
        contentWidth = Math.max(contentWidth, lineWidth);
    }

    contentBlock.outerWidth = contentBlock.width = retrieve2(style.textWidth, contentWidth);
    contentBlock.outerHeight = contentBlock.height = retrieve2(style.textHeight, contentHeight);

    if (stlPadding) {
        contentBlock.outerWidth += stlPadding[1] + stlPadding[3];
        contentBlock.outerHeight += stlPadding[0] + stlPadding[2];
    }

    for (var i = 0; i < pendingList.length; i++) {
        var token = pendingList[i];
        var percentWidth = token.percentWidth;
        // Should not base on outerWidth, because token can not be placed out of padding.
        token.width = parseInt(percentWidth, 10) / 100 * contentWidth;
    }

    return contentBlock;
}

function pushTokens(block, str, styleName) {
    var isEmptyStr = str === '';
    var strs = str.split('\n');
    var lines = block.lines;

    for (var i = 0; i < strs.length; i++) {
        var text = strs[i];
        var token = {
            styleName: styleName,
            text: text,
            isLineHolder: !text && !isEmptyStr
        };

        // The first token should be appended to the last line.
        if (!i) {
            var tokens = (lines[lines.length - 1] || (lines[0] = {tokens: []})).tokens;

            // Consider cases:
            // (1) ''.split('\n') => ['', '\n', ''], the '' at the first item
            // (which is a placeholder) should be replaced by new token.
            // (2) A image backage, where token likes {a|}.
            // (3) A redundant '' will affect textAlign in line.
            // (4) tokens with the same tplName should not be merged, because
            // they should be displayed in different box (with border and padding).
            var tokensLen = tokens.length;
            (tokensLen === 1 && tokens[0].isLineHolder)
                ? (tokens[0] = token)
                // Consider text is '', only insert when it is the "lineHolder" or
                // "emptyStr". Otherwise a redundant '' will affect textAlign in line.
                : ((text || !tokensLen || isEmptyStr) && tokens.push(token));
        }
        // Other tokens always start a new line.
        else {
            // If there is '', insert it as a placeholder.
            lines.push({tokens: [token]});
        }
    }
}

function makeFont(style) {
    // FIXME in node-canvas fontWeight is before fontStyle
    // Use `fontSize` `fontFamily` to check whether font properties are defined.
    var font = (style.fontSize || style.fontFamily) && [
        style.fontStyle,
        style.fontWeight,
        (style.fontSize || 12) + 'px',
        // If font properties are defined, `fontFamily` should not be ignored.
        style.fontFamily || 'sans-serif'
    ].join(' ');
    return font && trim(font) || style.textFont || style.font;
}

/**
 * @param {Object} ctx
 * @param {Object} shape
 * @param {number} shape.x
 * @param {number} shape.y
 * @param {number} shape.width
 * @param {number} shape.height
 * @param {number} shape.r
 */
function buildPath(ctx, shape) {
    var x = shape.x;
    var y = shape.y;
    var width = shape.width;
    var height = shape.height;
    var r = shape.r;
    var r1;
    var r2;
    var r3;
    var r4;

    // Convert width and height to positive for better borderRadius
    if (width < 0) {
        x = x + width;
        width = -width;
    }
    if (height < 0) {
        y = y + height;
        height = -height;
    }

    if (typeof r === 'number') {
        r1 = r2 = r3 = r4 = r;
    }
    else if (r instanceof Array) {
        if (r.length === 1) {
            r1 = r2 = r3 = r4 = r[0];
        }
        else if (r.length === 2) {
            r1 = r3 = r[0];
            r2 = r4 = r[1];
        }
        else if (r.length === 3) {
            r1 = r[0];
            r2 = r4 = r[1];
            r3 = r[2];
        }
        else {
            r1 = r[0];
            r2 = r[1];
            r3 = r[2];
            r4 = r[3];
        }
    }
    else {
        r1 = r2 = r3 = r4 = 0;
    }

    var total;
    if (r1 + r2 > width) {
        total = r1 + r2;
        r1 *= width / total;
        r2 *= width / total;
    }
    if (r3 + r4 > width) {
        total = r3 + r4;
        r3 *= width / total;
        r4 *= width / total;
    }
    if (r2 + r3 > height) {
        total = r2 + r3;
        r2 *= height / total;
        r3 *= height / total;
    }
    if (r1 + r4 > height) {
        total = r1 + r4;
        r1 *= height / total;
        r4 *= height / total;
    }
    ctx.moveTo(x + r1, y);
    ctx.lineTo(x + width - r2, y);
    r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r3);
    r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2);
    ctx.lineTo(x + r4, y + height);
    r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r1);
    r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5);
}

var DEFAULT_FONT = DEFAULT_FONT$1;

// TODO: Have not support 'start', 'end' yet.
var VALID_TEXT_ALIGN = {left: 1, right: 1, center: 1};
var VALID_TEXT_VERTICAL_ALIGN = {top: 1, bottom: 1, middle: 1};
// Different from `STYLE_COMMON_PROPS` of `graphic/Style`,
// the default value of shadowColor is `'transparent'`.
var SHADOW_STYLE_COMMON_PROPS = [
    ['textShadowBlur', 'shadowBlur', 0],
    ['textShadowOffsetX', 'shadowOffsetX', 0],
    ['textShadowOffsetY', 'shadowOffsetY', 0],
    ['textShadowColor', 'shadowColor', 'transparent']
];
var _tmpTextPositionResult = {};
var _tmpBoxPositionResult = {};

/**
 * @param {module:zrender/graphic/Style} style
 * @return {module:zrender/graphic/Style} The input style.
 */
function normalizeTextStyle(style) {
    normalizeStyle(style);
    each$1(style.rich, normalizeStyle);
    return style;
}

function normalizeStyle(style) {
    if (style) {

        style.font = makeFont(style);

        var textAlign = style.textAlign;
        textAlign === 'middle' && (textAlign = 'center');
        style.textAlign = (
            textAlign == null || VALID_TEXT_ALIGN[textAlign]
        ) ? textAlign : 'left';

        // Compatible with textBaseline.
        var textVerticalAlign = style.textVerticalAlign || style.textBaseline;
        textVerticalAlign === 'center' && (textVerticalAlign = 'middle');
        style.textVerticalAlign = (
            textVerticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[textVerticalAlign]
        ) ? textVerticalAlign : 'top';

        var textPadding = style.textPadding;
        if (textPadding) {
            style.textPadding = normalizeCssArray(style.textPadding);
        }
    }
}

/**
 * @param {CanvasRenderingContext2D} ctx
 * @param {string} text
 * @param {module:zrender/graphic/Style} style
 * @param {Object|boolean} [rect] {x, y, width, height}
 *                  If set false, rect text is not used.
 * @param {Element|module:zrender/graphic/helper/constant.WILL_BE_RESTORED} [prevEl] For ctx prop cache.
 */
function renderText(hostEl, ctx, text, style, rect, prevEl) {
    style.rich
        ? renderRichText(hostEl, ctx, text, style, rect, prevEl)
        : renderPlainText(hostEl, ctx, text, style, rect, prevEl);
}

// Avoid setting to ctx according to prevEl if possible for
// performance in scenarios of large amount text.
function renderPlainText(hostEl, ctx, text, style, rect, prevEl) {
    'use strict';

    var needDrawBg = needDrawBackground(style);

    var prevStyle;
    var checkCache = false;
    var cachedByMe = ctx.__attrCachedBy === ContextCachedBy.PLAIN_TEXT;

    // Only take and check cache for `Text` el, but not RectText.
    if (prevEl !== WILL_BE_RESTORED) {
        if (prevEl) {
            prevStyle = prevEl.style;
            checkCache = !needDrawBg && cachedByMe && prevStyle;
        }

        // Prevent from using cache in `Style::bind`, because of the case:
        // ctx property is modified by other properties than `Style::bind`
        // used, and Style::bind is called next.
        ctx.__attrCachedBy = needDrawBg ? ContextCachedBy.NONE : ContextCachedBy.PLAIN_TEXT;
    }
    // Since this will be restored, prevent from using these props to check cache in the next
    // entering of this method. But do not need to clear other cache like `Style::bind`.
    else if (cachedByMe) {
        ctx.__attrCachedBy = ContextCachedBy.NONE;
    }

    var styleFont = style.font || DEFAULT_FONT;
    // PENDING
    // Only `Text` el set `font` and keep it (`RectText` will restore). So theoretically
    // we can make font cache on ctx, which can cache for text el that are discontinuous.
    // But layer save/restore needed to be considered.
    // if (styleFont !== ctx.__fontCache) {
    //     ctx.font = styleFont;
    //     if (prevEl !== WILL_BE_RESTORED) {
    //         ctx.__fontCache = styleFont;
    //     }
    // }
    if (!checkCache || styleFont !== (prevStyle.font || DEFAULT_FONT)) {
        ctx.font = styleFont;
    }

    // Use the final font from context-2d, because the final
    // font might not be the style.font when it is illegal.
    // But get `ctx.font` might be time consuming.
    var computedFont = hostEl.__computedFont;
    if (hostEl.__styleFont !== styleFont) {
        hostEl.__styleFont = styleFont;
        computedFont = hostEl.__computedFont = ctx.font;
    }

    var textPadding = style.textPadding;
    var textLineHeight = style.textLineHeight;

    var contentBlock = hostEl.__textCotentBlock;
    if (!contentBlock || hostEl.__dirtyText) {
        contentBlock = hostEl.__textCotentBlock = parsePlainText(
            text, computedFont, textPadding, textLineHeight, style.truncate
        );
    }

    var outerHeight = contentBlock.outerHeight;

    var textLines = contentBlock.lines;
    var lineHeight = contentBlock.lineHeight;

    var boxPos = getBoxPosition(_tmpBoxPositionResult, hostEl, style, rect);
    var baseX = boxPos.baseX;
    var baseY = boxPos.baseY;
    var textAlign = boxPos.textAlign || 'left';
    var textVerticalAlign = boxPos.textVerticalAlign;

    // Origin of textRotation should be the base point of text drawing.
    applyTextRotation(ctx, style, rect, baseX, baseY);

    var boxY = adjustTextY(baseY, outerHeight, textVerticalAlign);
    var textX = baseX;
    var textY = boxY;

    if (needDrawBg || textPadding) {
        // Consider performance, do not call getTextWidth util necessary.
        var textWidth = getWidth(text, computedFont);
        var outerWidth = textWidth;
        textPadding && (outerWidth += textPadding[1] + textPadding[3]);
        var boxX = adjustTextX(baseX, outerWidth, textAlign);

        needDrawBg && drawBackground(hostEl, ctx, style, boxX, boxY, outerWidth, outerHeight);

        if (textPadding) {
            textX = getTextXForPadding(baseX, textAlign, textPadding);
            textY += textPadding[0];
        }
    }

    // Always set textAlign and textBase line, because it is difficute to calculate
    // textAlign from prevEl, and we dont sure whether textAlign will be reset if
    // font set happened.
    ctx.textAlign = textAlign;
    // Force baseline to be "middle". Otherwise, if using "top", the
    // text will offset downward a little bit in font "Microsoft YaHei".
    ctx.textBaseline = 'middle';
    // Set text opacity
    ctx.globalAlpha = style.opacity || 1;

    // Always set shadowBlur and shadowOffset to avoid leak from displayable.
    for (var i = 0; i < SHADOW_STYLE_COMMON_PROPS.length; i++) {
        var propItem = SHADOW_STYLE_COMMON_PROPS[i];
        var styleProp = propItem[0];
        var ctxProp = propItem[1];
        var val = style[styleProp];
        if (!checkCache || val !== prevStyle[styleProp]) {
            ctx[ctxProp] = fixShadow(ctx, ctxProp, val || propItem[2]);
        }
    }

    // `textBaseline` is set as 'middle'.
    textY += lineHeight / 2;

    var textStrokeWidth = style.textStrokeWidth;
    var textStrokeWidthPrev = checkCache ? prevStyle.textStrokeWidth : null;
    var strokeWidthChanged = !checkCache || textStrokeWidth !== textStrokeWidthPrev;
    var strokeChanged = !checkCache || strokeWidthChanged || style.textStroke !== prevStyle.textStroke;
    var textStroke = getStroke(style.textStroke, textStrokeWidth);
    var textFill = getFill(style.textFill);

    if (textStroke) {
        if (strokeWidthChanged) {
            ctx.lineWidth = textStrokeWidth;
        }
        if (strokeChanged) {
            ctx.strokeStyle = textStroke;
        }
    }
    if (textFill) {
        if (!checkCache || style.textFill !== prevStyle.textFill) {
            ctx.fillStyle = textFill;
        }
    }

    // Optimize simply, in most cases only one line exists.
    if (textLines.length === 1) {
        // Fill after stroke so the outline will not cover the main part.
        textStroke && ctx.strokeText(textLines[0], textX, textY);
        textFill && ctx.fillText(textLines[0], textX, textY);
    }
    else {
        for (var i = 0; i < textLines.length; i++) {
            // Fill after stroke so the outline will not cover the main part.
            textStroke && ctx.strokeText(textLines[i], textX, textY);
            textFill && ctx.fillText(textLines[i], textX, textY);
            textY += lineHeight;
        }
    }
}

function renderRichText(hostEl, ctx, text, style, rect, prevEl) {
    // Do not do cache for rich text because of the complexity.
    // But `RectText` this will be restored, do not need to clear other cache like `Style::bind`.
    if (prevEl !== WILL_BE_RESTORED) {
        ctx.__attrCachedBy = ContextCachedBy.NONE;
    }

    var contentBlock = hostEl.__textCotentBlock;

    if (!contentBlock || hostEl.__dirtyText) {
        contentBlock = hostEl.__textCotentBlock = parseRichText(text, style);
    }

    drawRichText(hostEl, ctx, contentBlock, style, rect);
}

function drawRichText(hostEl, ctx, contentBlock, style, rect) {
    var contentWidth = contentBlock.width;
    var outerWidth = contentBlock.outerWidth;
    var outerHeight = contentBlock.outerHeight;
    var textPadding = style.textPadding;

    var boxPos = getBoxPosition(_tmpBoxPositionResult, hostEl, style, rect);
    var baseX = boxPos.baseX;
    var baseY = boxPos.baseY;
    var textAlign = boxPos.textAlign;
    var textVerticalAlign = boxPos.textVerticalAlign;

    // Origin of textRotation should be the base point of text drawing.
    applyTextRotation(ctx, style, rect, baseX, baseY);

    var boxX = adjustTextX(baseX, outerWidth, textAlign);
    var boxY = adjustTextY(baseY, outerHeight, textVerticalAlign);
    var xLeft = boxX;
    var lineTop = boxY;
    if (textPadding) {
        xLeft += textPadding[3];
        lineTop += textPadding[0];
    }
    var xRight = xLeft + contentWidth;

    needDrawBackground(style) && drawBackground(
        hostEl, ctx, style, boxX, boxY, outerWidth, outerHeight
    );

    for (var i = 0; i < contentBlock.lines.length; i++) {
        var line = contentBlock.lines[i];
        var tokens = line.tokens;
        var tokenCount = tokens.length;
        var lineHeight = line.lineHeight;
        var usedWidth = line.width;

        var leftIndex = 0;
        var lineXLeft = xLeft;
        var lineXRight = xRight;
        var rightIndex = tokenCount - 1;
        var token;

        while (
            leftIndex < tokenCount
            && (token = tokens[leftIndex], !token.textAlign || token.textAlign === 'left')
        ) {
            placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXLeft, 'left');
            usedWidth -= token.width;
            lineXLeft += token.width;
            leftIndex++;
        }

        while (
            rightIndex >= 0
            && (token = tokens[rightIndex], token.textAlign === 'right')
        ) {
            placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXRight, 'right');
            usedWidth -= token.width;
            lineXRight -= token.width;
            rightIndex--;
        }

        // The other tokens are placed as textAlign 'center' if there is enough space.
        lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - usedWidth) / 2;
        while (leftIndex <= rightIndex) {
            token = tokens[leftIndex];
            // Consider width specified by user, use 'center' rather than 'left'.
            placeToken(hostEl, ctx, token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center');
            lineXLeft += token.width;
            leftIndex++;
        }

        lineTop += lineHeight;
    }
}

function applyTextRotation(ctx, style, rect, x, y) {
    // textRotation only apply in RectText.
    if (rect && style.textRotation) {
        var origin = style.textOrigin;
        if (origin === 'center') {
            x = rect.width / 2 + rect.x;
            y = rect.height / 2 + rect.y;
        }
        else if (origin) {
            x = origin[0] + rect.x;
            y = origin[1] + rect.y;
        }

        ctx.translate(x, y);
        // Positive: anticlockwise
        ctx.rotate(-style.textRotation);
        ctx.translate(-x, -y);
    }
}

function placeToken(hostEl, ctx, token, style, lineHeight, lineTop, x, textAlign) {
    var tokenStyle = style.rich[token.styleName] || {};
    tokenStyle.text = token.text;

    // 'ctx.textBaseline' is always set as 'middle', for sake of
    // the bias of "Microsoft YaHei".
    var textVerticalAlign = token.textVerticalAlign;
    var y = lineTop + lineHeight / 2;
    if (textVerticalAlign === 'top') {
        y = lineTop + token.height / 2;
    }
    else if (textVerticalAlign === 'bottom') {
        y = lineTop + lineHeight - token.height / 2;
    }

    !token.isLineHolder && needDrawBackground(tokenStyle) && drawBackground(
        hostEl,
        ctx,
        tokenStyle,
        textAlign === 'right'
            ? x - token.width
            : textAlign === 'center'
            ? x - token.width / 2
            : x,
        y - token.height / 2,
        token.width,
        token.height
    );

    var textPadding = token.textPadding;
    if (textPadding) {
        x = getTextXForPadding(x, textAlign, textPadding);
        y -= token.height / 2 - textPadding[2] - token.textHeight / 2;
    }

    setCtx(ctx, 'shadowBlur', retrieve3(tokenStyle.textShadowBlur, style.textShadowBlur, 0));
    setCtx(ctx, 'shadowColor', tokenStyle.textShadowColor || style.textShadowColor || 'transparent');
    setCtx(ctx, 'shadowOffsetX', retrieve3(tokenStyle.textShadowOffsetX, style.textShadowOffsetX, 0));
    setCtx(ctx, 'shadowOffsetY', retrieve3(tokenStyle.textShadowOffsetY, style.textShadowOffsetY, 0));

    setCtx(ctx, 'textAlign', textAlign);
    // Force baseline to be "middle". Otherwise, if using "top", the
    // text will offset downward a little bit in font "Microsoft YaHei".
    setCtx(ctx, 'textBaseline', 'middle');

    setCtx(ctx, 'font', token.font || DEFAULT_FONT);

    var textStroke = getStroke(tokenStyle.textStroke || style.textStroke, textStrokeWidth);
    var textFill = getFill(tokenStyle.textFill || style.textFill);
    var textStrokeWidth = retrieve2(tokenStyle.textStrokeWidth, style.textStrokeWidth);

    // Fill after stroke so the outline will not cover the main part.
    if (textStroke) {
        setCtx(ctx, 'lineWidth', textStrokeWidth);
        setCtx(ctx, 'strokeStyle', textStroke);
        ctx.strokeText(token.text, x, y);
    }
    if (textFill) {
        setCtx(ctx, 'fillStyle', textFill);
        ctx.fillText(token.text, x, y);
    }
}

function needDrawBackground(style) {
    return !!(
        style.textBackgroundColor
        || (style.textBorderWidth && style.textBorderColor)
    );
}

// style: {textBackgroundColor, textBorderWidth, textBorderColor, textBorderRadius, text}
// shape: {x, y, width, height}
function drawBackground(hostEl, ctx, style, x, y, width, height) {
    var textBackgroundColor = style.textBackgroundColor;
    var textBorderWidth = style.textBorderWidth;
    var textBorderColor = style.textBorderColor;
    var isPlainBg = isString(textBackgroundColor);

    setCtx(ctx, 'shadowBlur', style.textBoxShadowBlur || 0);
    setCtx(ctx, 'shadowColor', style.textBoxShadowColor || 'transparent');
    setCtx(ctx, 'shadowOffsetX', style.textBoxShadowOffsetX || 0);
    setCtx(ctx, 'shadowOffsetY', style.textBoxShadowOffsetY || 0);

    if (isPlainBg || (textBorderWidth && textBorderColor)) {
        ctx.beginPath();
        var textBorderRadius = style.textBorderRadius;
        if (!textBorderRadius) {
            ctx.rect(x, y, width, height);
        }
        else {
            buildPath(ctx, {
                x: x, y: y, width: width, height: height, r: textBorderRadius
            });
        }
        ctx.closePath();
    }

    if (isPlainBg) {
        setCtx(ctx, 'fillStyle', textBackgroundColor);

        if (style.fillOpacity != null) {
            var originalGlobalAlpha = ctx.globalAlpha;
            ctx.globalAlpha = style.fillOpacity * style.opacity;
            ctx.fill();
            ctx.globalAlpha = originalGlobalAlpha;
        }
        else {
            ctx.fill();
        }
    }
    else if (isObject$1(textBackgroundColor)) {
        var image = textBackgroundColor.image;

        image = createOrUpdateImage(
            image, null, hostEl, onBgImageLoaded, textBackgroundColor
        );
        if (image && isImageReady(image)) {
            ctx.drawImage(image, x, y, width, height);
        }
    }

    if (textBorderWidth && textBorderColor) {
        setCtx(ctx, 'lineWidth', textBorderWidth);
        setCtx(ctx, 'strokeStyle', textBorderColor);

        if (style.strokeOpacity != null) {
            var originalGlobalAlpha = ctx.globalAlpha;
            ctx.globalAlpha = style.strokeOpacity * style.opacity;
            ctx.stroke();
            ctx.globalAlpha = originalGlobalAlpha;
        }
        else {
            ctx.stroke();
        }
    }
}

function onBgImageLoaded(image, textBackgroundColor) {
    // Replace image, so that `contain/text.js#parseRichText`
    // will get correct result in next tick.
    textBackgroundColor.image = image;
}

function getBoxPosition(out, hostEl, style, rect) {
    var baseX = style.x || 0;
    var baseY = style.y || 0;
    var textAlign = style.textAlign;
    var textVerticalAlign = style.textVerticalAlign;

    // Text position represented by coord
    if (rect) {
        var textPosition = style.textPosition;
        if (textPosition instanceof Array) {
            // Percent
            baseX = rect.x + parsePercent(textPosition[0], rect.width);
            baseY = rect.y + parsePercent(textPosition[1], rect.height);
        }
        else {
            var res = (hostEl && hostEl.calculateTextPosition)
                ? hostEl.calculateTextPosition(_tmpTextPositionResult, style, rect)
                : calculateTextPosition(_tmpTextPositionResult, style, rect);
            baseX = res.x;
            baseY = res.y;
            // Default align and baseline when has textPosition
            textAlign = textAlign || res.textAlign;
            textVerticalAlign = textVerticalAlign || res.textVerticalAlign;
        }

        // textOffset is only support in RectText, otherwise
        // we have to adjust boundingRect for textOffset.
        var textOffset = style.textOffset;
        if (textOffset) {
            baseX += textOffset[0];
            baseY += textOffset[1];
        }
    }

    out = out || {};
    out.baseX = baseX;
    out.baseY = baseY;
    out.textAlign = textAlign;
    out.textVerticalAlign = textVerticalAlign;

    return out;
}


function setCtx(ctx, prop, value) {
    ctx[prop] = fixShadow(ctx, prop, value);
    return ctx[prop];
}

/**
 * @param {string} [stroke] If specified, do not check style.textStroke.
 * @param {string} [lineWidth] If specified, do not check style.textStroke.
 * @param {number} style
 */
function getStroke(stroke, lineWidth) {
    return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none')
        ? null
        // TODO pattern and gradient?
        : (stroke.image || stroke.colorStops)
        ? '#000'
        : stroke;
}

function getFill(fill) {
    return (fill == null || fill === 'none')
        ? null
        // TODO pattern and gradient?
        : (fill.image || fill.colorStops)
        ? '#000'
        : fill;
}

function parsePercent(value, maxValue) {
    if (typeof value === 'string') {
        if (value.lastIndexOf('%') >= 0) {
            return parseFloat(value) / 100 * maxValue;
        }
        return parseFloat(value);
    }
    return value;
}

function getTextXForPadding(x, textAlign, textPadding) {
    return textAlign === 'right'
        ? (x - textPadding[1])
        : textAlign === 'center'
        ? (x + textPadding[3] / 2 - textPadding[1] / 2)
        : (x + textPadding[3]);
}

/**
 * @param {string} text
 * @param {module:zrender/Style} style
 * @return {boolean}
 */
function needDrawText(text, style) {
    return text != null
        && (text
            || style.textBackgroundColor
            || (style.textBorderWidth && style.textBorderColor)
            || style.textPadding
        );
}

/**
 * Mixin for drawing text in a element bounding rect
 * @module zrender/mixin/RectText
 */

var tmpRect$1 = new BoundingRect();

var RectText = function () {};

RectText.prototype = {

    constructor: RectText,

    /**
     * Draw text in a rect with specified position.
     * @param  {CanvasRenderingContext2D} ctx
     * @param  {Object} rect Displayable rect
     */
    drawRectText: function (ctx, rect) {
        var style = this.style;

        rect = style.textRect || rect;

        // Optimize, avoid normalize every time.
        this.__dirty && normalizeTextStyle(style, true);

        var text = style.text;

        // Convert to string
        text != null && (text += '');

        if (!needDrawText(text, style)) {
            return;
        }

        // FIXME
        // Do not provide prevEl to `textHelper.renderText` for ctx prop cache,
        // but use `ctx.save()` and `ctx.restore()`. Because the cache for rect
        // text propably break the cache for its host elements.
        ctx.save();

        // Transform rect to view space
        var transform = this.transform;
        if (!style.transformText) {
            if (transform) {
                tmpRect$1.copy(rect);
                tmpRect$1.applyTransform(transform);
                rect = tmpRect$1;
            }
        }
        else {
            this.setTransform(ctx);
        }

        // transformText and textRotation can not be used at the same time.
        renderText(this, ctx, text, style, rect, WILL_BE_RESTORED);

        ctx.restore();
    }
};

/**
 * Base class of all displayable graphic objects
 * @module zrender/graphic/Displayable
 */


/**
 * @alias module:zrender/graphic/Displayable
 * @extends module:zrender/Element
 * @extends module:zrender/graphic/mixin/RectText
 */
function Displayable(opts) {

    opts = opts || {};

    Element.call(this, opts);

    // Extend properties
    for (var name in opts) {
        if (
            opts.hasOwnProperty(name)
                && name !== 'style'
        ) {
            this[name] = opts[name];
        }
    }

    /**
     * @type {module:zrender/graphic/Style}
     */
    this.style = new Style(opts.style, this);

    this._rect = null;
    // Shapes for cascade clipping.
    // Can only be `null`/`undefined` or an non-empty array, MUST NOT be an empty array.
    // because it is easy to only using null to check whether clipPaths changed.
    this.__clipPaths = null;

    // FIXME Stateful must be mixined after style is setted
    // Stateful.call(this, opts);
}

Displayable.prototype = {

    constructor: Displayable,

    type: 'displayable',

    /**
     * Dirty flag. From which painter will determine if this displayable object needs brush.
     * @name module:zrender/graphic/Displayable#__dirty
     * @type {boolean}
     */
    __dirty: true,

    /**
     * Whether the displayable object is visible. when it is true, the displayable object
     * is not drawn, but the mouse event can still trigger the object.
     * @name module:/zrender/graphic/Displayable#invisible
     * @type {boolean}
     * @default false
     */
    invisible: false,

    /**
     * @name module:/zrender/graphic/Displayable#z
     * @type {number}
     * @default 0
     */
    z: 0,

    /**
     * @name module:/zrender/graphic/Displayable#z
     * @type {number}
     * @default 0
     */
    z2: 0,

    /**
     * The z level determines the displayable object can be drawn in which layer canvas.
     * @name module:/zrender/graphic/Displayable#zlevel
     * @type {number}
     * @default 0
     */
    zlevel: 0,

    /**
     * Whether it can be dragged.
     * @name module:/zrender/graphic/Displayable#draggable
     * @type {boolean}
     * @default false
     */
    draggable: false,

    /**
     * Whether is it dragging.
     * @name module:/zrender/graphic/Displayable#draggable
     * @type {boolean}
     * @default false
     */
    dragging: false,

    /**
     * Whether to respond to mouse events.
     * @name module:/zrender/graphic/Displayable#silent
     * @type {boolean}
     * @default false
     */
    silent: false,

    /**
     * If enable culling
     * @type {boolean}
     * @default false
     */
    culling: false,

    /**
     * Mouse cursor when hovered
     * @name module:/zrender/graphic/Displayable#cursor
     * @type {string}
     */
    cursor: 'pointer',

    /**
     * If hover area is bounding rect
     * @name module:/zrender/graphic/Displayable#rectHover
     * @type {string}
     */
    rectHover: false,

    /**
     * Render the element progressively when the value >= 0,
     * usefull for large data.
     * @type {boolean}
     */
    progressive: false,

    /**
     * @type {boolean}
     */
    incremental: false,
    /**
     * Scale ratio for global scale.
     * @type {boolean}
     */
    globalScaleRatio: 1,

    beforeBrush: function (ctx) {},

    afterBrush: function (ctx) {},

    /**
     * Graphic drawing method.
     * @param {CanvasRenderingContext2D} ctx
     */
    // Interface
    brush: function (ctx, prevEl) {},

    /**
     * Get the minimum bounding box.
     * @return {module:zrender/core/BoundingRect}
     */
    // Interface
    getBoundingRect: function () {},

    /**
     * If displayable element contain coord x, y
     * @param  {number} x
     * @param  {number} y
     * @return {boolean}
     */
    contain: function (x, y) {
        return this.rectContain(x, y);
    },

    /**
     * @param  {Function} cb
     * @param  {}   context
     */
    traverse: function (cb, context) {
        cb.call(context, this);
    },

    /**
     * If bounding rect of element contain coord x, y
     * @param  {number} x
     * @param  {number} y
     * @return {boolean}
     */
    rectContain: function (x, y) {
        var coord = this.transformCoordToLocal(x, y);
        var rect = this.getBoundingRect();
        return rect.contain(coord[0], coord[1]);
    },

    /**
     * Mark displayable element dirty and refresh next frame
     */
    dirty: function () {
        this.__dirty = this.__dirtyText = true;

        this._rect = null;

        this.__zr && this.__zr.refresh();
    },

    /**
     * If displayable object binded any event
     * @return {boolean}
     */
    // TODO, events bound by bind
    // isSilent: function () {
    //     return !(
    //         this.hoverable || this.draggable
    //         || this.onmousemove || this.onmouseover || this.onmouseout
    //         || this.onmousedown || this.onmouseup || this.onclick
    //         || this.ondragenter || this.ondragover || this.ondragleave
    //         || this.ondrop
    //     );
    // },
    /**
     * Alias for animate('style')
     * @param {boolean} loop
     */
    animateStyle: function (loop) {
        return this.animate('style', loop);
    },

    attrKV: function (key, value) {
        if (key !== 'style') {
            Element.prototype.attrKV.call(this, key, value);
        }
        else {
            this.style.set(value);
        }
    },

    /**
     * @param {Object|string} key
     * @param {*} value
     */
    setStyle: function (key, value) {
        this.style.set(key, value);
        this.dirty(false);
        return this;
    },

    /**
     * Use given style object
     * @param  {Object} obj
     */
    useStyle: function (obj) {
        this.style = new Style(obj, this);
        this.dirty(false);
        return this;
    },

    /**
     * The string value of `textPosition` needs to be calculated to a real postion.
     * For example, `'inside'` is calculated to `[rect.width/2, rect.height/2]`
     * by default. See `contain/text.js#calculateTextPosition` for more details.
     * But some coutom shapes like "pin", "flag" have center that is not exactly
     * `[width/2, height/2]`. So we provide this hook to customize the calculation
     * for those shapes. It will be called if the `style.textPosition` is a string.
     * @param {Obejct} [out] Prepared out object. If not provided, this method should
     *        be responsible for creating one.
     * @param {module:zrender/graphic/Style} style
     * @param {Object} rect {x, y, width, height}
     * @return {Obejct} out The same as the input out.
     *         {
     *             x: number. mandatory.
     *             y: number. mandatory.
     *             textAlign: string. optional. use style.textAlign by default.
     *             textVerticalAlign: string. optional. use style.textVerticalAlign by default.
     *         }
     */
    calculateTextPosition: null
};

inherits(Displayable, Element);

mixin(Displayable, RectText);

/**
 * @alias zrender/graphic/Image
 * @extends module:zrender/graphic/Displayable
 * @constructor
 * @param {Object} opts
 */
function ZImage(opts) {
    Displayable.call(this, opts);
}

ZImage.prototype = {

    constructor: ZImage,

    type: 'image',

    brush: function (ctx, prevEl) {
        var style = this.style;
        var src = style.image;

        // Must bind each time
        style.bind(ctx, this, prevEl);

        var image = this._image = createOrUpdateImage(
            src,
            this._image,
            this,
            this.onload
        );

        if (!image || !isImageReady(image)) {
            return;
        }

        // 图片已经加载完成
        // if (image.nodeName.toUpperCase() == 'IMG') {
        //     if (!image.complete) {
        //         return;
        //     }
        // }
        // Else is canvas

        var x = style.x || 0;
        var y = style.y || 0;
        var width = style.width;
        var height = style.height;
        var aspect = image.width / image.height;
        if (width == null && height != null) {
            // Keep image/height ratio
            width = height * aspect;
        }
        else if (height == null && width != null) {
            height = width / aspect;
        }
        else if (width == null && height == null) {
            width = image.width;
            height = image.height;
        }

        // 设置transform
        this.setTransform(ctx);

        if (style.sWidth && style.sHeight) {
            var sx = style.sx || 0;
            var sy = style.sy || 0;
            ctx.drawImage(
                image,
                sx, sy, style.sWidth, style.sHeight,
                x, y, width, height
            );
        }
        else if (style.sx && style.sy) {
            var sx = style.sx;
            var sy = style.sy;
            var sWidth = width - sx;
            var sHeight = height - sy;
            ctx.drawImage(
                image,
                sx, sy, sWidth, sHeight,
                x, y, width, height
            );
        }
        else {
            ctx.drawImage(image, x, y, width, height);
        }

        // Draw rect text
        if (style.text != null) {
            // Only restore transform when needs draw text.
            this.restoreTransform(ctx);
            this.drawRectText(ctx, this.getBoundingRect());
        }
    },

    getBoundingRect: function () {
        var style = this.style;
        if (!this._rect) {
            this._rect = new BoundingRect(
                style.x || 0, style.y || 0, style.width || 0, style.height || 0
            );
        }
        return this._rect;
    }
};

inherits(ZImage, Displayable);

var HOVER_LAYER_ZLEVEL = 1e5;
var CANVAS_ZLEVEL = 314159;

var EL_AFTER_INCREMENTAL_INC = 0.01;
var INCREMENTAL_INC = 0.001;

function parseInt10(val) {
    return parseInt(val, 10);
}

function isLayerValid(layer) {
    if (!layer) {
        return false;
    }

    if (layer.__builtin__) {
        return true;
    }

    if (typeof (layer.resize) !== 'function'
        || typeof (layer.refresh) !== 'function'
    ) {
        return false;
    }

    return true;
}

var tmpRect = new BoundingRect(0, 0, 0, 0);
var viewRect = new BoundingRect(0, 0, 0, 0);
function isDisplayableCulled(el, width, height) {
    tmpRect.copy(el.getBoundingRect());
    if (el.transform) {
        tmpRect.applyTransform(el.transform);
    }
    viewRect.width = width;
    viewRect.height = height;
    return !tmpRect.intersect(viewRect);
}

function isClipPathChanged(clipPaths, prevClipPaths) {
    // displayable.__clipPaths can only be `null`/`undefined` or an non-empty array.
    if (clipPaths === prevClipPaths) {
        return false;
    }
    if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) {
        return true;
    }
    for (var i = 0; i < clipPaths.length; i++) {
        if (clipPaths[i] !== prevClipPaths[i]) {
            return true;
        }
    }
    return false;
}

function doClip(clipPaths, ctx) {
    for (var i = 0; i < clipPaths.length; i++) {
        var clipPath = clipPaths[i];

        clipPath.setTransform(ctx);
        ctx.beginPath();
        clipPath.buildPath(ctx, clipPath.shape);
        ctx.clip();
        // Transform back
        clipPath.restoreTransform(ctx);
    }
}

function createRoot(width, height) {
    var domRoot = document.createElement('div');

    // domRoot.onselectstart = returnFalse; // Avoid page selected
    domRoot.style.cssText = [
        'position:relative',
        // IOS13 safari probably has a compositing bug (z order of the canvas and the consequent
        // dom does not act as expected) when some of the parent dom has
        // `-webkit-overflow-scrolling: touch;` and the webpage is longer than one screen and
        // the canvas is not at the top part of the page.
        // Check `https://bugs.webkit.org/show_bug.cgi?id=203681` for more details. We remove
        // this `overflow:hidden` to avoid the bug.
        // 'overflow:hidden',
        'width:' + width + 'px',
        'height:' + height + 'px',
        'padding:0',
        'margin:0',
        'border-width:0'
    ].join(';') + ';';

    return domRoot;
}


/**
 * @alias module:zrender/Painter
 * @constructor
 * @param {HTMLElement} root 绘图容器
 * @param {module:zrender/Storage} storage
 * @param {Object} opts
 */
var Painter = function (root, storage, opts) {

    this.type = 'canvas';

    // In node environment using node-canvas
    var singleCanvas = !root.nodeName // In node ?
        || root.nodeName.toUpperCase() === 'CANVAS';

    this._opts = opts = extend({}, opts || {});

    /**
     * @type {number}
     */
    this.dpr = opts.devicePixelRatio || devicePixelRatio;
    /**
     * @type {boolean}
     * @private
     */
    this._singleCanvas = singleCanvas;
    /**
     * 绘图容器
     * @type {HTMLElement}
     */
    this.root = root;

    var rootStyle = root.style;

    if (rootStyle) {
        rootStyle['-webkit-tap-highlight-color'] = 'transparent';
        rootStyle['-webkit-user-select'] =
        rootStyle['user-select'] =
        rootStyle['-webkit-touch-callout'] = 'none';

        root.innerHTML = '';
    }

    /**
     * @type {module:zrender/Storage}
     */
    this.storage = storage;

    /**
     * @type {Array.<number>}
     * @private
     */
    var zlevelList = this._zlevelList = [];

    /**
     * @type {Object.<string, module:zrender/Layer>}
     * @private
     */
    var layers = this._layers = {};

    /**
     * @type {Object.<string, Object>}
     * @private
     */
    this._layerConfig = {};

    /**
     * zrender will do compositing when root is a canvas and have multiple zlevels.
     */
    this._needsManuallyCompositing = false;

    if (!singleCanvas) {
        this._width = this._getSize(0);
        this._height = this._getSize(1);

        var domRoot = this._domRoot = createRoot(
            this._width, this._height
        );
        root.appendChild(domRoot);
    }
    else {
        var width = root.width;
        var height = root.height;

        if (opts.width != null) {
            width = opts.width;
        }
        if (opts.height != null) {
            height = opts.height;
        }
        this.dpr = opts.devicePixelRatio || 1;

        // Use canvas width and height directly
        root.width = width * this.dpr;
        root.height = height * this.dpr;

        this._width = width;
        this._height = height;

        // Create layer if only one given canvas
        // Device can be specified to create a high dpi image.
        var mainLayer = new Layer(root, this, this.dpr);
        mainLayer.__builtin__ = true;
        mainLayer.initContext();
        // FIXME Use canvas width and height
        // mainLayer.resize(width, height);
        layers[CANVAS_ZLEVEL] = mainLayer;
        mainLayer.zlevel = CANVAS_ZLEVEL;
        // Not use common zlevel.
        zlevelList.push(CANVAS_ZLEVEL);

        this._domRoot = root;
    }

    /**
     * @type {module:zrender/Layer}
     * @private
     */
    this._hoverlayer = null;

    this._hoverElements = [];
};

Painter.prototype = {

    constructor: Painter,

    getType: function () {
        return 'canvas';
    },

    /**
     * If painter use a single canvas
     * @return {boolean}
     */
    isSingleCanvas: function () {
        return this._singleCanvas;
    },
    /**
     * @return {HTMLDivElement}
     */
    getViewportRoot: function () {
        return this._domRoot;
    },

    getViewportRootOffset: function () {
        var viewportRoot = this.getViewportRoot();
        if (viewportRoot) {
            return {
                offsetLeft: viewportRoot.offsetLeft || 0,
                offsetTop: viewportRoot.offsetTop || 0
            };
        }
    },

    /**
     * 刷新
     * @param {boolean} [paintAll=false] 强制绘制所有displayable
     */
    refresh: function (paintAll) {

        var list = this.storage.getDisplayList(true);

        var zlevelList = this._zlevelList;

        this._redrawId = Math.random();

        this._paintList(list, paintAll, this._redrawId);

        // Paint custum layers
        for (var i = 0; i < zlevelList.length; i++) {
            var z = zlevelList[i];
            var layer = this._layers[z];
            if (!layer.__builtin__ && layer.refresh) {
                var clearColor = i === 0 ? this._backgroundColor : null;
                layer.refresh(clearColor);
            }
        }

        this.refreshHover();

        return this;
    },

    addHover: function (el, hoverStyle) {
        if (el.__hoverMir) {
            return;
        }
        var elMirror = new el.constructor({
            style: el.style,
            shape: el.shape,
            z: el.z,
            z2: el.z2,
            silent: el.silent
        });
        elMirror.__from = el;
        el.__hoverMir = elMirror;
        hoverStyle && elMirror.setStyle(hoverStyle);
        this._hoverElements.push(elMirror);

        return elMirror;
    },

    removeHover: function (el) {
        var elMirror = el.__hoverMir;
        var hoverElements = this._hoverElements;
        var idx = indexOf(hoverElements, elMirror);
        if (idx >= 0) {
            hoverElements.splice(idx, 1);
        }
        el.__hoverMir = null;
    },

    clearHover: function (el) {
        var hoverElements = this._hoverElements;
        for (var i = 0; i < hoverElements.length; i++) {
            var from = hoverElements[i].__from;
            if (from) {
                from.__hoverMir = null;
            }
        }
        hoverElements.length = 0;
    },

    refreshHover: function () {
        var hoverElements = this._hoverElements;
        var len = hoverElements.length;
        var hoverLayer = this._hoverlayer;
        hoverLayer && hoverLayer.clear();

        if (!len) {
            return;
        }
        sort(hoverElements, this.storage.displayableSortFunc);

        // Use a extream large zlevel
        // FIXME?
        if (!hoverLayer) {
            hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL);
        }

        var scope = {};
        hoverLayer.ctx.save();
        for (var i = 0; i < len;) {
            var el = hoverElements[i];
            var originalEl = el.__from;
            // Original el is removed
            // PENDING
            if (!(originalEl && originalEl.__zr)) {
                hoverElements.splice(i, 1);
                originalEl.__hoverMir = null;
                len--;
                continue;
            }
            i++;

            // Use transform
            // FIXME style and shape ?
            if (!originalEl.invisible) {
                el.transform = originalEl.transform;
                el.invTransform = originalEl.invTransform;
                el.__clipPaths = originalEl.__clipPaths;
                // el.
                this._doPaintEl(el, hoverLayer, true, scope);
            }
        }

        hoverLayer.ctx.restore();
    },

    getHoverLayer: function () {
        return this.getLayer(HOVER_LAYER_ZLEVEL);
    },

    _paintList: function (list, paintAll, redrawId) {
        if (this._redrawId !== redrawId) {
            return;
        }

        paintAll = paintAll || false;

        this._updateLayerStatus(list);

        var finished = this._doPaintList(list, paintAll);

        if (this._needsManuallyCompositing) {
            this._compositeManually();
        }

        if (!finished) {
            var self = this;
            requestAnimationFrame(function () {
                self._paintList(list, paintAll, redrawId);
            });
        }
    },

    _compositeManually: function () {
        var ctx = this.getLayer(CANVAS_ZLEVEL).ctx;
        var width = this._domRoot.width;
        var height = this._domRoot.height;
        ctx.clearRect(0, 0, width, height);
        // PENDING, If only builtin layer?
        this.eachBuiltinLayer(function (layer) {
            if (layer.virtual) {
                ctx.drawImage(layer.dom, 0, 0, width, height);
            }
        });
    },

    _doPaintList: function (list, paintAll) {
        var layerList = [];
        for (var zi = 0; zi < this._zlevelList.length; zi++) {
            var zlevel = this._zlevelList[zi];
            var layer = this._layers[zlevel];
            if (layer.__builtin__
                && layer !== this._hoverlayer
                && (layer.__dirty || paintAll)
            ) {
                layerList.push(layer);
            }
        }

        var finished = true;

        for (var k = 0; k < layerList.length; k++) {
            var layer = layerList[k];
            var ctx = layer.ctx;
            var scope = {};
            ctx.save();

            var start = paintAll ? layer.__startIndex : layer.__drawIndex;

            var useTimer = !paintAll && layer.incremental && Date.now;
            var startTime = useTimer && Date.now();

            var clearColor = layer.zlevel === this._zlevelList[0]
                ? this._backgroundColor : null;
            // All elements in this layer are cleared.
            if (layer.__startIndex === layer.__endIndex) {
                layer.clear(false, clearColor);
            }
            else if (start === layer.__startIndex) {
                var firstEl = list[start];
                if (!firstEl.incremental || !firstEl.notClear || paintAll) {
                    layer.clear(false, clearColor);
                }
            }
            if (start === -1) {
                console.error('For some unknown reason. drawIndex is -1');
                start = layer.__startIndex;
            }
            for (var i = start; i < layer.__endIndex; i++) {
                var el = list[i];
                this._doPaintEl(el, layer, paintAll, scope);
                el.__dirty = el.__dirtyText = false;

                if (useTimer) {
                    // Date.now can be executed in 13,025,305 ops/second.
                    var dTime = Date.now() - startTime;
                    // Give 15 millisecond to draw.
                    // The rest elements will be drawn in the next frame.
                    if (dTime > 15) {
                        break;
                    }
                }
            }

            layer.__drawIndex = i;

            if (layer.__drawIndex < layer.__endIndex) {
                finished = false;
            }

            if (scope.prevElClipPaths) {
                // Needs restore the state. If last drawn element is in the clipping area.
                ctx.restore();
            }

            ctx.restore();
        }

        if (env$1.wxa) {
            // Flush for weixin application
            each$1(this._layers, function (layer) {
                if (layer && layer.ctx && layer.ctx.draw) {
                    layer.ctx.draw();
                }
            });
        }

        return finished;
    },

    _doPaintEl: function (el, currentLayer, forcePaint, scope) {
        var ctx = currentLayer.ctx;
        var m = el.transform;
        if (
            (currentLayer.__dirty || forcePaint)
            // Ignore invisible element
            && !el.invisible
            // Ignore transparent element
            && el.style.opacity !== 0
            // Ignore scale 0 element, in some environment like node-canvas
            // Draw a scale 0 element can cause all following draw wrong
            // And setTransform with scale 0 will cause set back transform failed.
            && !(m && !m[0] && !m[3])
            // Ignore culled element
            && !(el.culling && isDisplayableCulled(el, this._width, this._height))
        ) {

            var clipPaths = el.__clipPaths;
            var prevElClipPaths = scope.prevElClipPaths;

            // Optimize when clipping on group with several elements
            if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) {
                // If has previous clipping state, restore from it
                if (prevElClipPaths) {
                    ctx.restore();
                    scope.prevElClipPaths = null;
                    // Reset prevEl since context has been restored
                    scope.prevEl = null;
                }
                // New clipping state
                if (clipPaths) {
                    ctx.save();
                    doClip(clipPaths, ctx);
                    scope.prevElClipPaths = clipPaths;
                }
            }
            el.beforeBrush && el.beforeBrush(ctx);

            el.brush(ctx, scope.prevEl || null);
            scope.prevEl = el;

            el.afterBrush && el.afterBrush(ctx);
        }
    },

    /**
     * 获取 zlevel 所在层，如果不存在则会创建一个新的层
     * @param {number} zlevel
     * @param {boolean} virtual Virtual layer will not be inserted into dom.
     * @return {module:zrender/Layer}
     */
    getLayer: function (zlevel, virtual) {
        if (this._singleCanvas && !this._needsManuallyCompositing) {
            zlevel = CANVAS_ZLEVEL;
        }
        var layer = this._layers[zlevel];
        if (!layer) {
            // Create a new layer
            layer = new Layer('zr_' + zlevel, this, this.dpr);
            layer.zlevel = zlevel;
            layer.__builtin__ = true;

            if (this._layerConfig[zlevel]) {
                merge(layer, this._layerConfig[zlevel], true);
            }

            if (virtual) {
                layer.virtual = virtual;
            }

            this.insertLayer(zlevel, layer);

            // Context is created after dom inserted to document
            // Or excanvas will get 0px clientWidth and clientHeight
            layer.initContext();
        }

        return layer;
    },

    insertLayer: function (zlevel, layer) {

        var layersMap = this._layers;
        var zlevelList = this._zlevelList;
        var len = zlevelList.length;
        var prevLayer = null;
        var i = -1;
        var domRoot = this._domRoot;

        if (layersMap[zlevel]) {
            logError$1('ZLevel ' + zlevel + ' has been used already');
            return;
        }
        // Check if is a valid layer
        if (!isLayerValid(layer)) {
            logError$1('Layer of zlevel ' + zlevel + ' is not valid');
            return;
        }

        if (len > 0 && zlevel > zlevelList[0]) {
            for (i = 0; i < len - 1; i++) {
                if (
                    zlevelList[i] < zlevel
                    && zlevelList[i + 1] > zlevel
                ) {
                    break;
                }
            }
            prevLayer = layersMap[zlevelList[i]];
        }
        zlevelList.splice(i + 1, 0, zlevel);

        layersMap[zlevel] = layer;

        // Vitual layer will not directly show on the screen.
        // (It can be a WebGL layer and assigned to a ZImage element)
        // But it still under management of zrender.
        if (!layer.virtual) {
            if (prevLayer) {
                var prevDom = prevLayer.dom;
                if (prevDom.nextSibling) {
                    domRoot.insertBefore(
                        layer.dom,
                        prevDom.nextSibling
                    );
                }
                else {
                    domRoot.appendChild(layer.dom);
                }
            }
            else {
                if (domRoot.firstChild) {
                    domRoot.insertBefore(layer.dom, domRoot.firstChild);
                }
                else {
                    domRoot.appendChild(layer.dom);
                }
            }
        }
    },

    // Iterate each layer
    eachLayer: function (cb, context) {
        var zlevelList = this._zlevelList;
        var z;
        var i;
        for (i = 0; i < zlevelList.length; i++) {
            z = zlevelList[i];
            cb.call(context, this._layers[z], z);
        }
    },

    // Iterate each buildin layer
    eachBuiltinLayer: function (cb, context) {
        var zlevelList = this._zlevelList;
        var layer;
        var z;
        var i;
        for (i = 0; i < zlevelList.length; i++) {
            z = zlevelList[i];
            layer = this._layers[z];
            if (layer.__builtin__) {
                cb.call(context, layer, z);
            }
        }
    },

    // Iterate each other layer except buildin layer
    eachOtherLayer: function (cb, context) {
        var zlevelList = this._zlevelList;
        var layer;
        var z;
        var i;
        for (i = 0; i < zlevelList.length; i++) {
            z = zlevelList[i];
            layer = this._layers[z];
            if (!layer.__builtin__) {
                cb.call(context, layer, z);
            }
        }
    },

    /**
     * 获取所有已创建的层
     * @param {Array.<module:zrender/Layer>} [prevLayer]
     */
    getLayers: function () {
        return this._layers;
    },

    _updateLayerStatus: function (list) {

        this.eachBuiltinLayer(function (layer, z) {
            layer.__dirty = layer.__used = false;
        });

        function updatePrevLayer(idx) {
            if (prevLayer) {
                if (prevLayer.__endIndex !== idx) {
                    prevLayer.__dirty = true;
                }
                prevLayer.__endIndex = idx;
            }
        }

        if (this._singleCanvas) {
            for (var i = 1; i < list.length; i++) {
                var el = list[i];
                if (el.zlevel !== list[i - 1].zlevel || el.incremental) {
                    this._needsManuallyCompositing = true;
                    break;
                }
            }
        }

        var prevLayer = null;
        var incrementalLayerCount = 0;
        for (var i = 0; i < list.length; i++) {
            var el = list[i];
            var zlevel = el.zlevel;
            var layer;
            // PENDING If change one incremental element style ?
            // TODO Where there are non-incremental elements between incremental elements.
            if (el.incremental) {
                layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing);
                layer.incremental = true;
                incrementalLayerCount = 1;
            }
            else {
                layer = this.getLayer(
                    zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0),
                    this._needsManuallyCompositing
                );
            }

            if (!layer.__builtin__) {
                logError$1('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id);
            }

            if (layer !== prevLayer) {
                layer.__used = true;
                if (layer.__startIndex !== i) {
                    layer.__dirty = true;
                }
                layer.__startIndex = i;
                if (!layer.incremental) {
                    layer.__drawIndex = i;
                }
                else {
                    // Mark layer draw index needs to update.
                    layer.__drawIndex = -1;
                }
                updatePrevLayer(i);
                prevLayer = layer;
            }
            if (el.__dirty) {
                layer.__dirty = true;
                if (layer.incremental && layer.__drawIndex < 0) {
                    // Start draw from the first dirty element.
                    layer.__drawIndex = i;
                }
            }
        }

        updatePrevLayer(i);

        this.eachBuiltinLayer(function (layer, z) {
            // Used in last frame but not in this frame. Needs clear
            if (!layer.__used && layer.getElementCount() > 0) {
                layer.__dirty = true;
                layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0;
            }
            // For incremental layer. In case start index changed and no elements are dirty.
            if (layer.__dirty && layer.__drawIndex < 0) {
                layer.__drawIndex = layer.__startIndex;
            }
        });
    },

    /**
     * 清除hover层外所有内容
     */
    clear: function () {
        this.eachBuiltinLayer(this._clearLayer);
        return this;
    },

    _clearLayer: function (layer) {
        layer.clear();
    },

    setBackgroundColor: function (backgroundColor) {
        this._backgroundColor = backgroundColor;
    },

    /**
     * 修改指定zlevel的绘制参数
     *
     * @param {string} zlevel
     * @param {Object} config 配置对象
     * @param {string} [config.clearColor=0] 每次清空画布的颜色
     * @param {string} [config.motionBlur=false] 是否开启动态模糊
     * @param {number} [config.lastFrameAlpha=0.7]
     *                 在开启动态模糊的时候使用，与上一帧混合的alpha值，值越大尾迹越明显
     */
    configLayer: function (zlevel, config) {
        if (config) {
            var layerConfig = this._layerConfig;
            if (!layerConfig[zlevel]) {
                layerConfig[zlevel] = config;
            }
            else {
                merge(layerConfig[zlevel], config, true);
            }

            for (var i = 0; i < this._zlevelList.length; i++) {
                var _zlevel = this._zlevelList[i];
                if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) {
                    var layer = this._layers[_zlevel];
                    merge(layer, layerConfig[zlevel], true);
                }
            }
        }
    },

    /**
     * 删除指定层
     * @param {number} zlevel 层所在的zlevel
     */
    delLayer: function (zlevel) {
        var layers = this._layers;
        var zlevelList = this._zlevelList;
        var layer = layers[zlevel];
        if (!layer) {
            return;
        }
        layer.dom.parentNode.removeChild(layer.dom);
        delete layers[zlevel];

        zlevelList.splice(indexOf(zlevelList, zlevel), 1);
    },

    /**
     * 区域大小变化后重绘
     */
    resize: function (width, height) {
        if (!this._domRoot.style) { // Maybe in node or worker
            if (width == null || height == null) {
                return;
            }
            this._width = width;
            this._height = height;

            this.getLayer(CANVAS_ZLEVEL).resize(width, height);
        }
        else {
            var domRoot = this._domRoot;
            // FIXME Why ?
            domRoot.style.display = 'none';

            // Save input w/h
            var opts = this._opts;
            width != null && (opts.width = width);
            height != null && (opts.height = height);

            width = this._getSize(0);
            height = this._getSize(1);

            domRoot.style.display = '';

            // 优化没有实际改变的resize
            if (this._width !== width || height !== this._height) {
                domRoot.style.width = width + 'px';
                domRoot.style.height = height + 'px';

                for (var id in this._layers) {
                    if (this._layers.hasOwnProperty(id)) {
                        this._layers[id].resize(width, height);
                    }
                }
                each$1(this._progressiveLayers, function (layer) {
                    layer.resize(width, height);
                });

                this.refresh(true);
            }

            this._width = width;
            this._height = height;

        }
        return this;
    },

    /**
     * 清除单独的一个层
     * @param {number} zlevel
     */
    clearLayer: function (zlevel) {
        var layer = this._layers[zlevel];
        if (layer) {
            layer.clear();
        }
    },

    /**
     * 释放
     */
    dispose: function () {
        this.root.innerHTML = '';

        this.root =
        this.storage =

        this._domRoot =
        this._layers = null;
    },

    /**
     * Get canvas which has all thing rendered
     * @param {Object} opts
     * @param {string} [opts.backgroundColor]
     * @param {number} [opts.pixelRatio]
     */
    getRenderedCanvas: function (opts) {
        opts = opts || {};
        if (this._singleCanvas && !this._compositeManually) {
            return this._layers[CANVAS_ZLEVEL].dom;
        }

        var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr);
        imageLayer.initContext();
        imageLayer.clear(false, opts.backgroundColor || this._backgroundColor);

        if (opts.pixelRatio <= this.dpr) {
            this.refresh();

            var width = imageLayer.dom.width;
            var height = imageLayer.dom.height;
            var ctx = imageLayer.ctx;
            this.eachLayer(function (layer) {
                if (layer.__builtin__) {
                    ctx.drawImage(layer.dom, 0, 0, width, height);
                }
                else if (layer.renderToCanvas) {
                    imageLayer.ctx.save();
                    layer.renderToCanvas(imageLayer.ctx);
                    imageLayer.ctx.restore();
                }
            });
        }
        else {
            // PENDING, echarts-gl and incremental rendering.
            var scope = {};
            var displayList = this.storage.getDisplayList(true);
            for (var i = 0; i < displayList.length; i++) {
                var el = displayList[i];
                this._doPaintEl(el, imageLayer, true, scope);
            }
        }

        return imageLayer.dom;
    },
    /**
     * 获取绘图区域宽度
     */
    getWidth: function () {
        return this._width;
    },

    /**
     * 获取绘图区域高度
     */
    getHeight: function () {
        return this._height;
    },

    _getSize: function (whIdx) {
        var opts = this._opts;
        var wh = ['width', 'height'][whIdx];
        var cwh = ['clientWidth', 'clientHeight'][whIdx];
        var plt = ['paddingLeft', 'paddingTop'][whIdx];
        var prb = ['paddingRight', 'paddingBottom'][whIdx];

        if (opts[wh] != null && opts[wh] !== 'auto') {
            return parseFloat(opts[wh]);
        }

        var root = this.root;
        // IE8 does not support getComputedStyle, but it use VML.
        var stl = document.defaultView.getComputedStyle(root);

        return (
            (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh]))
            - (parseInt10(stl[plt]) || 0)
            - (parseInt10(stl[prb]) || 0)
        ) | 0;
    },

    pathToImage: function (path, dpr) {
        dpr = dpr || this.dpr;

        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var rect = path.getBoundingRect();
        var style = path.style;
        var shadowBlurSize = style.shadowBlur * dpr;
        var shadowOffsetX = style.shadowOffsetX * dpr;
        var shadowOffsetY = style.shadowOffsetY * dpr;
        var lineWidth = style.hasStroke() ? style.lineWidth : 0;

        var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize);
        var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize);
        var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize);
        var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize);
        var width = rect.width + leftMargin + rightMargin;
        var height = rect.height + topMargin + bottomMargin;

        canvas.width = width * dpr;
        canvas.height = height * dpr;

        ctx.scale(dpr, dpr);
        ctx.clearRect(0, 0, width, height);
        ctx.dpr = dpr;

        var pathTransform = {
            position: path.position,
            rotation: path.rotation,
            scale: path.scale
        };
        path.position = [leftMargin - rect.x, topMargin - rect.y];
        path.rotation = 0;
        path.scale = [1, 1];
        path.updateTransform();
        if (path) {
            path.brush(ctx);
        }

        var ImageShape = ZImage;
        var imgShape = new ImageShape({
            style: {
                x: 0,
                y: 0,
                image: canvas
            }
        });

        if (pathTransform.position != null) {
            imgShape.position = path.position = pathTransform.position;
        }

        if (pathTransform.rotation != null) {
            imgShape.rotation = path.rotation = pathTransform.rotation;
        }

        if (pathTransform.scale != null) {
            imgShape.scale = path.scale = pathTransform.scale;
        }

        return imgShape;
    }
};

/**
 * 动画主类, 调度和管理所有动画控制器
 *
 * @module zrender/animation/Animation
 * @author pissang(https://github.com/pissang)
 */
// TODO Additive animation
// http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/
// https://developer.apple.com/videos/wwdc2014/#236

/**
 * @typedef {Object} IZRenderStage
 * @property {Function} update
 */

/**
 * @alias module:zrender/animation/Animation
 * @constructor
 * @param {Object} [options]
 * @param {Function} [options.onframe]
 * @param {IZRenderStage} [options.stage]
 * @example
 *     var animation = new Animation();
 *     var obj = {
 *         x: 100,
 *         y: 100
 *     };
 *     animation.animate(node.position)
 *         .when(1000, {
 *             x: 500,
 *             y: 500
 *         })
 *         .when(2000, {
 *             x: 100,
 *             y: 100
 *         })
 *         .start('spline');
 */
var Animation = function (options) {

    options = options || {};

    this.stage = options.stage || {};

    this.onframe = options.onframe || function () {};

    // private properties
    this._clips = [];

    this._running = false;

    this._time;

    this._pausedTime;

    this._pauseStart;

    this._paused = false;

    Eventful.call(this);
};

Animation.prototype = {

    constructor: Animation,
    /**
     * 添加 clip
     * @param {module:zrender/animation/Clip} clip
     */
    addClip: function (clip) {
        this._clips.push(clip);
    },
    /**
     * 添加 animator
     * @param {module:zrender/animation/Animator} animator
     */
    addAnimator: function (animator) {
        animator.animation = this;
        var clips = animator.getClips();
        for (var i = 0; i < clips.length; i++) {
            this.addClip(clips[i]);
        }
    },
    /**
     * 删除动画片段
     * @param {module:zrender/animation/Clip} clip
     */
    removeClip: function (clip) {
        var idx = indexOf(this._clips, clip);
        if (idx >= 0) {
            this._clips.splice(idx, 1);
        }
    },

    /**
     * 删除动画片段
     * @param {module:zrender/animation/Animator} animator
     */
    removeAnimator: function (animator) {
        var clips = animator.getClips();
        for (var i = 0; i < clips.length; i++) {
            this.removeClip(clips[i]);
        }
        animator.animation = null;
    },

    _update: function () {
        var time = new Date().getTime() - this._pausedTime;
        var delta = time - this._time;
        var clips = this._clips;
        var len = clips.length;

        var deferredEvents = [];
        var deferredClips = [];
        for (var i = 0; i < len; i++) {
            var clip = clips[i];
            var e = clip.step(time, delta);
            // Throw out the events need to be called after
            // stage.update, like destroy
            if (e) {
                deferredEvents.push(e);
                deferredClips.push(clip);
            }
        }

        // Remove the finished clip
        for (var i = 0; i < len;) {
            if (clips[i]._needsRemove) {
                clips[i] = clips[len - 1];
                clips.pop();
                len--;
            }
            else {
                i++;
            }
        }

        len = deferredEvents.length;
        for (var i = 0; i < len; i++) {
            deferredClips[i].fire(deferredEvents[i]);
        }

        this._time = time;

        this.onframe(delta);

        // 'frame' should be triggered before stage, because upper application
        // depends on the sequence (e.g., echarts-stream and finish
        // event judge)
        this.trigger('frame', delta);

        if (this.stage.update) {
            this.stage.update();
        }
    },

    _startLoop: function () {
        var self = this;

        this._running = true;

        function step() {
            if (self._running) {

                requestAnimationFrame(step);

                !self._paused && self._update();
            }
        }

        requestAnimationFrame(step);
    },

    /**
     * Start animation.
     */
    start: function () {

        this._time = new Date().getTime();
        this._pausedTime = 0;

        this._startLoop();
    },

    /**
     * Stop animation.
     */
    stop: function () {
        this._running = false;
    },

    /**
     * Pause animation.
     */
    pause: function () {
        if (!this._paused) {
            this._pauseStart = new Date().getTime();
            this._paused = true;
        }
    },

    /**
     * Resume animation.
     */
    resume: function () {
        if (this._paused) {
            this._pausedTime += (new Date().getTime()) - this._pauseStart;
            this._paused = false;
        }
    },

    /**
     * Clear animation.
     */
    clear: function () {
        this._clips = [];
    },

    /**
     * Whether animation finished.
     */
    isFinished: function () {
        return !this._clips.length;
    },

    /**
     * Creat animator for a target, whose props can be animated.
     *
     * @param  {Object} target
     * @param  {Object} options
     * @param  {boolean} [options.loop=false] Whether loop animation.
     * @param  {Function} [options.getter=null] Get value from target.
     * @param  {Function} [options.setter=null] Set value to target.
     * @return {module:zrender/animation/Animation~Animator}
     */
    // TODO Gap
    animate: function (target, options) {
        options = options || {};

        var animator = new Animator(
            target,
            options.loop,
            options.getter,
            options.setter
        );

        this.addAnimator(animator);

        return animator;
    }
};

mixin(Animation, Eventful);

var TOUCH_CLICK_DELAY = 300;

var mouseHandlerNames = [
    'click', 'dblclick', 'mousewheel', 'mouseout',
    'mouseup', 'mousedown', 'mousemove', 'contextmenu'
];

var touchHandlerNames = [
    'touchstart', 'touchend', 'touchmove'
];

var pointerEventNames = {
    pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
};

var pointerHandlerNames = map(mouseHandlerNames, function (name) {
    var nm = name.replace('mouse', 'pointer');
    return pointerEventNames[nm] ? nm : name;
});

function eventNameFix(name) {
    return (name === 'mousewheel' && env$1.browser.firefox) ? 'DOMMouseScroll' : name;
}

// function onMSGestureChange(proxy, event) {
//     if (event.translationX || event.translationY) {
//         // mousemove is carried by MSGesture to reduce the sensitivity.
//         proxy.handler.dispatchToElement(event.target, 'mousemove', event);
//     }
//     if (event.scale !== 1) {
//         event.pinchX = event.offsetX;
//         event.pinchY = event.offsetY;
//         event.pinchScale = event.scale;
//         proxy.handler.dispatchToElement(event.target, 'pinch', event);
//     }
// }

/**
 * Prevent mouse event from being dispatched after Touch Events action
 * @see <https://github.com/deltakosh/handjs/blob/master/src/hand.base.js>
 * 1. Mobile browsers dispatch mouse events 300ms after touchend.
 * 2. Chrome for Android dispatch mousedown for long-touch about 650ms
 * Result: Blocking Mouse Events for 700ms.
 */
function setTouchTimer(instance) {
    instance._touching = true;
    clearTimeout(instance._touchTimer);
    instance._touchTimer = setTimeout(function () {
        instance._touching = false;
    }, 700);
}


var domHandlers = {
    /**
     * Mouse move handler
     * @inner
     * @param {Event} event
     */
    mousemove: function (event) {
        event = normalizeEvent(this.dom, event);

        this.trigger('mousemove', event);
    },

    /**
     * Mouse out handler
     * @inner
     * @param {Event} event
     */
    mouseout: function (event) {
        event = normalizeEvent(this.dom, event);

        var element = event.toElement || event.relatedTarget;
        if (element !== this.dom) {
            while (element && element.nodeType !== 9) {
                // 忽略包含在root中的dom引起的mouseOut
                if (element === this.dom) {
                    return;
                }

                element = element.parentNode;
            }
        }

        this.trigger('mouseout', event);
    },

    /**
     * Touch开始响应函数
     * @inner
     * @param {Event} event
     */
    touchstart: function (event) {
        // Default mouse behaviour should not be disabled here.
        // For example, page may needs to be slided.
        event = normalizeEvent(this.dom, event);

        // Mark touch, which is useful in distinguish touch and
        // mouse event in upper applicatoin.
        event.zrByTouch = true;

        this._lastTouchMoment = new Date();

        this.handler.processGesture(event, 'start');

        // In touch device, trigger `mousemove`(`mouseover`) should
        // be triggered, and must before `mousedown` triggered.
        domHandlers.mousemove.call(this, event);

        domHandlers.mousedown.call(this, event);

        setTouchTimer(this);
    },

    /**
     * Touch移动响应函数
     * @inner
     * @param {Event} event
     */
    touchmove: function (event) {

        event = normalizeEvent(this.dom, event);

        // Mark touch, which is useful in distinguish touch and
        // mouse event in upper applicatoin.
        event.zrByTouch = true;

        this.handler.processGesture(event, 'change');

        // Mouse move should always be triggered no matter whether
        // there is gestrue event, because mouse move and pinch may
        // be used at the same time.
        domHandlers.mousemove.call(this, event);

        setTouchTimer(this);
    },

    /**
     * Touch结束响应函数
     * @inner
     * @param {Event} event
     */
    touchend: function (event) {

        event = normalizeEvent(this.dom, event);

        // Mark touch, which is useful in distinguish touch and
        // mouse event in upper applicatoin.
        event.zrByTouch = true;

        this.handler.processGesture(event, 'end');

        domHandlers.mouseup.call(this, event);

        // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is
        // triggered in `touchstart`. This seems to be illogical, but by this mechanism,
        // we can conveniently implement "hover style" in both PC and touch device just
        // by listening to `mouseover` to add "hover style" and listening to `mouseout`
        // to remove "hover style" on an element, without any additional code for
        // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover
        // style" will remain for user view)

        // click event should always be triggered no matter whether
        // there is gestrue event. System click can not be prevented.
        if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) {
            domHandlers.click.call(this, event);
        }

        setTouchTimer(this);
    },

    pointerdown: function (event) {
        domHandlers.mousedown.call(this, event);

        // if (useMSGuesture(this, event)) {
        //     this._msGesture.addPointer(event.pointerId);
        // }
    },

    pointermove: function (event) {
        // FIXME
        // pointermove is so sensitive that it always triggered when
        // tap(click) on touch screen, which affect some judgement in
        // upper application. So, we dont support mousemove on MS touch
        // device yet.
        if (!isPointerFromTouch(event)) {
            domHandlers.mousemove.call(this, event);
        }
    },

    pointerup: function (event) {
        domHandlers.mouseup.call(this, event);
    },

    pointerout: function (event) {
        // pointerout will be triggered when tap on touch screen
        // (IE11+/Edge on MS Surface) after click event triggered,
        // which is inconsistent with the mousout behavior we defined
        // in touchend. So we unify them.
        // (check domHandlers.touchend for detailed explanation)
        if (!isPointerFromTouch(event)) {
            domHandlers.mouseout.call(this, event);
        }
    }
};

function isPointerFromTouch(event) {
    var pointerType = event.pointerType;
    return pointerType === 'pen' || pointerType === 'touch';
}

// function useMSGuesture(handlerProxy, event) {
//     return isPointerFromTouch(event) && !!handlerProxy._msGesture;
// }

// Common handlers
each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
    domHandlers[name] = function (event) {
        event = normalizeEvent(this.dom, event);
        this.trigger(name, event);
    };
});

/**
 * 为控制类实例初始化dom 事件处理函数
 *
 * @inner
 * @param {module:zrender/Handler} instance 控制类实例
 */
function initDomHandler(instance) {
    each$1(touchHandlerNames, function (name) {
        instance._handlers[name] = bind(domHandlers[name], instance);
    });

    each$1(pointerHandlerNames, function (name) {
        instance._handlers[name] = bind(domHandlers[name], instance);
    });

    each$1(mouseHandlerNames, function (name) {
        instance._handlers[name] = makeMouseHandler(domHandlers[name], instance);
    });

    function makeMouseHandler(fn, instance) {
        return function () {
            if (instance._touching) {
                return;
            }
            return fn.apply(instance, arguments);
        };
    }
}


function HandlerDomProxy(dom) {
    Eventful.call(this);

    this.dom = dom;

    /**
     * @private
     * @type {boolean}
     */
    this._touching = false;

    /**
     * @private
     * @type {number}
     */
    this._touchTimer;

    this._handlers = {};

    initDomHandler(this);

    if (env$1.pointerEventsSupported) { // Only IE11+/Edge
        // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240),
        // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event
        // at the same time.
        // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on
        // screen, which do not occurs in pointer event.
        // So we use pointer event to both detect touch gesture and mouse behavior.
        mountHandlers(pointerHandlerNames, this);

        // FIXME
        // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,
        // which does not prevent defuault behavior occasionally (which may cause view port
        // zoomed in but use can not zoom it back). And event.preventDefault() does not work.
        // So we have to not to use MSGesture and not to support touchmove and pinch on MS
        // touch screen. And we only support click behavior on MS touch screen now.

        // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+.
        // We dont support touch on IE on win7.
        // See <https://msdn.microsoft.com/en-us/library/dn433243(v=vs.85).aspx>
        // if (typeof MSGesture === 'function') {
        //     (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line
        //     dom.addEventListener('MSGestureChange', onMSGestureChange);
        // }
    }
    else {
        if (env$1.touchEventsSupported) {
            mountHandlers(touchHandlerNames, this);
            // Handler of 'mouseout' event is needed in touch mode, which will be mounted below.
            // addEventListener(root, 'mouseout', this._mouseoutHandler);
        }

        // 1. Considering some devices that both enable touch and mouse event (like on MS Surface
        // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise
        // mouse event can not be handle in those devices.
        // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent
        // mouseevent after touch event triggered, see `setTouchTimer`.
        mountHandlers(mouseHandlerNames, this);
    }

    function mountHandlers(handlerNames, instance) {
        each$1(handlerNames, function (name) {
            addEventListener(dom, eventNameFix(name), instance._handlers[name]);
        }, instance);
    }
}

var handlerDomProxyProto = HandlerDomProxy.prototype;
handlerDomProxyProto.dispose = function () {
    var handlerNames = mouseHandlerNames.concat(touchHandlerNames);

    for (var i = 0; i < handlerNames.length; i++) {
        var name = handlerNames[i];
        removeEventListener(this.dom, eventNameFix(name), this._handlers[name]);
    }
};

handlerDomProxyProto.setCursor = function (cursorStyle) {
    this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
};

mixin(HandlerDomProxy, Eventful);

/*!
* ZRender, a high performance 2d drawing library.
*
* Copyright (c) 2013, Baidu Inc.
* All rights reserved.
*
* LICENSE
* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
*/

var useVML = !env$1.canvasSupported;

var painterCtors = {
    canvas: Painter
};

var instances$1 = {};    // ZRender实例map索引

/**
 * @type {string}
 */
var version$1 = '4.1.2';

/**
 * Initializing a zrender instance
 * @param {HTMLElement} dom
 * @param {Object} [opts]
 * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
 * @param {number} [opts.devicePixelRatio]
 * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
 * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
 * @return {module:zrender/ZRender}
 */
function init$1(dom, opts) {
    var zr = new ZRender(guid(), dom, opts);
    instances$1[zr.id] = zr;
    return zr;
}

/**
 * Dispose zrender instance
 * @param {module:zrender/ZRender} zr
 */
function dispose$1(zr) {
    if (zr) {
        zr.dispose();
    }
    else {
        for (var key in instances$1) {
            if (instances$1.hasOwnProperty(key)) {
                instances$1[key].dispose();
            }
        }
        instances$1 = {};
    }

    return this;
}

/**
 * Get zrender instance by id
 * @param {string} id zrender instance id
 * @return {module:zrender/ZRender}
 */
function getInstance(id) {
    return instances$1[id];
}

function registerPainter(name, Ctor) {
    painterCtors[name] = Ctor;
}

function delInstance(id) {
    delete instances$1[id];
}

/**
 * @module zrender/ZRender
 */
/**
 * @constructor
 * @alias module:zrender/ZRender
 * @param {string} id
 * @param {HTMLElement} dom
 * @param {Object} opts
 * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
 * @param {number} [opts.devicePixelRatio]
 * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
 * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
 */
var ZRender = function (id, dom, opts) {

    opts = opts || {};

    /**
     * @type {HTMLDomElement}
     */
    this.dom = dom;

    /**
     * @type {string}
     */
    this.id = id;

    var self = this;
    var storage = new Storage();

    var rendererType = opts.renderer;
    // TODO WebGL
    if (useVML) {
        if (!painterCtors.vml) {
            throw new Error('You need to require \'zrender/vml/vml\' to support IE8');
        }
        rendererType = 'vml';
    }
    else if (!rendererType || !painterCtors[rendererType]) {
        rendererType = 'canvas';
    }
    var painter = new painterCtors[rendererType](dom, storage, opts, id);

    this.storage = storage;
    this.painter = painter;

    var handerProxy = (!env$1.node && !env$1.worker) ? new HandlerDomProxy(painter.getViewportRoot()) : null;
    this.handler = new Handler(storage, painter, handerProxy, painter.root);

    /**
     * @type {module:zrender/animation/Animation}
     */
    this.animation = new Animation({
        stage: {
            update: bind(this.flush, this)
        }
    });
    this.animation.start();

    /**
     * @type {boolean}
     * @private
     */
    this._needsRefresh;

    // 修改 storage.delFromStorage, 每次删除元素之前删除动画
    // FIXME 有点ugly
    var oldDelFromStorage = storage.delFromStorage;
    var oldAddToStorage = storage.addToStorage;

    storage.delFromStorage = function (el) {
        oldDelFromStorage.call(storage, el);

        el && el.removeSelfFromZr(self);
    };

    storage.addToStorage = function (el) {
        oldAddToStorage.call(storage, el);

        el.addSelfToZr(self);
    };
};

ZRender.prototype = {

    constructor: ZRender,
    /**
     * 获取实例唯一标识
     * @return {string}
     */
    getId: function () {
        return this.id;
    },

    /**
     * 添加元素
     * @param  {module:zrender/Element} el
     */
    add: function (el) {
        this.storage.addRoot(el);
        this._needsRefresh = true;
    },

    /**
     * 删除元素
     * @param  {module:zrender/Element} el
     */
    remove: function (el) {
        this.storage.delRoot(el);
        this._needsRefresh = true;
    },

    /**
     * Change configuration of layer
     * @param {string} zLevel
     * @param {Object} config
     * @param {string} [config.clearColor=0] Clear color
     * @param {string} [config.motionBlur=false] If enable motion blur
     * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer
    */
    configLayer: function (zLevel, config) {
        if (this.painter.configLayer) {
            this.painter.configLayer(zLevel, config);
        }
        this._needsRefresh = true;
    },

    /**
     * Set background color
     * @param {string} backgroundColor
     */
    setBackgroundColor: function (backgroundColor) {
        if (this.painter.setBackgroundColor) {
            this.painter.setBackgroundColor(backgroundColor);
        }
        this._needsRefresh = true;
    },

    /**
     * Repaint the canvas immediately
     */
    refreshImmediately: function () {
        // var start = new Date();

        // Clear needsRefresh ahead to avoid something wrong happens in refresh
        // Or it will cause zrender refreshes again and again.
        this._needsRefresh = this._needsRefreshHover = false;
        this.painter.refresh();
        // Avoid trigger zr.refresh in Element#beforeUpdate hook
        this._needsRefresh = this._needsRefreshHover = false;

        // var end = new Date();
        // var log = document.getElementById('log');
        // if (log) {
        //     log.innerHTML = log.innerHTML + '<br>' + (end - start);
        // }
    },

    /**
     * Mark and repaint the canvas in the next frame of browser
     */
    refresh: function () {
        this._needsRefresh = true;
    },

    /**
     * Perform all refresh
     */
    flush: function () {
        var triggerRendered;

        if (this._needsRefresh) {
            triggerRendered = true;
            this.refreshImmediately();
        }
        if (this._needsRefreshHover) {
            triggerRendered = true;
            this.refreshHoverImmediately();
        }

        triggerRendered && this.trigger('rendered');
    },

    /**
     * Add element to hover layer
     * @param  {module:zrender/Element} el
     * @param {Object} style
     */
    addHover: function (el, style) {
        if (this.painter.addHover) {
            var elMirror = this.painter.addHover(el, style);
            this.refreshHover();
            return elMirror;
        }
    },

    /**
     * Add element from hover layer
     * @param  {module:zrender/Element} el
     */
    removeHover: function (el) {
        if (this.painter.removeHover) {
            this.painter.removeHover(el);
            this.refreshHover();
        }
    },

    /**
     * Clear all hover elements in hover layer
     * @param  {module:zrender/Element} el
     */
    clearHover: function () {
        if (this.painter.clearHover) {
            this.painter.clearHover();
            this.refreshHover();
        }
    },

    /**
     * Refresh hover in next frame
     */
    refreshHover: function () {
        this._needsRefreshHover = true;
    },

    /**
     * Refresh hover immediately
     */
    refreshHoverImmediately: function () {
        this._needsRefreshHover = false;
        this.painter.refreshHover && this.painter.refreshHover();
    },

    /**
     * Resize the canvas.
     * Should be invoked when container size is changed
     * @param {Object} [opts]
     * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
     * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
     */
    resize: function (opts) {
        opts = opts || {};
        this.painter.resize(opts.width, opts.height);
        this.handler.resize();
    },

    /**
     * Stop and clear all animation immediately
     */
    clearAnimation: function () {
        this.animation.clear();
    },

    /**
     * Get container width
     */
    getWidth: function () {
        return this.painter.getWidth();
    },

    /**
     * Get container height
     */
    getHeight: function () {
        return this.painter.getHeight();
    },

    /**
     * Export the canvas as Base64 URL
     * @param {string} type
     * @param {string} [backgroundColor='#fff']
     * @return {string} Base64 URL
     */
    // toDataURL: function(type, backgroundColor) {
    //     return this.painter.getRenderedCanvas({
    //         backgroundColor: backgroundColor
    //     }).toDataURL(type);
    // },

    /**
     * Converting a path to image.
     * It has much better performance of drawing image rather than drawing a vector path.
     * @param {module:zrender/graphic/Path} e
     * @param {number} width
     * @param {number} height
     */
    pathToImage: function (e, dpr) {
        return this.painter.pathToImage(e, dpr);
    },

    /**
     * Set default cursor
     * @param {string} [cursorStyle='default'] 例如 crosshair
     */
    setCursorStyle: function (cursorStyle) {
        this.handler.setCursorStyle(cursorStyle);
    },

    /**
     * Find hovered element
     * @param {number} x
     * @param {number} y
     * @return {Object} {target, topTarget}
     */
    findHover: function (x, y) {
        return this.handler.findHover(x, y);
    },

    /**
     * Bind event
     *
     * @param {string} eventName Event name
     * @param {Function} eventHandler Handler function
     * @param {Object} [context] Context object
     */
    on: function (eventName, eventHandler, context) {
        this.handler.on(eventName, eventHandler, context);
    },

    /**
     * Unbind event
     * @param {string} eventName Event name
     * @param {Function} [eventHandler] Handler function
     */
    off: function (eventName, eventHandler) {
        this.handler.off(eventName, eventHandler);
    },

    /**
     * Trigger event manually
     *
     * @param {string} eventName Event name
     * @param {event=} event Event object
     */
    trigger: function (eventName, event) {
        this.handler.trigger(eventName, event);
    },


    /**
     * Clear all objects and the canvas.
     */
    clear: function () {
        this.storage.delRoot();
        this.painter.clear();
    },

    /**
     * Dispose self.
     */
    dispose: function () {
        this.animation.stop();

        this.clear();
        this.storage.dispose();
        this.painter.dispose();
        this.handler.dispose();

        this.animation =
        this.storage =
        this.painter =
        this.handler = null;

        delInstance(this.id);
    }
};



var zrender = (Object.freeze || Object)({
	version: version$1,
	init: init$1,
	dispose: dispose$1,
	getInstance: getInstance,
	registerPainter: registerPainter
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$2 = each$1;
var isObject$2 = isObject$1;
var isArray$1 = isArray;

/**
 * Make the name displayable. But we should
 * make sure it is not duplicated with user
 * specified name, so use '\0';
 */
var DUMMY_COMPONENT_NAME_PREFIX = 'series\0';

/**
 * If value is not array, then translate it to array.
 * @param  {*} value
 * @return {Array} [value] or value
 */
function normalizeToArray(value) {
    return value instanceof Array
        ? value
        : value == null
        ? []
        : [value];
}

/**
 * Sync default option between normal and emphasis like `position` and `show`
 * In case some one will write code like
 *     label: {
 *          show: false,
 *          position: 'outside',
 *          fontSize: 18
 *     },
 *     emphasis: {
 *          label: { show: true }
 *     }
 * @param {Object} opt
 * @param {string} key
 * @param {Array.<string>} subOpts
 */
function defaultEmphasis(opt, key, subOpts) {
    // Caution: performance sensitive.
    if (opt) {
        opt[key] = opt[key] || {};
        opt.emphasis = opt.emphasis || {};
        opt.emphasis[key] = opt.emphasis[key] || {};

        // Default emphasis option from normal
        for (var i = 0, len = subOpts.length; i < len; i++) {
            var subOptName = subOpts[i];
            if (!opt.emphasis[key].hasOwnProperty(subOptName)
                && opt[key].hasOwnProperty(subOptName)
            ) {
                opt.emphasis[key][subOptName] = opt[key][subOptName];
            }
        }
    }
}

var TEXT_STYLE_OPTIONS = [
    'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
    'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth',
    'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline',
    'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY',
    'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY',
    'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding'
];

// modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([
//     'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter',
//     'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
//     // FIXME: deprecated, check and remove it.
//     'textStyle'
// ]);

/**
 * The method do not ensure performance.
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method retieves value from data.
 * @param {string|number|Date|Array|Object} dataItem
 * @return {number|string|Date|Array.<number|string|Date>}
 */
function getDataItemValue(dataItem) {
    return (isObject$2(dataItem) && !isArray$1(dataItem) && !(dataItem instanceof Date))
        ? dataItem.value : dataItem;
}

/**
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method determine if dataItem has extra option besides value
 * @param {string|number|Date|Array|Object} dataItem
 */
function isDataItemOption(dataItem) {
    return isObject$2(dataItem)
        && !(dataItem instanceof Array);
        // // markLine data can be array
        // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));
}

/**
 * Mapping to exists for merge.
 *
 * @public
 * @param {Array.<Object>|Array.<module:echarts/model/Component>} exists
 * @param {Object|Array.<Object>} newCptOptions
 * @return {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],
 *                          index of which is the same as exists.
 */
function mappingToExists(exists, newCptOptions) {
    // Mapping by the order by original option (but not order of
    // new option) in merge mode. Because we should ensure
    // some specified index (like xAxisIndex) is consistent with
    // original option, which is easy to understand, espatially in
    // media query. And in most case, merge option is used to
    // update partial option but not be expected to change order.
    newCptOptions = (newCptOptions || []).slice();

    var result = map(exists || [], function (obj, index) {
        return {exist: obj};
    });

    // Mapping by id or name if specified.
    each$2(newCptOptions, function (cptOption, index) {
        if (!isObject$2(cptOption)) {
            return;
        }

        // id has highest priority.
        for (var i = 0; i < result.length; i++) {
            if (!result[i].option // Consider name: two map to one.
                && cptOption.id != null
                && result[i].exist.id === cptOption.id + ''
            ) {
                result[i].option = cptOption;
                newCptOptions[index] = null;
                return;
            }
        }

        for (var i = 0; i < result.length; i++) {
            var exist = result[i].exist;
            if (!result[i].option // Consider name: two map to one.
                // Can not match when both ids exist but different.
                && (exist.id == null || cptOption.id == null)
                && cptOption.name != null
                && !isIdInner(cptOption)
                && !isIdInner(exist)
                && exist.name === cptOption.name + ''
            ) {
                result[i].option = cptOption;
                newCptOptions[index] = null;
                return;
            }
        }
    });

    // Otherwise mapping by index.
    each$2(newCptOptions, function (cptOption, index) {
        if (!isObject$2(cptOption)) {
            return;
        }

        var i = 0;
        for (; i < result.length; i++) {
            var exist = result[i].exist;
            if (!result[i].option
                // Existing model that already has id should be able to
                // mapped to (because after mapping performed model may
                // be assigned with a id, whish should not affect next
                // mapping), except those has inner id.
                && !isIdInner(exist)
                // Caution:
                // Do not overwrite id. But name can be overwritten,
                // because axis use name as 'show label text'.
                // 'exist' always has id and name and we dont
                // need to check it.
                && cptOption.id == null
            ) {
                result[i].option = cptOption;
                break;
            }
        }

        if (i >= result.length) {
            result.push({option: cptOption});
        }
    });

    return result;
}

/**
 * Make id and name for mapping result (result of mappingToExists)
 * into `keyInfo` field.
 *
 * @public
 * @param {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],
 *                          which order is the same as exists.
 * @return {Array.<Object>} The input.
 */
function makeIdAndName(mapResult) {
    // We use this id to hash component models and view instances
    // in echarts. id can be specified by user, or auto generated.

    // The id generation rule ensures new view instance are able
    // to mapped to old instance when setOption are called in
    // no-merge mode. So we generate model id by name and plus
    // type in view id.

    // name can be duplicated among components, which is convenient
    // to specify multi components (like series) by one name.

    // Ensure that each id is distinct.
    var idMap = createHashMap();

    each$2(mapResult, function (item, index) {
        var existCpt = item.exist;
        existCpt && idMap.set(existCpt.id, item);
    });

    each$2(mapResult, function (item, index) {
        var opt = item.option;

        assert$1(
            !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item,
            'id duplicates: ' + (opt && opt.id)
        );

        opt && opt.id != null && idMap.set(opt.id, item);
        !item.keyInfo && (item.keyInfo = {});
    });

    // Make name and id.
    each$2(mapResult, function (item, index) {
        var existCpt = item.exist;
        var opt = item.option;
        var keyInfo = item.keyInfo;

        if (!isObject$2(opt)) {
            return;
        }

        // name can be overwitten. Consider case: axis.name = '20km'.
        // But id generated by name will not be changed, which affect
        // only in that case: setOption with 'not merge mode' and view
        // instance will be recreated, which can be accepted.
        keyInfo.name = opt.name != null
            ? opt.name + ''
            : existCpt
            ? existCpt.name
            // Avoid diffferent series has the same name,
            // because name may be used like in color pallet.
            : DUMMY_COMPONENT_NAME_PREFIX + index;

        if (existCpt) {
            keyInfo.id = existCpt.id;
        }
        else if (opt.id != null) {
            keyInfo.id = opt.id + '';
        }
        else {
            // Consider this situatoin:
            //  optionA: [{name: 'a'}, {name: 'a'}, {..}]
            //  optionB [{..}, {name: 'a'}, {name: 'a'}]
            // Series with the same name between optionA and optionB
            // should be mapped.
            var idNum = 0;
            do {
                keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
            }
            while (idMap.get(keyInfo.id));
        }

        idMap.set(keyInfo.id, item);
    });
}

function isNameSpecified(componentModel) {
    var name = componentModel.name;
    // Is specified when `indexOf` get -1 or > 0.
    return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));
}

/**
 * @public
 * @param {Object} cptOption
 * @return {boolean}
 */
function isIdInner(cptOption) {
    return isObject$2(cptOption)
        && cptOption.id
        && (cptOption.id + '').indexOf('\0_ec_\0') === 0;
}

/**
 * A helper for removing duplicate items between batchA and batchB,
 * and in themselves, and categorize by series.
 *
 * @param {Array.<Object>} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
 * @param {Array.<Object>} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
 * @return {Array.<Array.<Object>, Array.<Object>>} result: [resultBatchA, resultBatchB]
 */
function compressBatches(batchA, batchB) {
    var mapA = {};
    var mapB = {};

    makeMap(batchA || [], mapA);
    makeMap(batchB || [], mapB, mapA);

    return [mapToArray(mapA), mapToArray(mapB)];

    function makeMap(sourceBatch, map$$1, otherMap) {
        for (var i = 0, len = sourceBatch.length; i < len; i++) {
            var seriesId = sourceBatch[i].seriesId;
            var dataIndices = normalizeToArray(sourceBatch[i].dataIndex);
            var otherDataIndices = otherMap && otherMap[seriesId];

            for (var j = 0, lenj = dataIndices.length; j < lenj; j++) {
                var dataIndex = dataIndices[j];

                if (otherDataIndices && otherDataIndices[dataIndex]) {
                    otherDataIndices[dataIndex] = null;
                }
                else {
                    (map$$1[seriesId] || (map$$1[seriesId] = {}))[dataIndex] = 1;
                }
            }
        }
    }

    function mapToArray(map$$1, isData) {
        var result = [];
        for (var i in map$$1) {
            if (map$$1.hasOwnProperty(i) && map$$1[i] != null) {
                if (isData) {
                    result.push(+i);
                }
                else {
                    var dataIndices = mapToArray(map$$1[i], true);
                    dataIndices.length && result.push({seriesId: i, dataIndex: dataIndices});
                }
            }
        }
        return result;
    }
}

/**
 * @param {module:echarts/data/List} data
 * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name
 *                         each of which can be Array or primary type.
 * @return {number|Array.<number>} dataIndex If not found, return undefined/null.
 */
function queryDataIndex(data, payload) {
    if (payload.dataIndexInside != null) {
        return payload.dataIndexInside;
    }
    else if (payload.dataIndex != null) {
        return isArray(payload.dataIndex)
            ? map(payload.dataIndex, function (value) {
                return data.indexOfRawIndex(value);
            })
            : data.indexOfRawIndex(payload.dataIndex);
    }
    else if (payload.name != null) {
        return isArray(payload.name)
            ? map(payload.name, function (value) {
                return data.indexOfName(value);
            })
            : data.indexOfName(payload.name);
    }
}

/**
 * Enable property storage to any host object.
 * Notice: Serialization is not supported.
 *
 * For example:
 * var inner = zrUitl.makeInner();
 *
 * function some1(hostObj) {
 *      inner(hostObj).someProperty = 1212;
 *      ...
 * }
 * function some2() {
 *      var fields = inner(this);
 *      fields.someProperty1 = 1212;
 *      fields.someProperty2 = 'xx';
 *      ...
 * }
 *
 * @return {Function}
 */
function makeInner() {
    // Consider different scope by es module import.
    var key = '__\0ec_inner_' + innerUniqueIndex++ + '_' + Math.random().toFixed(5);
    return function (hostObj) {
        return hostObj[key] || (hostObj[key] = {});
    };
}
var innerUniqueIndex = 0;

/**
 * @param {module:echarts/model/Global} ecModel
 * @param {string|Object} finder
 *        If string, e.g., 'geo', means {geoIndex: 0}.
 *        If Object, could contain some of these properties below:
 *        {
 *            seriesIndex, seriesId, seriesName,
 *            geoIndex, geoId, geoName,
 *            bmapIndex, bmapId, bmapName,
 *            xAxisIndex, xAxisId, xAxisName,
 *            yAxisIndex, yAxisId, yAxisName,
 *            gridIndex, gridId, gridName,
 *            ... (can be extended)
 *        }
 *        Each properties can be number|string|Array.<number>|Array.<string>
 *        For example, a finder could be
 *        {
 *            seriesIndex: 3,
 *            geoId: ['aa', 'cc'],
 *            gridName: ['xx', 'rr']
 *        }
 *        xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify)
 *        If nothing or null/undefined specified, return nothing.
 * @param {Object} [opt]
 * @param {string} [opt.defaultMainType]
 * @param {Array.<string>} [opt.includeMainTypes]
 * @return {Object} result like:
 *        {
 *            seriesModels: [seriesModel1, seriesModel2],
 *            seriesModel: seriesModel1, // The first model
 *            geoModels: [geoModel1, geoModel2],
 *            geoModel: geoModel1, // The first model
 *            ...
 *        }
 */
function parseFinder(ecModel, finder, opt) {
    if (isString(finder)) {
        var obj = {};
        obj[finder + 'Index'] = 0;
        finder = obj;
    }

    var defaultMainType = opt && opt.defaultMainType;
    if (defaultMainType
        && !has(finder, defaultMainType + 'Index')
        && !has(finder, defaultMainType + 'Id')
        && !has(finder, defaultMainType + 'Name')
    ) {
        finder[defaultMainType + 'Index'] = 0;
    }

    var result = {};

    each$2(finder, function (value, key) {
        var value = finder[key];

        // Exclude 'dataIndex' and other illgal keys.
        if (key === 'dataIndex' || key === 'dataIndexInside') {
            result[key] = value;
            return;
        }

        var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || [];
        var mainType = parsedKey[1];
        var queryType = (parsedKey[2] || '').toLowerCase();

        if (!mainType
            || !queryType
            || value == null
            || (queryType === 'index' && value === 'none')
            || (opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0)
        ) {
            return;
        }

        var queryParam = {mainType: mainType};
        if (queryType !== 'index' || value !== 'all') {
            queryParam[queryType] = value;
        }

        var models = ecModel.queryComponents(queryParam);
        result[mainType + 'Models'] = models;
        result[mainType + 'Model'] = models[0];
    });

    return result;
}

function has(obj, prop) {
    return obj && obj.hasOwnProperty(prop);
}

function setAttribute(dom, key, value) {
    dom.setAttribute
        ? dom.setAttribute(key, value)
        : (dom[key] = value);
}

function getAttribute(dom, key) {
    return dom.getAttribute
        ? dom.getAttribute(key)
        : dom[key];
}

function getTooltipRenderMode(renderModeOption) {
    if (renderModeOption === 'auto') {
        // Using html when `document` exists, use richText otherwise
        return env$1.domSupported ? 'html' : 'richText';
    }
    else {
        return renderModeOption || 'html';
    }
}

/**
 * Group a list by key.
 *
 * @param {Array} array
 * @param {Function} getKey
 *        param {*} Array item
 *        return {string} key
 * @return {Object} Result
 *        {Array}: keys,
 *        {module:zrender/core/util/HashMap} buckets: {key -> Array}
 */
function groupData(array, getKey) {
    var buckets = createHashMap();
    var keys = [];

    each$1(array, function (item) {
        var key = getKey(item);
        (buckets.get(key)
            || (keys.push(key), buckets.set(key, []))
        ).push(item);
    });

    return {keys: keys, buckets: buckets};
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var TYPE_DELIMITER = '.';
var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';

/**
 * Notice, parseClassType('') should returns {main: '', sub: ''}
 * @public
 */
function parseClassType$1(componentType) {
    var ret = {main: '', sub: ''};
    if (componentType) {
        componentType = componentType.split(TYPE_DELIMITER);
        ret.main = componentType[0] || '';
        ret.sub = componentType[1] || '';
    }
    return ret;
}

/**
 * @public
 */
function checkClassType(componentType) {
    assert$1(
        /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType),
        'componentType "' + componentType + '" illegal'
    );
}

/**
 * @public
 */
function enableClassExtend(RootClass, mandatoryMethods) {

    RootClass.$constructor = RootClass;
    RootClass.extend = function (proto) {

        if (__DEV__) {
            each$1(mandatoryMethods, function (method) {
                if (!proto[method]) {
                    console.warn(
                        'Method `' + method + '` should be implemented'
                        + (proto.type ? ' in ' + proto.type : '') + '.'
                    );
                }
            });
        }

        var superClass = this;
        var ExtendedClass = function () {
            if (!proto.$constructor) {
                superClass.apply(this, arguments);
            }
            else {
                proto.$constructor.apply(this, arguments);
            }
        };

        extend(ExtendedClass.prototype, proto);

        ExtendedClass.extend = this.extend;
        ExtendedClass.superCall = superCall;
        ExtendedClass.superApply = superApply;
        inherits(ExtendedClass, this);
        ExtendedClass.superClass = superClass;

        return ExtendedClass;
    };
}

var classBase = 0;

/**
 * Can not use instanceof, consider different scope by
 * cross domain or es module import in ec extensions.
 * Mount a method "isInstance()" to Clz.
 */
function enableClassCheck(Clz) {
    var classAttr = ['__\0is_clz', classBase++, Math.random().toFixed(3)].join('_');
    Clz.prototype[classAttr] = true;

    if (__DEV__) {
        assert$1(!Clz.isInstance, 'The method "is" can not be defined.');
    }

    Clz.isInstance = function (obj) {
        return !!(obj && obj[classAttr]);
    };
}

// superCall should have class info, which can not be fetch from 'this'.
// Consider this case:
// class A has method f,
// class B inherits class A, overrides method f, f call superApply('f'),
// class C inherits class B, do not overrides method f,
// then when method of class C is called, dead loop occured.
function superCall(context, methodName) {
    var args = slice(arguments, 2);
    return this.superClass.prototype[methodName].apply(context, args);
}

function superApply(context, methodName, args) {
    return this.superClass.prototype[methodName].apply(context, args);
}

/**
 * @param {Object} entity
 * @param {Object} options
 * @param {boolean} [options.registerWhenExtend]
 * @public
 */
function enableClassManagement(entity, options) {
    options = options || {};

    /**
     * Component model classes
     * key: componentType,
     * value:
     *     componentClass, when componentType is 'xxx'
     *     or Object.<subKey, componentClass>, when componentType is 'xxx.yy'
     * @type {Object}
     */
    var storage = {};

    entity.registerClass = function (Clazz, componentType) {
        if (componentType) {
            checkClassType(componentType);
            componentType = parseClassType$1(componentType);

            if (!componentType.sub) {
                if (__DEV__) {
                    if (storage[componentType.main]) {
                        console.warn(componentType.main + ' exists.');
                    }
                }
                storage[componentType.main] = Clazz;
            }
            else if (componentType.sub !== IS_CONTAINER) {
                var container = makeContainer(componentType);
                container[componentType.sub] = Clazz;
            }
        }
        return Clazz;
    };

    entity.getClass = function (componentMainType, subType, throwWhenNotFound) {
        var Clazz = storage[componentMainType];

        if (Clazz && Clazz[IS_CONTAINER]) {
            Clazz = subType ? Clazz[subType] : null;
        }

        if (throwWhenNotFound && !Clazz) {
            throw new Error(
                !subType
                    ? componentMainType + '.' + 'type should be specified.'
                    : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.'
            );
        }

        return Clazz;
    };

    entity.getClassesByMainType = function (componentType) {
        componentType = parseClassType$1(componentType);

        var result = [];
        var obj = storage[componentType.main];

        if (obj && obj[IS_CONTAINER]) {
            each$1(obj, function (o, type) {
                type !== IS_CONTAINER && result.push(o);
            });
        }
        else {
            result.push(obj);
        }

        return result;
    };

    entity.hasClass = function (componentType) {
        // Just consider componentType.main.
        componentType = parseClassType$1(componentType);
        return !!storage[componentType.main];
    };

    /**
     * @return {Array.<string>} Like ['aa', 'bb'], but can not be ['aa.xx']
     */
    entity.getAllClassMainTypes = function () {
        var types = [];
        each$1(storage, function (obj, type) {
            types.push(type);
        });
        return types;
    };

    /**
     * If a main type is container and has sub types
     * @param  {string}  mainType
     * @return {boolean}
     */
    entity.hasSubTypes = function (componentType) {
        componentType = parseClassType$1(componentType);
        var obj = storage[componentType.main];
        return obj && obj[IS_CONTAINER];
    };

    entity.parseClassType = parseClassType$1;

    function makeContainer(componentType) {
        var container = storage[componentType.main];
        if (!container || !container[IS_CONTAINER]) {
            container = storage[componentType.main] = {};
            container[IS_CONTAINER] = true;
        }
        return container;
    }

    if (options.registerWhenExtend) {
        var originalExtend = entity.extend;
        if (originalExtend) {
            entity.extend = function (proto) {
                var ExtendedClass = originalExtend.call(this, proto);
                return entity.registerClass(ExtendedClass, proto.type);
            };
        }
    }

    return entity;
}

/**
 * @param {string|Array.<string>} properties
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO Parse shadow style
// TODO Only shallow path support
var makeStyleMapper = function (properties) {
    // Normalize
    for (var i = 0; i < properties.length; i++) {
        if (!properties[i][1]) {
            properties[i][1] = properties[i][0];
        }
    }
    return function (model, excludes, includes) {
        var style = {};
        for (var i = 0; i < properties.length; i++) {
            var propName = properties[i][1];
            if ((excludes && indexOf(excludes, propName) >= 0)
                || (includes && indexOf(includes, propName) < 0)
            ) {
                continue;
            }
            var val = model.getShallow(propName);
            if (val != null) {
                style[properties[i][0]] = val;
            }
        }
        return style;
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var getLineStyle = makeStyleMapper(
    [
        ['lineWidth', 'width'],
        ['stroke', 'color'],
        ['opacity'],
        ['shadowBlur'],
        ['shadowOffsetX'],
        ['shadowOffsetY'],
        ['shadowColor']
    ]
);

var lineStyleMixin = {
    getLineStyle: function (excludes) {
        var style = getLineStyle(this, excludes);
        // Always set lineDash whether dashed, otherwise we can not
        // erase the previous style when assigning to el.style.
        style.lineDash = this.getLineDash(style.lineWidth);
        return style;
    },

    getLineDash: function (lineWidth) {
        if (lineWidth == null) {
            lineWidth = 1;
        }
        var lineType = this.get('type');
        var dotSize = Math.max(lineWidth, 2);
        var dashSize = lineWidth * 4;
        return (lineType === 'solid' || lineType == null)
            // Use `false` but not `null` for the solid line here, because `null` might be
            // ignored when assigning to `el.style`. e.g., when setting `lineStyle.type` as
            // `'dashed'` and `emphasis.lineStyle.type` as `'solid'` in graph series, the
            // `lineDash` gotten form the latter one is not able to erase that from the former
            // one if using `null` here according to the emhpsis strategy in `util/graphic.js`.
            ? false
            : lineType === 'dashed'
            ? [dashSize, dashSize]
            : [dotSize, dotSize];
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var getAreaStyle = makeStyleMapper(
    [
        ['fill', 'color'],
        ['shadowBlur'],
        ['shadowOffsetX'],
        ['shadowOffsetY'],
        ['opacity'],
        ['shadowColor']
    ]
);

var areaStyleMixin = {
    getAreaStyle: function (excludes, includes) {
        return getAreaStyle(this, excludes, includes);
    }
};

/**
 * 曲线辅助模块
 * @module zrender/core/curve
 * @author pissang(https://www.github.com/pissang)
 */

var mathPow = Math.pow;
var mathSqrt$2 = Math.sqrt;

var EPSILON$1 = 1e-8;
var EPSILON_NUMERIC = 1e-4;

var THREE_SQRT = mathSqrt$2(3);
var ONE_THIRD = 1 / 3;

// 临时变量
var _v0 = create();
var _v1 = create();
var _v2 = create();

function isAroundZero(val) {
    return val > -EPSILON$1 && val < EPSILON$1;
}
function isNotAroundZero$1(val) {
    return val > EPSILON$1 || val < -EPSILON$1;
}
/**
 * 计算三次贝塞尔值
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {number} t
 * @return {number}
 */
function cubicAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return onet * onet * (onet * p0 + 3 * t * p1)
            + t * t * (t * p3 + 3 * onet * p2);
}

/**
 * 计算三次贝塞尔导数值
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {number} t
 * @return {number}
 */
function cubicDerivativeAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return 3 * (
        ((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet
        + (p3 - p2) * t * t
    );
}

/**
 * 计算三次贝塞尔方程根，使用盛金公式
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {number} val
 * @param  {Array.<number>} roots
 * @return {number} 有效根数目
 */
function cubicRootAt(p0, p1, p2, p3, val, roots) {
    // Evaluate roots of cubic functions
    var a = p3 + 3 * (p1 - p2) - p0;
    var b = 3 * (p2 - p1 * 2 + p0);
    var c = 3 * (p1 - p0);
    var d = p0 - val;

    var A = b * b - 3 * a * c;
    var B = b * c - 9 * a * d;
    var C = c * c - 3 * b * d;

    var n = 0;

    if (isAroundZero(A) && isAroundZero(B)) {
        if (isAroundZero(b)) {
            roots[0] = 0;
        }
        else {
            var t1 = -c / b;  //t1, t2, t3, b is not zero
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
    }
    else {
        var disc = B * B - 4 * A * C;

        if (isAroundZero(disc)) {
            var K = B / A;
            var t1 = -b / a + K;  // t1, a is not zero
            var t2 = -K / 2;  // t2, t3
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$2(disc);
            var Y1 = A * b + 1.5 * a * (-B + discSqrt);
            var Y2 = A * b + 1.5 * a * (-B - discSqrt);
            if (Y1 < 0) {
                Y1 = -mathPow(-Y1, ONE_THIRD);
            }
            else {
                Y1 = mathPow(Y1, ONE_THIRD);
            }
            if (Y2 < 0) {
                Y2 = -mathPow(-Y2, ONE_THIRD);
            }
            else {
                Y2 = mathPow(Y2, ONE_THIRD);
            }
            var t1 = (-b - (Y1 + Y2)) / (3 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
        else {
            var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt$2(A * A * A));
            var theta = Math.acos(T) / 3;
            var ASqrt = mathSqrt$2(A);
            var tmp = Math.cos(theta);

            var t1 = (-b - 2 * ASqrt * tmp) / (3 * a);
            var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a);
            var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
            if (t3 >= 0 && t3 <= 1) {
                roots[n++] = t3;
            }
        }
    }
    return n;
}

/**
 * 计算三次贝塞尔方程极限值的位置
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {Array.<number>} extrema
 * @return {number} 有效数目
 */
function cubicExtrema(p0, p1, p2, p3, extrema) {
    var b = 6 * p2 - 12 * p1 + 6 * p0;
    var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2;
    var c = 3 * p1 - 3 * p0;

    var n = 0;
    if (isAroundZero(a)) {
        if (isNotAroundZero$1(b)) {
            var t1 = -c / b;
            if (t1 >= 0 && t1 <= 1) {
                extrema[n++] = t1;
            }
        }
    }
    else {
        var disc = b * b - 4 * a * c;
        if (isAroundZero(disc)) {
            extrema[0] = -b / (2 * a);
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$2(disc);
            var t1 = (-b + discSqrt) / (2 * a);
            var t2 = (-b - discSqrt) / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                extrema[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                extrema[n++] = t2;
            }
        }
    }
    return n;
}

/**
 * 细分三次贝塞尔曲线
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} p3
 * @param  {number} t
 * @param  {Array.<number>} out
 */
function cubicSubdivide(p0, p1, p2, p3, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p23 = (p3 - p2) * t + p2;

    var p012 = (p12 - p01) * t + p01;
    var p123 = (p23 - p12) * t + p12;

    var p0123 = (p123 - p012) * t + p012;
    // Seg0
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;
    out[3] = p0123;
    // Seg1
    out[4] = p0123;
    out[5] = p123;
    out[6] = p23;
    out[7] = p3;
}

/**
 * 投射点到三次贝塞尔曲线上，返回投射距离。
 * 投射点有可能会有一个或者多个，这里只返回其中距离最短的一个。
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @param {number} x2
 * @param {number} y2
 * @param {number} x3
 * @param {number} y3
 * @param {number} x
 * @param {number} y
 * @param {Array.<number>} [out] 投射点
 * @return {number}
 */
function cubicProjectPoint(
    x0, y0, x1, y1, x2, y2, x3, y3,
    x, y, out
) {
    // http://pomax.github.io/bezierinfo/#projections
    var t;
    var interval = 0.005;
    var d = Infinity;
    var prev;
    var next;
    var d1;
    var d2;

    _v0[0] = x;
    _v0[1] = y;

    // 先粗略估计一下可能的最小距离的 t 值
    // PENDING
    for (var _t = 0; _t < 1; _t += 0.05) {
        _v1[0] = cubicAt(x0, x1, x2, x3, _t);
        _v1[1] = cubicAt(y0, y1, y2, y3, _t);
        d1 = distSquare(_v0, _v1);
        if (d1 < d) {
            t = _t;
            d = d1;
        }
    }
    d = Infinity;

    // At most 32 iteration
    for (var i = 0; i < 32; i++) {
        if (interval < EPSILON_NUMERIC) {
            break;
        }
        prev = t - interval;
        next = t + interval;
        // t - interval
        _v1[0] = cubicAt(x0, x1, x2, x3, prev);
        _v1[1] = cubicAt(y0, y1, y2, y3, prev);

        d1 = distSquare(_v1, _v0);

        if (prev >= 0 && d1 < d) {
            t = prev;
            d = d1;
        }
        else {
            // t + interval
            _v2[0] = cubicAt(x0, x1, x2, x3, next);
            _v2[1] = cubicAt(y0, y1, y2, y3, next);
            d2 = distSquare(_v2, _v0);

            if (next <= 1 && d2 < d) {
                t = next;
                d = d2;
            }
            else {
                interval *= 0.5;
            }
        }
    }
    // t
    if (out) {
        out[0] = cubicAt(x0, x1, x2, x3, t);
        out[1] = cubicAt(y0, y1, y2, y3, t);
    }
    // console.log(interval, i);
    return mathSqrt$2(d);
}

/**
 * 计算二次方贝塞尔值
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} t
 * @return {number}
 */
function quadraticAt(p0, p1, p2, t) {
    var onet = 1 - t;
    return onet * (onet * p0 + 2 * t * p1) + t * t * p2;
}

/**
 * 计算二次方贝塞尔导数值
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} t
 * @return {number}
 */
function quadraticDerivativeAt(p0, p1, p2, t) {
    return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1));
}

/**
 * 计算二次方贝塞尔方程根
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} t
 * @param  {Array.<number>} roots
 * @return {number} 有效根数目
 */
function quadraticRootAt(p0, p1, p2, val, roots) {
    var a = p0 - 2 * p1 + p2;
    var b = 2 * (p1 - p0);
    var c = p0 - val;

    var n = 0;
    if (isAroundZero(a)) {
        if (isNotAroundZero$1(b)) {
            var t1 = -c / b;
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
    }
    else {
        var disc = b * b - 4 * a * c;
        if (isAroundZero(disc)) {
            var t1 = -b / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$2(disc);
            var t1 = (-b + discSqrt) / (2 * a);
            var t2 = (-b - discSqrt) / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
        }
    }
    return n;
}

/**
 * 计算二次贝塞尔方程极限值
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @return {number}
 */
function quadraticExtremum(p0, p1, p2) {
    var divider = p0 + p2 - 2 * p1;
    if (divider === 0) {
        // p1 is center of p0 and p2
        return 0.5;
    }
    else {
        return (p0 - p1) / divider;
    }
}

/**
 * 细分二次贝塞尔曲线
 * @memberOf module:zrender/core/curve
 * @param  {number} p0
 * @param  {number} p1
 * @param  {number} p2
 * @param  {number} t
 * @param  {Array.<number>} out
 */
function quadraticSubdivide(p0, p1, p2, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p012 = (p12 - p01) * t + p01;

    // Seg0
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;

    // Seg1
    out[3] = p012;
    out[4] = p12;
    out[5] = p2;
}

/**
 * 投射点到二次贝塞尔曲线上，返回投射距离。
 * 投射点有可能会有一个或者多个，这里只返回其中距离最短的一个。
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @param {number} x2
 * @param {number} y2
 * @param {number} x
 * @param {number} y
 * @param {Array.<number>} out 投射点
 * @return {number}
 */
function quadraticProjectPoint(
    x0, y0, x1, y1, x2, y2,
    x, y, out
) {
    // http://pomax.github.io/bezierinfo/#projections
    var t;
    var interval = 0.005;
    var d = Infinity;

    _v0[0] = x;
    _v0[1] = y;

    // 先粗略估计一下可能的最小距离的 t 值
    // PENDING
    for (var _t = 0; _t < 1; _t += 0.05) {
        _v1[0] = quadraticAt(x0, x1, x2, _t);
        _v1[1] = quadraticAt(y0, y1, y2, _t);
        var d1 = distSquare(_v0, _v1);
        if (d1 < d) {
            t = _t;
            d = d1;
        }
    }
    d = Infinity;

    // At most 32 iteration
    for (var i = 0; i < 32; i++) {
        if (interval < EPSILON_NUMERIC) {
            break;
        }
        var prev = t - interval;
        var next = t + interval;
        // t - interval
        _v1[0] = quadraticAt(x0, x1, x2, prev);
        _v1[1] = quadraticAt(y0, y1, y2, prev);

        var d1 = distSquare(_v1, _v0);

        if (prev >= 0 && d1 < d) {
            t = prev;
            d = d1;
        }
        else {
            // t + interval
            _v2[0] = quadraticAt(x0, x1, x2, next);
            _v2[1] = quadraticAt(y0, y1, y2, next);
            var d2 = distSquare(_v2, _v0);
            if (next <= 1 && d2 < d) {
                t = next;
                d = d2;
            }
            else {
                interval *= 0.5;
            }
        }
    }
    // t
    if (out) {
        out[0] = quadraticAt(x0, x1, x2, t);
        out[1] = quadraticAt(y0, y1, y2, t);
    }
    // console.log(interval, i);
    return mathSqrt$2(d);
}

/**
 * @author Yi Shen(https://github.com/pissang)
 */

var mathMin$3 = Math.min;
var mathMax$3 = Math.max;
var mathSin$2 = Math.sin;
var mathCos$2 = Math.cos;
var PI2 = Math.PI * 2;

var start = create();
var end = create();
var extremity = create();

/**
 * 从顶点数组中计算出最小包围盒，写入`min`和`max`中
 * @module zrender/core/bbox
 * @param {Array<Object>} points 顶点数组
 * @param {number} min
 * @param {number} max
 */
function fromPoints(points, min$$1, max$$1) {
    if (points.length === 0) {
        return;
    }
    var p = points[0];
    var left = p[0];
    var right = p[0];
    var top = p[1];
    var bottom = p[1];
    var i;

    for (i = 1; i < points.length; i++) {
        p = points[i];
        left = mathMin$3(left, p[0]);
        right = mathMax$3(right, p[0]);
        top = mathMin$3(top, p[1]);
        bottom = mathMax$3(bottom, p[1]);
    }

    min$$1[0] = left;
    min$$1[1] = top;
    max$$1[0] = right;
    max$$1[1] = bottom;
}

/**
 * @memberOf module:zrender/core/bbox
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @param {Array.<number>} min
 * @param {Array.<number>} max
 */
function fromLine(x0, y0, x1, y1, min$$1, max$$1) {
    min$$1[0] = mathMin$3(x0, x1);
    min$$1[1] = mathMin$3(y0, y1);
    max$$1[0] = mathMax$3(x0, x1);
    max$$1[1] = mathMax$3(y0, y1);
}

var xDim = [];
var yDim = [];
/**
 * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒，写入`min`和`max`中
 * @memberOf module:zrender/core/bbox
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @param {number} x2
 * @param {number} y2
 * @param {number} x3
 * @param {number} y3
 * @param {Array.<number>} min
 * @param {Array.<number>} max
 */
function fromCubic(
    x0, y0, x1, y1, x2, y2, x3, y3, min$$1, max$$1
) {
    var cubicExtrema$$1 = cubicExtrema;
    var cubicAt$$1 = cubicAt;
    var i;
    var n = cubicExtrema$$1(x0, x1, x2, x3, xDim);
    min$$1[0] = Infinity;
    min$$1[1] = Infinity;
    max$$1[0] = -Infinity;
    max$$1[1] = -Infinity;

    for (i = 0; i < n; i++) {
        var x = cubicAt$$1(x0, x1, x2, x3, xDim[i]);
        min$$1[0] = mathMin$3(x, min$$1[0]);
        max$$1[0] = mathMax$3(x, max$$1[0]);
    }
    n = cubicExtrema$$1(y0, y1, y2, y3, yDim);
    for (i = 0; i < n; i++) {
        var y = cubicAt$$1(y0, y1, y2, y3, yDim[i]);
        min$$1[1] = mathMin$3(y, min$$1[1]);
        max$$1[1] = mathMax$3(y, max$$1[1]);
    }

    min$$1[0] = mathMin$3(x0, min$$1[0]);
    max$$1[0] = mathMax$3(x0, max$$1[0]);
    min$$1[0] = mathMin$3(x3, min$$1[0]);
    max$$1[0] = mathMax$3(x3, max$$1[0]);

    min$$1[1] = mathMin$3(y0, min$$1[1]);
    max$$1[1] = mathMax$3(y0, max$$1[1]);
    min$$1[1] = mathMin$3(y3, min$$1[1]);
    max$$1[1] = mathMax$3(y3, max$$1[1]);
}

/**
 * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒，写入`min`和`max`中
 * @memberOf module:zrender/core/bbox
 * @param {number} x0
 * @param {number} y0
 * @param {number} x1
 * @param {number} y1
 * @param {number} x2
 * @param {number} y2
 * @param {Array.<number>} min
 * @param {Array.<number>} max
 */
function fromQuadratic(x0, y0, x1, y1, x2, y2, min$$1, max$$1) {
    var quadraticExtremum$$1 = quadraticExtremum;
    var quadraticAt$$1 = quadraticAt;
    // Find extremities, where derivative in x dim or y dim is zero
    var tx =
        mathMax$3(
            mathMin$3(quadraticExtremum$$1(x0, x1, x2), 1), 0
        );
    var ty =
        mathMax$3(
            mathMin$3(quadraticExtremum$$1(y0, y1, y2), 1), 0
        );

    var x = quadraticAt$$1(x0, x1, x2, tx);
    var y = quadraticAt$$1(y0, y1, y2, ty);

    min$$1[0] = mathMin$3(x0, x2, x);
    min$$1[1] = mathMin$3(y0, y2, y);
    max$$1[0] = mathMax$3(x0, x2, x);
    max$$1[1] = mathMax$3(y0, y2, y);
}

/**
 * 从圆弧中计算出最小包围盒，写入`min`和`max`中
 * @method
 * @memberOf module:zrender/core/bbox
 * @param {number} x
 * @param {number} y
 * @param {number} rx
 * @param {number} ry
 * @param {number} startAngle
 * @param {number} endAngle
 * @param {number} anticlockwise
 * @param {Array.<number>} min
 * @param {Array.<number>} max
 */
function fromArc(
    x, y, rx, ry, startAngle, endAngle, anticlockwise, min$$1, max$$1
) {
    var vec2Min = min;
    var vec2Max = max;

    var diff = Math.abs(startAngle - endAngle);


    if (diff % PI2 < 1e-4 && diff > 1e-4) {
        // Is a circle
        min$$1[0] = x - rx;
        min$$1[1] = y - ry;
        max$$1[0] = x + rx;
        max$$1[1] = y + ry;
        return;
    }

    start[0] = mathCos$2(startAngle) * rx + x;
    start[1] = mathSin$2(startAngle) * ry + y;

    end[0] = mathCos$2(endAngle) * rx + x;
    end[1] = mathSin$2(endAngle) * ry + y;

    vec2Min(min$$1, start, end);
    vec2Max(max$$1, start, end);

    // Thresh to [0, Math.PI * 2]
    startAngle = startAngle % (PI2);
    if (startAngle < 0) {
        startAngle = startAngle + PI2;
    }
    endAngle = endAngle % (PI2);
    if (endAngle < 0) {
        endAngle = endAngle + PI2;
    }

    if (startAngle > endAngle && !anticlockwise) {
        endAngle += PI2;
    }
    else if (startAngle < endAngle && anticlockwise) {
        startAngle += PI2;
    }
    if (anticlockwise) {
        var tmp = endAngle;
        endAngle = startAngle;
        startAngle = tmp;
    }

    // var number = 0;
    // var step = (anticlockwise ? -Math.PI : Math.PI) / 2;
    for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
        if (angle > startAngle) {
            extremity[0] = mathCos$2(angle) * rx + x;
            extremity[1] = mathSin$2(angle) * ry + y;

            vec2Min(min$$1, extremity, min$$1);
            vec2Max(max$$1, extremity, max$$1);
        }
    }
}

/**
 * Path 代理，可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中
 * 可以用于 isInsidePath 判断以及获取boundingRect
 *
 * @module zrender/core/PathProxy
 * @author Yi Shen (http://www.github.com/pissang)
 */

// TODO getTotalLength, getPointAtLength

/* global Float32Array */

var CMD = {
    M: 1,
    L: 2,
    C: 3,
    Q: 4,
    A: 5,
    Z: 6,
    // Rect
    R: 7
};

// var CMD_MEM_SIZE = {
//     M: 3,
//     L: 3,
//     C: 7,
//     Q: 5,
//     A: 9,
//     R: 5,
//     Z: 1
// };

var min$1 = [];
var max$1 = [];
var min2 = [];
var max2 = [];
var mathMin$2 = Math.min;
var mathMax$2 = Math.max;
var mathCos$1 = Math.cos;
var mathSin$1 = Math.sin;
var mathSqrt$1 = Math.sqrt;
var mathAbs = Math.abs;

var hasTypedArray = typeof Float32Array !== 'undefined';

/**
 * @alias module:zrender/core/PathProxy
 * @constructor
 */
var PathProxy = function (notSaveData) {

    this._saveData = !(notSaveData || false);

    if (this._saveData) {
        /**
         * Path data. Stored as flat array
         * @type {Array.<Object>}
         */
        this.data = [];
    }

    this._ctx = null;
};

/**
 * 快速计算Path包围盒（并不是最小包围盒）
 * @return {Object}
 */
PathProxy.prototype = {

    constructor: PathProxy,

    _xi: 0,
    _yi: 0,

    _x0: 0,
    _y0: 0,
    // Unit x, Unit y. Provide for avoiding drawing that too short line segment
    _ux: 0,
    _uy: 0,

    _len: 0,

    _lineDash: null,

    _dashOffset: 0,

    _dashIdx: 0,

    _dashSum: 0,

    /**
     * @readOnly
     */
    setScale: function (sx, sy, segmentIgnoreThreshold) {
        // Compat. Previously there is no segmentIgnoreThreshold.
        segmentIgnoreThreshold = segmentIgnoreThreshold || 0;
        this._ux = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sx) || 0;
        this._uy = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sy) || 0;
    },

    getContext: function () {
        return this._ctx;
    },

    /**
     * @param  {CanvasRenderingContext2D} ctx
     * @return {module:zrender/core/PathProxy}
     */
    beginPath: function (ctx) {

        this._ctx = ctx;

        ctx && ctx.beginPath();

        ctx && (this.dpr = ctx.dpr);

        // Reset
        if (this._saveData) {
            this._len = 0;
        }

        if (this._lineDash) {
            this._lineDash = null;

            this._dashOffset = 0;
        }

        return this;
    },

    /**
     * @param  {number} x
     * @param  {number} y
     * @return {module:zrender/core/PathProxy}
     */
    moveTo: function (x, y) {
        this.addData(CMD.M, x, y);
        this._ctx && this._ctx.moveTo(x, y);

        // x0, y0, xi, yi 是记录在 _dashedXXXXTo 方法中使用
        // xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。
        // 有可能在 beginPath 之后直接调用 lineTo，这时候 x0, y0 需要
        // 在 lineTo 方法中记录，这里先不考虑这种情况，dashed line 也只在 IE10- 中不支持
        this._x0 = x;
        this._y0 = y;

        this._xi = x;
        this._yi = y;

        return this;
    },

    /**
     * @param  {number} x
     * @param  {number} y
     * @return {module:zrender/core/PathProxy}
     */
    lineTo: function (x, y) {
        var exceedUnit = mathAbs(x - this._xi) > this._ux
            || mathAbs(y - this._yi) > this._uy
            // Force draw the first segment
            || this._len < 5;

        this.addData(CMD.L, x, y);

        if (this._ctx && exceedUnit) {
            this._needsDash() ? this._dashedLineTo(x, y)
                : this._ctx.lineTo(x, y);
        }
        if (exceedUnit) {
            this._xi = x;
            this._yi = y;
        }

        return this;
    },

    /**
     * @param  {number} x1
     * @param  {number} y1
     * @param  {number} x2
     * @param  {number} y2
     * @param  {number} x3
     * @param  {number} y3
     * @return {module:zrender/core/PathProxy}
     */
    bezierCurveTo: function (x1, y1, x2, y2, x3, y3) {
        this.addData(CMD.C, x1, y1, x2, y2, x3, y3);
        if (this._ctx) {
            this._needsDash() ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3)
                : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
        }
        this._xi = x3;
        this._yi = y3;
        return this;
    },

    /**
     * @param  {number} x1
     * @param  {number} y1
     * @param  {number} x2
     * @param  {number} y2
     * @return {module:zrender/core/PathProxy}
     */
    quadraticCurveTo: function (x1, y1, x2, y2) {
        this.addData(CMD.Q, x1, y1, x2, y2);
        if (this._ctx) {
            this._needsDash() ? this._dashedQuadraticTo(x1, y1, x2, y2)
                : this._ctx.quadraticCurveTo(x1, y1, x2, y2);
        }
        this._xi = x2;
        this._yi = y2;
        return this;
    },

    /**
     * @param  {number} cx
     * @param  {number} cy
     * @param  {number} r
     * @param  {number} startAngle
     * @param  {number} endAngle
     * @param  {boolean} anticlockwise
     * @return {module:zrender/core/PathProxy}
     */
    arc: function (cx, cy, r, startAngle, endAngle, anticlockwise) {
        this.addData(
            CMD.A, cx, cy, r, r, startAngle, endAngle - startAngle, 0, anticlockwise ? 0 : 1
        );
        this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);

        this._xi = mathCos$1(endAngle) * r + cx;
        this._yi = mathSin$1(endAngle) * r + cy;
        return this;
    },

    // TODO
    arcTo: function (x1, y1, x2, y2, radius) {
        if (this._ctx) {
            this._ctx.arcTo(x1, y1, x2, y2, radius);
        }
        return this;
    },

    // TODO
    rect: function (x, y, w, h) {
        this._ctx && this._ctx.rect(x, y, w, h);
        this.addData(CMD.R, x, y, w, h);
        return this;
    },

    /**
     * @return {module:zrender/core/PathProxy}
     */
    closePath: function () {
        this.addData(CMD.Z);

        var ctx = this._ctx;
        var x0 = this._x0;
        var y0 = this._y0;
        if (ctx) {
            this._needsDash() && this._dashedLineTo(x0, y0);
            ctx.closePath();
        }

        this._xi = x0;
        this._yi = y0;
        return this;
    },

    /**
     * Context 从外部传入，因为有可能是 rebuildPath 完之后再 fill。
     * stroke 同样
     * @param {CanvasRenderingContext2D} ctx
     * @return {module:zrender/core/PathProxy}
     */
    fill: function (ctx) {
        ctx && ctx.fill();
        this.toStatic();
    },

    /**
     * @param {CanvasRenderingContext2D} ctx
     * @return {module:zrender/core/PathProxy}
     */
    stroke: function (ctx) {
        ctx && ctx.stroke();
        this.toStatic();
    },

    /**
     * 必须在其它绘制命令前调用
     * Must be invoked before all other path drawing methods
     * @return {module:zrender/core/PathProxy}
     */
    setLineDash: function (lineDash) {
        if (lineDash instanceof Array) {
            this._lineDash = lineDash;

            this._dashIdx = 0;

            var lineDashSum = 0;
            for (var i = 0; i < lineDash.length; i++) {
                lineDashSum += lineDash[i];
            }
            this._dashSum = lineDashSum;
        }
        return this;
    },

    /**
     * 必须在其它绘制命令前调用
     * Must be invoked before all other path drawing methods
     * @return {module:zrender/core/PathProxy}
     */
    setLineDashOffset: function (offset) {
        this._dashOffset = offset;
        return this;
    },

    /**
     *
     * @return {boolean}
     */
    len: function () {
        return this._len;
    },

    /**
     * 直接设置 Path 数据
     */
    setData: function (data) {

        var len$$1 = data.length;

        if (!(this.data && this.data.length === len$$1) && hasTypedArray) {
            this.data = new Float32Array(len$$1);
        }

        for (var i = 0; i < len$$1; i++) {
            this.data[i] = data[i];
        }

        this._len = len$$1;
    },

    /**
     * 添加子路径
     * @param {module:zrender/core/PathProxy|Array.<module:zrender/core/PathProxy>} path
     */
    appendPath: function (path) {
        if (!(path instanceof Array)) {
            path = [path];
        }
        var len$$1 = path.length;
        var appendSize = 0;
        var offset = this._len;
        for (var i = 0; i < len$$1; i++) {
            appendSize += path[i].len();
        }
        if (hasTypedArray && (this.data instanceof Float32Array)) {
            this.data = new Float32Array(offset + appendSize);
        }
        for (var i = 0; i < len$$1; i++) {
            var appendPathData = path[i].data;
            for (var k = 0; k < appendPathData.length; k++) {
                this.data[offset++] = appendPathData[k];
            }
        }
        this._len = offset;
    },

    /**
     * 填充 Path 数据。
     * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。
     */
    addData: function (cmd) {
        if (!this._saveData) {
            return;
        }

        var data = this.data;
        if (this._len + arguments.length > data.length) {
            // 因为之前的数组已经转换成静态的 Float32Array
            // 所以不够用时需要扩展一个新的动态数组
            this._expandData();
            data = this.data;
        }
        for (var i = 0; i < arguments.length; i++) {
            data[this._len++] = arguments[i];
        }

        this._prevCmd = cmd;
    },

    _expandData: function () {
        // Only if data is Float32Array
        if (!(this.data instanceof Array)) {
            var newData = [];
            for (var i = 0; i < this._len; i++) {
                newData[i] = this.data[i];
            }
            this.data = newData;
        }
    },

    /**
     * If needs js implemented dashed line
     * @return {boolean}
     * @private
     */
    _needsDash: function () {
        return this._lineDash;
    },

    _dashedLineTo: function (x1, y1) {
        var dashSum = this._dashSum;
        var offset = this._dashOffset;
        var lineDash = this._lineDash;
        var ctx = this._ctx;

        var x0 = this._xi;
        var y0 = this._yi;
        var dx = x1 - x0;
        var dy = y1 - y0;
        var dist$$1 = mathSqrt$1(dx * dx + dy * dy);
        var x = x0;
        var y = y0;
        var dash;
        var nDash = lineDash.length;
        var idx;
        dx /= dist$$1;
        dy /= dist$$1;

        if (offset < 0) {
            // Convert to positive offset
            offset = dashSum + offset;
        }
        offset %= dashSum;
        x -= offset * dx;
        y -= offset * dy;

        while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1)
        || (dx === 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) {
            idx = this._dashIdx;
            dash = lineDash[idx];
            x += dx * dash;
            y += dy * dash;
            this._dashIdx = (idx + 1) % nDash;
            // Skip positive offset
            if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) {
                continue;
            }
            ctx[idx % 2 ? 'moveTo' : 'lineTo'](
                dx >= 0 ? mathMin$2(x, x1) : mathMax$2(x, x1),
                dy >= 0 ? mathMin$2(y, y1) : mathMax$2(y, y1)
            );
        }
        // Offset for next lineTo
        dx = x - x1;
        dy = y - y1;
        this._dashOffset = -mathSqrt$1(dx * dx + dy * dy);
    },

    // Not accurate dashed line to
    _dashedBezierTo: function (x1, y1, x2, y2, x3, y3) {
        var dashSum = this._dashSum;
        var offset = this._dashOffset;
        var lineDash = this._lineDash;
        var ctx = this._ctx;

        var x0 = this._xi;
        var y0 = this._yi;
        var t;
        var dx;
        var dy;
        var cubicAt$$1 = cubicAt;
        var bezierLen = 0;
        var idx = this._dashIdx;
        var nDash = lineDash.length;

        var x;
        var y;

        var tmpLen = 0;

        if (offset < 0) {
            // Convert to positive offset
            offset = dashSum + offset;
        }
        offset %= dashSum;
        // Bezier approx length
        for (t = 0; t < 1; t += 0.1) {
            dx = cubicAt$$1(x0, x1, x2, x3, t + 0.1)
                - cubicAt$$1(x0, x1, x2, x3, t);
            dy = cubicAt$$1(y0, y1, y2, y3, t + 0.1)
                - cubicAt$$1(y0, y1, y2, y3, t);
            bezierLen += mathSqrt$1(dx * dx + dy * dy);
        }

        // Find idx after add offset
        for (; idx < nDash; idx++) {
            tmpLen += lineDash[idx];
            if (tmpLen > offset) {
                break;
            }
        }
        t = (tmpLen - offset) / bezierLen;

        while (t <= 1) {

            x = cubicAt$$1(x0, x1, x2, x3, t);
            y = cubicAt$$1(y0, y1, y2, y3, t);

            // Use line to approximate dashed bezier
            // Bad result if dash is long
            idx % 2 ? ctx.moveTo(x, y)
                : ctx.lineTo(x, y);

            t += lineDash[idx] / bezierLen;

            idx = (idx + 1) % nDash;
        }

        // Finish the last segment and calculate the new offset
        (idx % 2 !== 0) && ctx.lineTo(x3, y3);
        dx = x3 - x;
        dy = y3 - y;
        this._dashOffset = -mathSqrt$1(dx * dx + dy * dy);
    },

    _dashedQuadraticTo: function (x1, y1, x2, y2) {
        // Convert quadratic to cubic using degree elevation
        var x3 = x2;
        var y3 = y2;
        x2 = (x2 + 2 * x1) / 3;
        y2 = (y2 + 2 * y1) / 3;
        x1 = (this._xi + 2 * x1) / 3;
        y1 = (this._yi + 2 * y1) / 3;

        this._dashedBezierTo(x1, y1, x2, y2, x3, y3);
    },

    /**
     * 转成静态的 Float32Array 减少堆内存占用
     * Convert dynamic array to static Float32Array
     */
    toStatic: function () {
        var data = this.data;
        if (data instanceof Array) {
            data.length = this._len;
            if (hasTypedArray) {
                this.data = new Float32Array(data);
            }
        }
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getBoundingRect: function () {
        min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE;
        max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE;

        var data = this.data;
        var xi = 0;
        var yi = 0;
        var x0 = 0;
        var y0 = 0;

        for (var i = 0; i < data.length;) {
            var cmd = data[i++];

            if (i === 1) {
                // 如果第一个命令是 L, C, Q
                // 则 previous point 同绘制命令的第一个 point
                //
                // 第一个命令为 Arc 的情况下会在后面特殊处理
                xi = data[i];
                yi = data[i + 1];

                x0 = xi;
                y0 = yi;
            }

            switch (cmd) {
                case CMD.M:
                    // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点
                    // 在 closePath 的时候使用
                    x0 = data[i++];
                    y0 = data[i++];
                    xi = x0;
                    yi = y0;
                    min2[0] = x0;
                    min2[1] = y0;
                    max2[0] = x0;
                    max2[1] = y0;
                    break;
                case CMD.L:
                    fromLine(xi, yi, data[i], data[i + 1], min2, max2);
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD.C:
                    fromCubic(
                        xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
                        min2, max2
                    );
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD.Q:
                    fromQuadratic(
                        xi, yi, data[i++], data[i++], data[i], data[i + 1],
                        min2, max2
                    );
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD.A:
                    // TODO Arc 判断的开销比较大
                    var cx = data[i++];
                    var cy = data[i++];
                    var rx = data[i++];
                    var ry = data[i++];
                    var startAngle = data[i++];
                    var endAngle = data[i++] + startAngle;
                    // TODO Arc 旋转
                    i += 1;
                    var anticlockwise = 1 - data[i++];

                    if (i === 1) {
                        // 直接使用 arc 命令
                        // 第一个命令起点还未定义
                        x0 = mathCos$1(startAngle) * rx + cx;
                        y0 = mathSin$1(startAngle) * ry + cy;
                    }

                    fromArc(
                        cx, cy, rx, ry, startAngle, endAngle,
                        anticlockwise, min2, max2
                    );

                    xi = mathCos$1(endAngle) * rx + cx;
                    yi = mathSin$1(endAngle) * ry + cy;
                    break;
                case CMD.R:
                    x0 = xi = data[i++];
                    y0 = yi = data[i++];
                    var width = data[i++];
                    var height = data[i++];
                    // Use fromLine
                    fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
                    break;
                case CMD.Z:
                    xi = x0;
                    yi = y0;
                    break;
            }

            // Union
            min(min$1, min$1, min2);
            max(max$1, max$1, max2);
        }

        // No data
        if (i === 0) {
            min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
        }

        return new BoundingRect(
            min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]
        );
    },

    /**
     * Rebuild path from current data
     * Rebuild path will not consider javascript implemented line dash.
     * @param {CanvasRenderingContext2D} ctx
     */
    rebuildPath: function (ctx) {
        var d = this.data;
        var x0;
        var y0;
        var xi;
        var yi;
        var x;
        var y;
        var ux = this._ux;
        var uy = this._uy;
        var len$$1 = this._len;
        for (var i = 0; i < len$$1;) {
            var cmd = d[i++];

            if (i === 1) {
                // 如果第一个命令是 L, C, Q
                // 则 previous point 同绘制命令的第一个 point
                //
                // 第一个命令为 Arc 的情况下会在后面特殊处理
                xi = d[i];
                yi = d[i + 1];

                x0 = xi;
                y0 = yi;
            }
            switch (cmd) {
                case CMD.M:
                    x0 = xi = d[i++];
                    y0 = yi = d[i++];
                    ctx.moveTo(xi, yi);
                    break;
                case CMD.L:
                    x = d[i++];
                    y = d[i++];
                    // Not draw too small seg between
                    if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len$$1 - 1) {
                        ctx.lineTo(x, y);
                        xi = x;
                        yi = y;
                    }
                    break;
                case CMD.C:
                    ctx.bezierCurveTo(
                        d[i++], d[i++], d[i++], d[i++], d[i++], d[i++]
                    );
                    xi = d[i - 2];
                    yi = d[i - 1];
                    break;
                case CMD.Q:
                    ctx.quadraticCurveTo(d[i++], d[i++], d[i++], d[i++]);
                    xi = d[i - 2];
                    yi = d[i - 1];
                    break;
                case CMD.A:
                    var cx = d[i++];
                    var cy = d[i++];
                    var rx = d[i++];
                    var ry = d[i++];
                    var theta = d[i++];
                    var dTheta = d[i++];
                    var psi = d[i++];
                    var fs = d[i++];
                    var r = (rx > ry) ? rx : ry;
                    var scaleX = (rx > ry) ? 1 : rx / ry;
                    var scaleY = (rx > ry) ? ry / rx : 1;
                    var isEllipse = Math.abs(rx - ry) > 1e-3;
                    var endAngle = theta + dTheta;
                    if (isEllipse) {
                        ctx.translate(cx, cy);
                        ctx.rotate(psi);
                        ctx.scale(scaleX, scaleY);
                        ctx.arc(0, 0, r, theta, endAngle, 1 - fs);
                        ctx.scale(1 / scaleX, 1 / scaleY);
                        ctx.rotate(-psi);
                        ctx.translate(-cx, -cy);
                    }
                    else {
                        ctx.arc(cx, cy, r, theta, endAngle, 1 - fs);
                    }

                    if (i === 1) {
                        // 直接使用 arc 命令
                        // 第一个命令起点还未定义
                        x0 = mathCos$1(theta) * rx + cx;
                        y0 = mathSin$1(theta) * ry + cy;
                    }
                    xi = mathCos$1(endAngle) * rx + cx;
                    yi = mathSin$1(endAngle) * ry + cy;
                    break;
                case CMD.R:
                    x0 = xi = d[i];
                    y0 = yi = d[i + 1];
                    ctx.rect(d[i++], d[i++], d[i++], d[i++]);
                    break;
                case CMD.Z:
                    ctx.closePath();
                    xi = x0;
                    yi = y0;
            }
        }
    }
};

PathProxy.CMD = CMD;

/**
 * 线段包含判断
 * @param  {number}  x0
 * @param  {number}  y0
 * @param  {number}  x1
 * @param  {number}  y1
 * @param  {number}  lineWidth
 * @param  {number}  x
 * @param  {number}  y
 * @return {boolean}
 */
function containStroke$1(x0, y0, x1, y1, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    var _a = 0;
    var _b = x0;
    // Quick reject
    if (
        (y > y0 + _l && y > y1 + _l)
        || (y < y0 - _l && y < y1 - _l)
        || (x > x0 + _l && x > x1 + _l)
        || (x < x0 - _l && x < x1 - _l)
    ) {
        return false;
    }

    if (x0 !== x1) {
        _a = (y0 - y1) / (x0 - x1);
        _b = (x0 * y1 - x1 * y0) / (x0 - x1);
    }
    else {
        return Math.abs(x - x0) <= _l / 2;
    }
    var tmp = _a * x - y + _b;
    var _s = tmp * tmp / (_a * _a + 1);
    return _s <= _l / 2 * _l / 2;
}

/**
 * 三次贝塞尔曲线描边包含判断
 * @param  {number}  x0
 * @param  {number}  y0
 * @param  {number}  x1
 * @param  {number}  y1
 * @param  {number}  x2
 * @param  {number}  y2
 * @param  {number}  x3
 * @param  {number}  y3
 * @param  {number}  lineWidth
 * @param  {number}  x
 * @param  {number}  y
 * @return {boolean}
 */
function containStroke$2(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    // Quick reject
    if (
        (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l)
        || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l)
        || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l)
        || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)
    ) {
        return false;
    }
    var d = cubicProjectPoint(
        x0, y0, x1, y1, x2, y2, x3, y3,
        x, y, null
    );
    return d <= _l / 2;
}

/**
 * 二次贝塞尔曲线描边包含判断
 * @param  {number}  x0
 * @param  {number}  y0
 * @param  {number}  x1
 * @param  {number}  y1
 * @param  {number}  x2
 * @param  {number}  y2
 * @param  {number}  lineWidth
 * @param  {number}  x
 * @param  {number}  y
 * @return {boolean}
 */
function containStroke$3(x0, y0, x1, y1, x2, y2, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    // Quick reject
    if (
        (y > y0 + _l && y > y1 + _l && y > y2 + _l)
        || (y < y0 - _l && y < y1 - _l && y < y2 - _l)
        || (x > x0 + _l && x > x1 + _l && x > x2 + _l)
        || (x < x0 - _l && x < x1 - _l && x < x2 - _l)
    ) {
        return false;
    }
    var d = quadraticProjectPoint(
        x0, y0, x1, y1, x2, y2,
        x, y, null
    );
    return d <= _l / 2;
}

var PI2$3 = Math.PI * 2;

function normalizeRadian(angle) {
    angle %= PI2$3;
    if (angle < 0) {
        angle += PI2$3;
    }
    return angle;
}

var PI2$2 = Math.PI * 2;

/**
 * 圆弧描边包含判断
 * @param  {number}  cx
 * @param  {number}  cy
 * @param  {number}  r
 * @param  {number}  startAngle
 * @param  {number}  endAngle
 * @param  {boolean}  anticlockwise
 * @param  {number} lineWidth
 * @param  {number}  x
 * @param  {number}  y
 * @return {Boolean}
 */
function containStroke$4(
    cx, cy, r, startAngle, endAngle, anticlockwise,
    lineWidth, x, y
) {

    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;

    x -= cx;
    y -= cy;
    var d = Math.sqrt(x * x + y * y);

    if ((d - _l > r) || (d + _l < r)) {
        return false;
    }
    if (Math.abs(startAngle - endAngle) % PI2$2 < 1e-4) {
        // Is a circle
        return true;
    }
    if (anticlockwise) {
        var tmp = startAngle;
        startAngle = normalizeRadian(endAngle);
        endAngle = normalizeRadian(tmp);
    }
    else {
        startAngle = normalizeRadian(startAngle);
        endAngle = normalizeRadian(endAngle);
    }
    if (startAngle > endAngle) {
        endAngle += PI2$2;
    }

    var angle = Math.atan2(y, x);
    if (angle < 0) {
        angle += PI2$2;
    }
    return (angle >= startAngle && angle <= endAngle)
        || (angle + PI2$2 >= startAngle && angle + PI2$2 <= endAngle);
}

function windingLine(x0, y0, x1, y1, x, y) {
    if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
        return 0;
    }
    // Ignore horizontal line
    if (y1 === y0) {
        return 0;
    }
    var dir = y1 < y0 ? 1 : -1;
    var t = (y - y0) / (y1 - y0);

    // Avoid winding error when intersection point is the connect point of two line of polygon
    if (t === 1 || t === 0) {
        dir = y1 < y0 ? 0.5 : -0.5;
    }

    var x_ = t * (x1 - x0) + x0;

    // If (x, y) on the line, considered as "contain".
    return x_ === x ? Infinity : x_ > x ? dir : 0;
}

var CMD$1 = PathProxy.CMD;
var PI2$1 = Math.PI * 2;

var EPSILON$2 = 1e-4;

function isAroundEqual(a, b) {
    return Math.abs(a - b) < EPSILON$2;
}

// 临时数组
var roots = [-1, -1, -1];
var extrema = [-1, -1];

function swapExtrema() {
    var tmp = extrema[0];
    extrema[0] = extrema[1];
    extrema[1] = tmp;
}

function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) {
    // Quick reject
    if (
        (y > y0 && y > y1 && y > y2 && y > y3)
        || (y < y0 && y < y1 && y < y2 && y < y3)
    ) {
        return 0;
    }
    var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots);
    if (nRoots === 0) {
        return 0;
    }
    else {
        var w = 0;
        var nExtrema = -1;
        var y0_;
        var y1_;
        for (var i = 0; i < nRoots; i++) {
            var t = roots[i];

            // Avoid winding error when intersection point is the connect point of two line of polygon
            var unit = (t === 0 || t === 1) ? 0.5 : 1;

            var x_ = cubicAt(x0, x1, x2, x3, t);
            if (x_ < x) { // Quick reject
                continue;
            }
            if (nExtrema < 0) {
                nExtrema = cubicExtrema(y0, y1, y2, y3, extrema);
                if (extrema[1] < extrema[0] && nExtrema > 1) {
                    swapExtrema();
                }
                y0_ = cubicAt(y0, y1, y2, y3, extrema[0]);
                if (nExtrema > 1) {
                    y1_ = cubicAt(y0, y1, y2, y3, extrema[1]);
                }
            }
            if (nExtrema === 2) {
                // 分成三段单调函数
                if (t < extrema[0]) {
                    w += y0_ < y0 ? unit : -unit;
                }
                else if (t < extrema[1]) {
                    w += y1_ < y0_ ? unit : -unit;
                }
                else {
                    w += y3 < y1_ ? unit : -unit;
                }
            }
            else {
                // 分成两段单调函数
                if (t < extrema[0]) {
                    w += y0_ < y0 ? unit : -unit;
                }
                else {
                    w += y3 < y0_ ? unit : -unit;
                }
            }
        }
        return w;
    }
}

function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) {
    // Quick reject
    if (
        (y > y0 && y > y1 && y > y2)
        || (y < y0 && y < y1 && y < y2)
    ) {
        return 0;
    }
    var nRoots = quadraticRootAt(y0, y1, y2, y, roots);
    if (nRoots === 0) {
        return 0;
    }
    else {
        var t = quadraticExtremum(y0, y1, y2);
        if (t >= 0 && t <= 1) {
            var w = 0;
            var y_ = quadraticAt(y0, y1, y2, t);
            for (var i = 0; i < nRoots; i++) {
                // Remove one endpoint.
                var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1;

                var x_ = quadraticAt(x0, x1, x2, roots[i]);
                if (x_ < x) {   // Quick reject
                    continue;
                }
                if (roots[i] < t) {
                    w += y_ < y0 ? unit : -unit;
                }
                else {
                    w += y2 < y_ ? unit : -unit;
                }
            }
            return w;
        }
        else {
            // Remove one endpoint.
            var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1;

            var x_ = quadraticAt(x0, x1, x2, roots[0]);
            if (x_ < x) {   // Quick reject
                return 0;
            }
            return y2 < y0 ? unit : -unit;
        }
    }
}

// TODO
// Arc 旋转
function windingArc(
    cx, cy, r, startAngle, endAngle, anticlockwise, x, y
) {
    y -= cy;
    if (y > r || y < -r) {
        return 0;
    }
    var tmp = Math.sqrt(r * r - y * y);
    roots[0] = -tmp;
    roots[1] = tmp;

    var diff = Math.abs(startAngle - endAngle);
    if (diff < 1e-4) {
        return 0;
    }
    if (diff % PI2$1 < 1e-4) {
        // Is a circle
        startAngle = 0;
        endAngle = PI2$1;
        var dir = anticlockwise ? 1 : -1;
        if (x >= roots[0] + cx && x <= roots[1] + cx) {
            return dir;
        }
        else {
            return 0;
        }
    }

    if (anticlockwise) {
        var tmp = startAngle;
        startAngle = normalizeRadian(endAngle);
        endAngle = normalizeRadian(tmp);
    }
    else {
        startAngle = normalizeRadian(startAngle);
        endAngle = normalizeRadian(endAngle);
    }
    if (startAngle > endAngle) {
        endAngle += PI2$1;
    }

    var w = 0;
    for (var i = 0; i < 2; i++) {
        var x_ = roots[i];
        if (x_ + cx > x) {
            var angle = Math.atan2(y, x_);
            var dir = anticlockwise ? 1 : -1;
            if (angle < 0) {
                angle = PI2$1 + angle;
            }
            if (
                (angle >= startAngle && angle <= endAngle)
                || (angle + PI2$1 >= startAngle && angle + PI2$1 <= endAngle)
            ) {
                if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
                    dir = -dir;
                }
                w += dir;
            }
        }
    }
    return w;
}

function containPath(data, lineWidth, isStroke, x, y) {
    var w = 0;
    var xi = 0;
    var yi = 0;
    var x0 = 0;
    var y0 = 0;

    for (var i = 0; i < data.length;) {
        var cmd = data[i++];
        // Begin a new subpath
        if (cmd === CMD$1.M && i > 1) {
            // Close previous subpath
            if (!isStroke) {
                w += windingLine(xi, yi, x0, y0, x, y);
            }
            // 如果被任何一个 subpath 包含
            // if (w !== 0) {
            //     return true;
            // }
        }

        if (i === 1) {
            // 如果第一个命令是 L, C, Q
            // 则 previous point 同绘制命令的第一个 point
            //
            // 第一个命令为 Arc 的情况下会在后面特殊处理
            xi = data[i];
            yi = data[i + 1];

            x0 = xi;
            y0 = yi;
        }

        switch (cmd) {
            case CMD$1.M:
                // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点
                // 在 closePath 的时候使用
                x0 = data[i++];
                y0 = data[i++];
                xi = x0;
                yi = y0;
                break;
            case CMD$1.L:
                if (isStroke) {
                    if (containStroke$1(xi, yi, data[i], data[i + 1], lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    // NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN
                    w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.C:
                if (isStroke) {
                    if (containStroke$2(xi, yi,
                        data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
                        lineWidth, x, y
                    )) {
                        return true;
                    }
                }
                else {
                    w += windingCubic(
                        xi, yi,
                        data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
                        x, y
                    ) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.Q:
                if (isStroke) {
                    if (containStroke$3(xi, yi,
                        data[i++], data[i++], data[i], data[i + 1],
                        lineWidth, x, y
                    )) {
                        return true;
                    }
                }
                else {
                    w += windingQuadratic(
                        xi, yi,
                        data[i++], data[i++], data[i], data[i + 1],
                        x, y
                    ) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.A:
                // TODO Arc 判断的开销比较大
                var cx = data[i++];
                var cy = data[i++];
                var rx = data[i++];
                var ry = data[i++];
                var theta = data[i++];
                var dTheta = data[i++];
                // TODO Arc 旋转
                i += 1;
                var anticlockwise = 1 - data[i++];
                var x1 = Math.cos(theta) * rx + cx;
                var y1 = Math.sin(theta) * ry + cy;
                // 不是直接使用 arc 命令
                if (i > 1) {
                    w += windingLine(xi, yi, x1, y1, x, y);
                }
                else {
                    // 第一个命令起点还未定义
                    x0 = x1;
                    y0 = y1;
                }
                // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放
                var _x = (x - cx) * ry / rx + cx;
                if (isStroke) {
                    if (containStroke$4(
                        cx, cy, ry, theta, theta + dTheta, anticlockwise,
                        lineWidth, _x, y
                    )) {
                        return true;
                    }
                }
                else {
                    w += windingArc(
                        cx, cy, ry, theta, theta + dTheta, anticlockwise,
                        _x, y
                    );
                }
                xi = Math.cos(theta + dTheta) * rx + cx;
                yi = Math.sin(theta + dTheta) * ry + cy;
                break;
            case CMD$1.R:
                x0 = xi = data[i++];
                y0 = yi = data[i++];
                var width = data[i++];
                var height = data[i++];
                var x1 = x0 + width;
                var y1 = y0 + height;
                if (isStroke) {
                    if (containStroke$1(x0, y0, x1, y0, lineWidth, x, y)
                        || containStroke$1(x1, y0, x1, y1, lineWidth, x, y)
                        || containStroke$1(x1, y1, x0, y1, lineWidth, x, y)
                        || containStroke$1(x0, y1, x0, y0, lineWidth, x, y)
                    ) {
                        return true;
                    }
                }
                else {
                    // FIXME Clockwise ?
                    w += windingLine(x1, y0, x1, y1, x, y);
                    w += windingLine(x0, y1, x0, y0, x, y);
                }
                break;
            case CMD$1.Z:
                if (isStroke) {
                    if (containStroke$1(
                        xi, yi, x0, y0, lineWidth, x, y
                    )) {
                        return true;
                    }
                }
                else {
                    // Close a subpath
                    w += windingLine(xi, yi, x0, y0, x, y);
                    // 如果被任何一个 subpath 包含
                    // FIXME subpaths may overlap
                    // if (w !== 0) {
                    //     return true;
                    // }
                }
                xi = x0;
                yi = y0;
                break;
        }
    }
    if (!isStroke && !isAroundEqual(yi, y0)) {
        w += windingLine(xi, yi, x0, y0, x, y) || 0;
    }
    return w !== 0;
}

function contain(pathData, x, y) {
    return containPath(pathData, 0, false, x, y);
}

function containStroke(pathData, lineWidth, x, y) {
    return containPath(pathData, lineWidth, true, x, y);
}

var getCanvasPattern = Pattern.prototype.getCanvasPattern;

var abs = Math.abs;

var pathProxyForDraw = new PathProxy(true);
/**
 * @alias module:zrender/graphic/Path
 * @extends module:zrender/graphic/Displayable
 * @constructor
 * @param {Object} opts
 */
function Path(opts) {
    Displayable.call(this, opts);

    /**
     * @type {module:zrender/core/PathProxy}
     * @readOnly
     */
    this.path = null;
}

Path.prototype = {

    constructor: Path,

    type: 'path',

    __dirtyPath: true,

    strokeContainThreshold: 5,

    // This item default to be false. But in map series in echarts,
    // in order to improve performance, it should be set to true,
    // so the shorty segment won't draw.
    segmentIgnoreThreshold: 0,

    /**
     * See `module:zrender/src/graphic/helper/subPixelOptimize`.
     * @type {boolean}
     */
    subPixelOptimize: false,

    brush: function (ctx, prevEl) {
        var style = this.style;
        var path = this.path || pathProxyForDraw;
        var hasStroke = style.hasStroke();
        var hasFill = style.hasFill();
        var fill = style.fill;
        var stroke = style.stroke;
        var hasFillGradient = hasFill && !!(fill.colorStops);
        var hasStrokeGradient = hasStroke && !!(stroke.colorStops);
        var hasFillPattern = hasFill && !!(fill.image);
        var hasStrokePattern = hasStroke && !!(stroke.image);

        style.bind(ctx, this, prevEl);
        this.setTransform(ctx);

        if (this.__dirty) {
            var rect;
            // Update gradient because bounding rect may changed
            if (hasFillGradient) {
                rect = rect || this.getBoundingRect();
                this._fillGradient = style.getGradient(ctx, fill, rect);
            }
            if (hasStrokeGradient) {
                rect = rect || this.getBoundingRect();
                this._strokeGradient = style.getGradient(ctx, stroke, rect);
            }
        }
        // Use the gradient or pattern
        if (hasFillGradient) {
            // PENDING If may have affect the state
            ctx.fillStyle = this._fillGradient;
        }
        else if (hasFillPattern) {
            ctx.fillStyle = getCanvasPattern.call(fill, ctx);
        }
        if (hasStrokeGradient) {
            ctx.strokeStyle = this._strokeGradient;
        }
        else if (hasStrokePattern) {
            ctx.strokeStyle = getCanvasPattern.call(stroke, ctx);
        }

        var lineDash = style.lineDash;
        var lineDashOffset = style.lineDashOffset;

        var ctxLineDash = !!ctx.setLineDash;

        // Update path sx, sy
        var scale = this.getGlobalScale();
        path.setScale(scale[0], scale[1], this.segmentIgnoreThreshold);

        // Proxy context
        // Rebuild path in following 2 cases
        // 1. Path is dirty
        // 2. Path needs javascript implemented lineDash stroking.
        //    In this case, lineDash information will not be saved in PathProxy
        if (this.__dirtyPath
            || (lineDash && !ctxLineDash && hasStroke)
        ) {
            path.beginPath(ctx);

            // Setting line dash before build path
            if (lineDash && !ctxLineDash) {
                path.setLineDash(lineDash);
                path.setLineDashOffset(lineDashOffset);
            }

            this.buildPath(path, this.shape, false);

            // Clear path dirty flag
            if (this.path) {
                this.__dirtyPath = false;
            }
        }
        else {
            // Replay path building
            ctx.beginPath();
            this.path.rebuildPath(ctx);
        }

        if (hasFill) {
            if (style.fillOpacity != null) {
                var originalGlobalAlpha = ctx.globalAlpha;
                ctx.globalAlpha = style.fillOpacity * style.opacity;
                path.fill(ctx);
                ctx.globalAlpha = originalGlobalAlpha;
            }
            else {
                path.fill(ctx);
            }
        }

        if (lineDash && ctxLineDash) {
            ctx.setLineDash(lineDash);
            ctx.lineDashOffset = lineDashOffset;
        }

        if (hasStroke) {
            if (style.strokeOpacity != null) {
                var originalGlobalAlpha = ctx.globalAlpha;
                ctx.globalAlpha = style.strokeOpacity * style.opacity;
                path.stroke(ctx);
                ctx.globalAlpha = originalGlobalAlpha;
            }
            else {
                path.stroke(ctx);
            }
        }

        if (lineDash && ctxLineDash) {
            // PENDING
            // Remove lineDash
            ctx.setLineDash([]);
        }

        // Draw rect text
        if (style.text != null) {
            // Only restore transform when needs draw text.
            this.restoreTransform(ctx);
            this.drawRectText(ctx, this.getBoundingRect());
        }
    },

    // When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath
    // Like in circle
    buildPath: function (ctx, shapeCfg, inBundle) {},

    createPathProxy: function () {
        this.path = new PathProxy();
    },

    getBoundingRect: function () {
        var rect = this._rect;
        var style = this.style;
        var needsUpdateRect = !rect;
        if (needsUpdateRect) {
            var path = this.path;
            if (!path) {
                // Create path on demand.
                path = this.path = new PathProxy();
            }
            if (this.__dirtyPath) {
                path.beginPath();
                this.buildPath(path, this.shape, false);
            }
            rect = path.getBoundingRect();
        }
        this._rect = rect;

        if (style.hasStroke()) {
            // Needs update rect with stroke lineWidth when
            // 1. Element changes scale or lineWidth
            // 2. Shape is changed
            var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone());
            if (this.__dirty || needsUpdateRect) {
                rectWithStroke.copy(rect);
                // FIXME Must after updateTransform
                var w = style.lineWidth;
                // PENDING, Min line width is needed when line is horizontal or vertical
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;

                // Only add extra hover lineWidth when there are no fill
                if (!style.hasFill()) {
                    w = Math.max(w, this.strokeContainThreshold || 4);
                }
                // Consider line width
                // Line scale can't be 0;
                if (lineScale > 1e-10) {
                    rectWithStroke.width += w / lineScale;
                    rectWithStroke.height += w / lineScale;
                    rectWithStroke.x -= w / lineScale / 2;
                    rectWithStroke.y -= w / lineScale / 2;
                }
            }

            // Return rect with stroke
            return rectWithStroke;
        }

        return rect;
    },

    contain: function (x, y) {
        var localPos = this.transformCoordToLocal(x, y);
        var rect = this.getBoundingRect();
        var style = this.style;
        x = localPos[0];
        y = localPos[1];

        if (rect.contain(x, y)) {
            var pathData = this.path.data;
            if (style.hasStroke()) {
                var lineWidth = style.lineWidth;
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
                // Line scale can't be 0;
                if (lineScale > 1e-10) {
                    // Only add extra hover lineWidth when there are no fill
                    if (!style.hasFill()) {
                        lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
                    }
                    if (containStroke(
                        pathData, lineWidth / lineScale, x, y
                    )) {
                        return true;
                    }
                }
            }
            if (style.hasFill()) {
                return contain(pathData, x, y);
            }
        }
        return false;
    },

    /**
     * @param  {boolean} dirtyPath
     */
    dirty: function (dirtyPath) {
        if (dirtyPath == null) {
            dirtyPath = true;
        }
        // Only mark dirty, not mark clean
        if (dirtyPath) {
            this.__dirtyPath = dirtyPath;
            this._rect = null;
        }

        this.__dirty = this.__dirtyText = true;

        this.__zr && this.__zr.refresh();

        // Used as a clipping path
        if (this.__clipTarget) {
            this.__clipTarget.dirty();
        }
    },

    /**
     * Alias for animate('shape')
     * @param {boolean} loop
     */
    animateShape: function (loop) {
        return this.animate('shape', loop);
    },

    // Overwrite attrKV
    attrKV: function (key, value) {
        // FIXME
        if (key === 'shape') {
            this.setShape(value);
            this.__dirtyPath = true;
            this._rect = null;
        }
        else {
            Displayable.prototype.attrKV.call(this, key, value);
        }
    },

    /**
     * @param {Object|string} key
     * @param {*} value
     */
    setShape: function (key, value) {
        var shape = this.shape;
        // Path from string may not have shape
        if (shape) {
            if (isObject$1(key)) {
                for (var name in key) {
                    if (key.hasOwnProperty(name)) {
                        shape[name] = key[name];
                    }
                }
            }
            else {
                shape[key] = value;
            }
            this.dirty(true);
        }
        return this;
    },

    getLineScale: function () {
        var m = this.transform;
        // Get the line scale.
        // Determinant of `m` means how much the area is enlarged by the
        // transformation. So its square root can be used as a scale factor
        // for width.
        return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10
            ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1]))
            : 1;
    }
};

/**
 * 扩展一个 Path element, 比如星形，圆等。
 * Extend a path element
 * @param {Object} props
 * @param {string} props.type Path type
 * @param {Function} props.init Initialize
 * @param {Function} props.buildPath Overwrite buildPath method
 * @param {Object} [props.style] Extended default style config
 * @param {Object} [props.shape] Extended default shape config
 */
Path.extend = function (defaults$$1) {
    var Sub = function (opts) {
        Path.call(this, opts);

        if (defaults$$1.style) {
            // Extend default style
            this.style.extendFrom(defaults$$1.style, false);
        }

        // Extend default shape
        var defaultShape = defaults$$1.shape;
        if (defaultShape) {
            this.shape = this.shape || {};
            var thisShape = this.shape;
            for (var name in defaultShape) {
                if (
                    !thisShape.hasOwnProperty(name)
                    && defaultShape.hasOwnProperty(name)
                ) {
                    thisShape[name] = defaultShape[name];
                }
            }
        }

        defaults$$1.init && defaults$$1.init.call(this, opts);
    };

    inherits(Sub, Path);

    // FIXME 不能 extend position, rotation 等引用对象
    for (var name in defaults$$1) {
        // Extending prototype values and methods
        if (name !== 'style' && name !== 'shape') {
            Sub.prototype[name] = defaults$$1[name];
        }
    }

    return Sub;
};

inherits(Path, Displayable);

var CMD$2 = PathProxy.CMD;

var points = [[], [], []];
var mathSqrt$3 = Math.sqrt;
var mathAtan2 = Math.atan2;

var transformPath = function (path, m) {
    var data = path.data;
    var cmd;
    var nPoint;
    var i;
    var j;
    var k;
    var p;

    var M = CMD$2.M;
    var C = CMD$2.C;
    var L = CMD$2.L;
    var R = CMD$2.R;
    var A = CMD$2.A;
    var Q = CMD$2.Q;

    for (i = 0, j = 0; i < data.length;) {
        cmd = data[i++];
        j = i;
        nPoint = 0;

        switch (cmd) {
            case M:
                nPoint = 1;
                break;
            case L:
                nPoint = 1;
                break;
            case C:
                nPoint = 3;
                break;
            case Q:
                nPoint = 2;
                break;
            case A:
                var x = m[4];
                var y = m[5];
                var sx = mathSqrt$3(m[0] * m[0] + m[1] * m[1]);
                var sy = mathSqrt$3(m[2] * m[2] + m[3] * m[3]);
                var angle = mathAtan2(-m[1] / sy, m[0] / sx);
                // cx
                data[i] *= sx;
                data[i++] += x;
                // cy
                data[i] *= sy;
                data[i++] += y;
                // Scale rx and ry
                // FIXME Assume psi is 0 here
                data[i++] *= sx;
                data[i++] *= sy;

                // Start angle
                data[i++] += angle;
                // end angle
                data[i++] += angle;
                // FIXME psi
                i += 2;
                j = i;
                break;
            case R:
                // x0, y0
                p[0] = data[i++];
                p[1] = data[i++];
                applyTransform(p, p, m);
                data[j++] = p[0];
                data[j++] = p[1];
                // x1, y1
                p[0] += data[i++];
                p[1] += data[i++];
                applyTransform(p, p, m);
                data[j++] = p[0];
                data[j++] = p[1];
        }

        for (k = 0; k < nPoint; k++) {
            var p = points[k];
            p[0] = data[i++];
            p[1] = data[i++];

            applyTransform(p, p, m);
            // Write back
            data[j++] = p[0];
            data[j++] = p[1];
        }
    }
};

// command chars
// var cc = [
//     'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',
//     'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'
// ];

var mathSqrt = Math.sqrt;
var mathSin = Math.sin;
var mathCos = Math.cos;
var PI = Math.PI;

var vMag = function (v) {
    return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
};
var vRatio = function (u, v) {
    return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
};
var vAngle = function (u, v) {
    return (u[0] * v[1] < u[1] * v[0] ? -1 : 1)
            * Math.acos(vRatio(u, v));
};

function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
    var psi = psiDeg * (PI / 180.0);
    var xp = mathCos(psi) * (x1 - x2) / 2.0
                + mathSin(psi) * (y1 - y2) / 2.0;
    var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0
                + mathCos(psi) * (y1 - y2) / 2.0;

    var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);

    if (lambda > 1) {
        rx *= mathSqrt(lambda);
        ry *= mathSqrt(lambda);
    }

    var f = (fa === fs ? -1 : 1)
        * mathSqrt((((rx * rx) * (ry * ry))
                - ((rx * rx) * (yp * yp))
                - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp)
                + (ry * ry) * (xp * xp))
            ) || 0;

    var cxp = f * rx * yp / ry;
    var cyp = f * -ry * xp / rx;

    var cx = (x1 + x2) / 2.0
                + mathCos(psi) * cxp
                - mathSin(psi) * cyp;
    var cy = (y1 + y2) / 2.0
            + mathSin(psi) * cxp
            + mathCos(psi) * cyp;

    var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]);
    var u = [ (xp - cxp) / rx, (yp - cyp) / ry ];
    var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ];
    var dTheta = vAngle(u, v);

    if (vRatio(u, v) <= -1) {
        dTheta = PI;
    }
    if (vRatio(u, v) >= 1) {
        dTheta = 0;
    }
    if (fs === 0 && dTheta > 0) {
        dTheta = dTheta - 2 * PI;
    }
    if (fs === 1 && dTheta < 0) {
        dTheta = dTheta + 2 * PI;
    }

    path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
}


var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;
// Consider case:
// (1) delimiter can be comma or space, where continuous commas
// or spaces should be seen as one comma.
// (2) value can be like:
// '2e-4', 'l.5.9' (ignore 0), 'M-10-10', 'l-2.43e-1,34.9983',
// 'l-.5E1,54', '121-23-44-11' (no delimiter)
var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
// var valueSplitReg = /[\s,]+/;

function createPathProxyFromString(data) {
    if (!data) {
        return new PathProxy();
    }

    // var data = data.replace(/-/g, ' -')
    //     .replace(/  /g, ' ')
    //     .replace(/ /g, ',')
    //     .replace(/,,/g, ',');

    // var n;
    // create pipes so that we can split the data
    // for (n = 0; n < cc.length; n++) {
    //     cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);
    // }

    // data = data.replace(/-/g, ',-');

    // create array
    // var arr = cs.split('|');
    // init context point
    var cpx = 0;
    var cpy = 0;
    var subpathX = cpx;
    var subpathY = cpy;
    var prevCmd;

    var path = new PathProxy();
    var CMD = PathProxy.CMD;

    // commandReg.lastIndex = 0;
    // var cmdResult;
    // while ((cmdResult = commandReg.exec(data)) != null) {
    //     var cmdStr = cmdResult[1];
    //     var cmdContent = cmdResult[2];

    var cmdList = data.match(commandReg);
    for (var l = 0; l < cmdList.length; l++) {
        var cmdText = cmdList[l];
        var cmdStr = cmdText.charAt(0);

        var cmd;

        // String#split is faster a little bit than String#replace or RegExp#exec.
        // var p = cmdContent.split(valueSplitReg);
        // var pLen = 0;
        // for (var i = 0; i < p.length; i++) {
        //     // '' and other invalid str => NaN
        //     var val = parseFloat(p[i]);
        //     !isNaN(val) && (p[pLen++] = val);
        // }

        var p = cmdText.match(numberReg) || [];
        var pLen = p.length;
        for (var i = 0; i < pLen; i++) {
            p[i] = parseFloat(p[i]);
        }

        var off = 0;
        while (off < pLen) {
            var ctlPtx;
            var ctlPty;

            var rx;
            var ry;
            var psi;
            var fa;
            var fs;

            var x1 = cpx;
            var y1 = cpy;

            // convert l, H, h, V, and v to L
            switch (cmdStr) {
                case 'l':
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'L':
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'm':
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.M;
                    path.addData(cmd, cpx, cpy);
                    subpathX = cpx;
                    subpathY = cpy;
                    cmdStr = 'l';
                    break;
                case 'M':
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.M;
                    path.addData(cmd, cpx, cpy);
                    subpathX = cpx;
                    subpathY = cpy;
                    cmdStr = 'L';
                    break;
                case 'h':
                    cpx += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'H':
                    cpx = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'v':
                    cpy += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'V':
                    cpy = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'C':
                    cmd = CMD.C;
                    path.addData(
                        cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]
                    );
                    cpx = p[off - 2];
                    cpy = p[off - 1];
                    break;
                case 'c':
                    cmd = CMD.C;
                    path.addData(
                        cmd,
                        p[off++] + cpx, p[off++] + cpy,
                        p[off++] + cpx, p[off++] + cpy,
                        p[off++] + cpx, p[off++] + cpy
                    );
                    cpx += p[off - 2];
                    cpy += p[off - 1];
                    break;
                case 'S':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    var len = path.len();
                    var pathData = path.data;
                    if (prevCmd === CMD.C) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cmd = CMD.C;
                    x1 = p[off++];
                    y1 = p[off++];
                    cpx = p[off++];
                    cpy = p[off++];
                    path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
                    break;
                case 's':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    var len = path.len();
                    var pathData = path.data;
                    if (prevCmd === CMD.C) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cmd = CMD.C;
                    x1 = cpx + p[off++];
                    y1 = cpy + p[off++];
                    cpx += p[off++];
                    cpy += p[off++];
                    path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
                    break;
                case 'Q':
                    x1 = p[off++];
                    y1 = p[off++];
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, x1, y1, cpx, cpy);
                    break;
                case 'q':
                    x1 = p[off++] + cpx;
                    y1 = p[off++] + cpy;
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, x1, y1, cpx, cpy);
                    break;
                case 'T':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    var len = path.len();
                    var pathData = path.data;
                    if (prevCmd === CMD.Q) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
                    break;
                case 't':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    var len = path.len();
                    var pathData = path.data;
                    if (prevCmd === CMD.Q) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
                    break;
                case 'A':
                    rx = p[off++];
                    ry = p[off++];
                    psi = p[off++];
                    fa = p[off++];
                    fs = p[off++];

                    x1 = cpx, y1 = cpy;
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.A;
                    processArc(
                        x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
                    );
                    break;
                case 'a':
                    rx = p[off++];
                    ry = p[off++];
                    psi = p[off++];
                    fa = p[off++];
                    fs = p[off++];

                    x1 = cpx, y1 = cpy;
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.A;
                    processArc(
                        x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
                    );
                    break;
            }
        }

        if (cmdStr === 'z' || cmdStr === 'Z') {
            cmd = CMD.Z;
            path.addData(cmd);
            // z may be in the middle of the path.
            cpx = subpathX;
            cpy = subpathY;
        }

        prevCmd = cmd;
    }

    path.toStatic();

    return path;
}

// TODO Optimize double memory cost problem
function createPathOptions(str, opts) {
    var pathProxy = createPathProxyFromString(str);
    opts = opts || {};
    opts.buildPath = function (path) {
        if (path.setData) {
            path.setData(pathProxy.data);
            // Svg and vml renderer don't have context
            var ctx = path.getContext();
            if (ctx) {
                path.rebuildPath(ctx);
            }
        }
        else {
            var ctx = path;
            pathProxy.rebuildPath(ctx);
        }
    };

    opts.applyTransform = function (m) {
        transformPath(pathProxy, m);
        this.dirty(true);
    };

    return opts;
}

/**
 * Create a Path object from path string data
 * http://www.w3.org/TR/SVG/paths.html#PathData
 * @param  {Object} opts Other options
 */
function createFromString(str, opts) {
    return new Path(createPathOptions(str, opts));
}

/**
 * Create a Path class from path string data
 * @param  {string} str
 * @param  {Object} opts Other options
 */
function extendFromString(str, opts) {
    return Path.extend(createPathOptions(str, opts));
}

/**
 * Merge multiple paths
 */
// TODO Apply transform
// TODO stroke dash
// TODO Optimize double memory cost problem
function mergePath$1(pathEls, opts) {
    var pathList = [];
    var len = pathEls.length;
    for (var i = 0; i < len; i++) {
        var pathEl = pathEls[i];
        if (!pathEl.path) {
            pathEl.createPathProxy();
        }
        if (pathEl.__dirtyPath) {
            pathEl.buildPath(pathEl.path, pathEl.shape, true);
        }
        pathList.push(pathEl.path);
    }

    var pathBundle = new Path(opts);
    // Need path proxy.
    pathBundle.createPathProxy();
    pathBundle.buildPath = function (path) {
        path.appendPath(pathList);
        // Svg and vml renderer don't have context
        var ctx = path.getContext();
        if (ctx) {
            path.rebuildPath(ctx);
        }
    };

    return pathBundle;
}

/**
 * @alias zrender/graphic/Text
 * @extends module:zrender/graphic/Displayable
 * @constructor
 * @param {Object} opts
 */
var Text = function (opts) { // jshint ignore:line
    Displayable.call(this, opts);
};

Text.prototype = {

    constructor: Text,

    type: 'text',

    brush: function (ctx, prevEl) {
        var style = this.style;

        // Optimize, avoid normalize every time.
        this.__dirty && normalizeTextStyle(style, true);

        // Use props with prefix 'text'.
        style.fill = style.stroke = style.shadowBlur = style.shadowColor =
            style.shadowOffsetX = style.shadowOffsetY = null;

        var text = style.text;
        // Convert to string
        text != null && (text += '');

        // Do not apply style.bind in Text node. Because the real bind job
        // is in textHelper.renderText, and performance of text render should
        // be considered.
        // style.bind(ctx, this, prevEl);

        if (!needDrawText(text, style)) {
            // The current el.style is not applied
            // and should not be used as cache.
            ctx.__attrCachedBy = ContextCachedBy.NONE;
            return;
        }

        this.setTransform(ctx);

        renderText(this, ctx, text, style, null, prevEl);

        this.restoreTransform(ctx);
    },

    getBoundingRect: function () {
        var style = this.style;

        // Optimize, avoid normalize every time.
        this.__dirty && normalizeTextStyle(style, true);

        if (!this._rect) {
            var text = style.text;
            text != null ? (text += '') : (text = '');

            var rect = getBoundingRect(
                style.text + '',
                style.font,
                style.textAlign,
                style.textVerticalAlign,
                style.textPadding,
                style.textLineHeight,
                style.rich
            );

            rect.x += style.x || 0;
            rect.y += style.y || 0;

            if (getStroke(style.textStroke, style.textStrokeWidth)) {
                var w = style.textStrokeWidth;
                rect.x -= w / 2;
                rect.y -= w / 2;
                rect.width += w;
                rect.height += w;
            }

            this._rect = rect;
        }

        return this._rect;
    }
};

inherits(Text, Displayable);

/**
 * 圆形
 * @module zrender/shape/Circle
 */

var Circle = Path.extend({

    type: 'circle',

    shape: {
        cx: 0,
        cy: 0,
        r: 0
    },


    buildPath: function (ctx, shape, inBundle) {
        // Better stroking in ShapeBundle
        // Always do it may have performence issue ( fill may be 2x more cost)
        if (inBundle) {
            ctx.moveTo(shape.cx + shape.r, shape.cy);
        }
        // else {
        //     if (ctx.allocate && !ctx.data.length) {
        //         ctx.allocate(ctx.CMD_MEM_SIZE.A);
        //     }
        // }
        // Better stroking in ShapeBundle
        // ctx.moveTo(shape.cx + shape.r, shape.cy);
        ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true);
    }
});

// Fix weird bug in some version of IE11 (like 11.0.9600.178**),
// where exception "unexpected call to method or property access"
// might be thrown when calling ctx.fill or ctx.stroke after a path
// whose area size is zero is drawn and ctx.clip() is called and
// shadowBlur is set. See #4572, #3112, #5777.
// (e.g.,
//  ctx.moveTo(10, 10);
//  ctx.lineTo(20, 10);
//  ctx.closePath();
//  ctx.clip();
//  ctx.shadowBlur = 10;
//  ...
//  ctx.fill();
// )

var shadowTemp = [
    ['shadowBlur', 0],
    ['shadowColor', '#000'],
    ['shadowOffsetX', 0],
    ['shadowOffsetY', 0]
];

var fixClipWithShadow = function (orignalBrush) {

    // version string can be: '11.0'
    return (env$1.browser.ie && env$1.browser.version >= 11)

        ? function () {
            var clipPaths = this.__clipPaths;
            var style = this.style;
            var modified;

            if (clipPaths) {
                for (var i = 0; i < clipPaths.length; i++) {
                    var clipPath = clipPaths[i];
                    var shape = clipPath && clipPath.shape;
                    var type = clipPath && clipPath.type;

                    if (shape && (
                        (type === 'sector' && shape.startAngle === shape.endAngle)
                        || (type === 'rect' && (!shape.width || !shape.height))
                    )) {
                        for (var j = 0; j < shadowTemp.length; j++) {
                            // It is save to put shadowTemp static, because shadowTemp
                            // will be all modified each item brush called.
                            shadowTemp[j][2] = style[shadowTemp[j][0]];
                            style[shadowTemp[j][0]] = shadowTemp[j][1];
                        }
                        modified = true;
                        break;
                    }
                }
            }

            orignalBrush.apply(this, arguments);

            if (modified) {
                for (var j = 0; j < shadowTemp.length; j++) {
                    style[shadowTemp[j][0]] = shadowTemp[j][2];
                }
            }
        }

        : orignalBrush;
};

/**
 * 扇形
 * @module zrender/graphic/shape/Sector
 */

var Sector = Path.extend({

    type: 'sector',

    shape: {

        cx: 0,

        cy: 0,

        r0: 0,

        r: 0,

        startAngle: 0,

        endAngle: Math.PI * 2,

        clockwise: true
    },

    brush: fixClipWithShadow(Path.prototype.brush),

    buildPath: function (ctx, shape) {

        var x = shape.cx;
        var y = shape.cy;
        var r0 = Math.max(shape.r0 || 0, 0);
        var r = Math.max(shape.r, 0);
        var startAngle = shape.startAngle;
        var endAngle = shape.endAngle;
        var clockwise = shape.clockwise;

        var unitX = Math.cos(startAngle);
        var unitY = Math.sin(startAngle);

        ctx.moveTo(unitX * r0 + x, unitY * r0 + y);

        ctx.lineTo(unitX * r + x, unitY * r + y);

        ctx.arc(x, y, r, startAngle, endAngle, !clockwise);

        ctx.lineTo(
            Math.cos(endAngle) * r0 + x,
            Math.sin(endAngle) * r0 + y
        );

        if (r0 !== 0) {
            ctx.arc(x, y, r0, endAngle, startAngle, clockwise);
        }

        ctx.closePath();
    }
});

/**
 * 圆环
 * @module zrender/graphic/shape/Ring
 */

var Ring = Path.extend({

    type: 'ring',

    shape: {
        cx: 0,
        cy: 0,
        r: 0,
        r0: 0
    },

    buildPath: function (ctx, shape) {
        var x = shape.cx;
        var y = shape.cy;
        var PI2 = Math.PI * 2;
        ctx.moveTo(x + shape.r, y);
        ctx.arc(x, y, shape.r, 0, PI2, false);
        ctx.moveTo(x + shape.r0, y);
        ctx.arc(x, y, shape.r0, 0, PI2, true);
    }
});

/**
 * Catmull-Rom spline 插值折线
 * @module zrender/shape/util/smoothSpline
 * @author pissang (https://www.github.com/pissang)
 *         Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *         errorrik (errorrik@gmail.com)
 */

/**
 * @inner
 */
function interpolate(p0, p1, p2, p3, t, t2, t3) {
    var v0 = (p2 - p0) * 0.5;
    var v1 = (p3 - p1) * 0.5;
    return (2 * (p1 - p2) + v0 + v1) * t3
            + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
            + v0 * t + p1;
}

/**
 * @alias module:zrender/shape/util/smoothSpline
 * @param {Array} points 线段顶点数组
 * @param {boolean} isLoop
 * @return {Array}
 */
var smoothSpline = function (points, isLoop) {
    var len$$1 = points.length;
    var ret = [];

    var distance$$1 = 0;
    for (var i = 1; i < len$$1; i++) {
        distance$$1 += distance(points[i - 1], points[i]);
    }

    var segs = distance$$1 / 2;
    segs = segs < len$$1 ? len$$1 : segs;
    for (var i = 0; i < segs; i++) {
        var pos = i / (segs - 1) * (isLoop ? len$$1 : len$$1 - 1);
        var idx = Math.floor(pos);

        var w = pos - idx;

        var p0;
        var p1 = points[idx % len$$1];
        var p2;
        var p3;
        if (!isLoop) {
            p0 = points[idx === 0 ? idx : idx - 1];
            p2 = points[idx > len$$1 - 2 ? len$$1 - 1 : idx + 1];
            p3 = points[idx > len$$1 - 3 ? len$$1 - 1 : idx + 2];
        }
        else {
            p0 = points[(idx - 1 + len$$1) % len$$1];
            p2 = points[(idx + 1) % len$$1];
            p3 = points[(idx + 2) % len$$1];
        }

        var w2 = w * w;
        var w3 = w * w2;

        ret.push([
            interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3),
            interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3)
        ]);
    }
    return ret;
};

/**
 * 贝塞尔平滑曲线
 * @module zrender/shape/util/smoothBezier
 * @author pissang (https://www.github.com/pissang)
 *         Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *         errorrik (errorrik@gmail.com)
 */

/**
 * 贝塞尔平滑曲线
 * @alias module:zrender/shape/util/smoothBezier
 * @param {Array} points 线段顶点数组
 * @param {number} smooth 平滑等级, 0-1
 * @param {boolean} isLoop
 * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内
 *                           比如 [[0, 0], [100, 100]], 这个包围盒会与
 *                           整个折线的包围盒做一个并集用来约束控制点。
 * @param {Array} 计算出来的控制点数组
 */
var smoothBezier = function (points, smooth, isLoop, constraint) {
    var cps = [];

    var v = [];
    var v1 = [];
    var v2 = [];
    var prevPoint;
    var nextPoint;

    var min$$1;
    var max$$1;
    if (constraint) {
        min$$1 = [Infinity, Infinity];
        max$$1 = [-Infinity, -Infinity];
        for (var i = 0, len$$1 = points.length; i < len$$1; i++) {
            min(min$$1, min$$1, points[i]);
            max(max$$1, max$$1, points[i]);
        }
        // 与指定的包围盒做并集
        min(min$$1, min$$1, constraint[0]);
        max(max$$1, max$$1, constraint[1]);
    }

    for (var i = 0, len$$1 = points.length; i < len$$1; i++) {
        var point = points[i];

        if (isLoop) {
            prevPoint = points[i ? i - 1 : len$$1 - 1];
            nextPoint = points[(i + 1) % len$$1];
        }
        else {
            if (i === 0 || i === len$$1 - 1) {
                cps.push(clone$1(points[i]));
                continue;
            }
            else {
                prevPoint = points[i - 1];
                nextPoint = points[i + 1];
            }
        }

        sub(v, nextPoint, prevPoint);

        // use degree to scale the handle length
        scale(v, v, smooth);

        var d0 = distance(point, prevPoint);
        var d1 = distance(point, nextPoint);
        var sum = d0 + d1;
        if (sum !== 0) {
            d0 /= sum;
            d1 /= sum;
        }

        scale(v1, v, -d0);
        scale(v2, v, d1);
        var cp0 = add([], point, v1);
        var cp1 = add([], point, v2);
        if (constraint) {
            max(cp0, cp0, min$$1);
            min(cp0, cp0, max$$1);
            max(cp1, cp1, min$$1);
            min(cp1, cp1, max$$1);
        }
        cps.push(cp0);
        cps.push(cp1);
    }

    if (isLoop) {
        cps.push(cps.shift());
    }

    return cps;
};

function buildPath$1(ctx, shape, closePath) {
    var points = shape.points;
    var smooth = shape.smooth;
    if (points && points.length >= 2) {
        if (smooth && smooth !== 'spline') {
            var controlPoints = smoothBezier(
                points, smooth, closePath, shape.smoothConstraint
            );

            ctx.moveTo(points[0][0], points[0][1]);
            var len = points.length;
            for (var i = 0; i < (closePath ? len : len - 1); i++) {
                var cp1 = controlPoints[i * 2];
                var cp2 = controlPoints[i * 2 + 1];
                var p = points[(i + 1) % len];
                ctx.bezierCurveTo(
                    cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]
                );
            }
        }
        else {
            if (smooth === 'spline') {
                points = smoothSpline(points, closePath);
            }

            ctx.moveTo(points[0][0], points[0][1]);
            for (var i = 1, l = points.length; i < l; i++) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
        }

        closePath && ctx.closePath();
    }
}

/**
 * 多边形
 * @module zrender/shape/Polygon
 */

var Polygon = Path.extend({

    type: 'polygon',

    shape: {
        points: null,

        smooth: false,

        smoothConstraint: null
    },

    buildPath: function (ctx, shape) {
        buildPath$1(ctx, shape, true);
    }
});

/**
 * @module zrender/graphic/shape/Polyline
 */

var Polyline = Path.extend({

    type: 'polyline',

    shape: {
        points: null,

        smooth: false,

        smoothConstraint: null
    },

    style: {
        stroke: '#000',

        fill: null
    },

    buildPath: function (ctx, shape) {
        buildPath$1(ctx, shape, false);
    }
});

/**
 * Sub-pixel optimize for canvas rendering, prevent from blur
 * when rendering a thin vertical/horizontal line.
 */

var round = Math.round;

/**
 * Sub pixel optimize line for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x1`, `x2`, `y1`, `y2` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x1]
 * @param {number} [inputShape.y1]
 * @param {number} [inputShape.x2]
 * @param {number} [inputShape.y2]
 * @param {Object} [style]
 * @param {number} [style.lineWidth]
 */
function subPixelOptimizeLine$1(outputShape, inputShape, style) {
    var lineWidth = style && style.lineWidth;

    if (!inputShape || !lineWidth) {
        return;
    }

    var x1 = inputShape.x1;
    var x2 = inputShape.x2;
    var y1 = inputShape.y1;
    var y2 = inputShape.y2;

    if (round(x1 * 2) === round(x2 * 2)) {
        outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true);
    }
    else {
        outputShape.x1 = x1;
        outputShape.x2 = x2;
    }
    if (round(y1 * 2) === round(y2 * 2)) {
        outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true);
    }
    else {
        outputShape.y1 = y1;
        outputShape.y2 = y2;
    }
}

/**
 * Sub pixel optimize rect for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x`, `y`, `width`, `height` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x]
 * @param {number} [inputShape.y]
 * @param {number} [inputShape.width]
 * @param {number} [inputShape.height]
 * @param {Object} [style]
 * @param {number} [style.lineWidth]
 */
function subPixelOptimizeRect$1(outputShape, inputShape, style) {
    var lineWidth = style && style.lineWidth;

    if (!inputShape || !lineWidth) {
        return;
    }

    var originX = inputShape.x;
    var originY = inputShape.y;
    var originWidth = inputShape.width;
    var originHeight = inputShape.height;

    outputShape.x = subPixelOptimize$1(originX, lineWidth, true);
    outputShape.y = subPixelOptimize$1(originY, lineWidth, true);
    outputShape.width = Math.max(
        subPixelOptimize$1(originX + originWidth, lineWidth, false) - outputShape.x,
        originWidth === 0 ? 0 : 1
    );
    outputShape.height = Math.max(
        subPixelOptimize$1(originY + originHeight, lineWidth, false) - outputShape.y,
        originHeight === 0 ? 0 : 1
    );
}

/**
 * Sub pixel optimize for canvas
 *
 * @param {number} position Coordinate, such as x, y
 * @param {number} lineWidth Should be nonnegative integer.
 * @param {boolean=} positiveOrNegative Default false (negative).
 * @return {number} Optimized position.
 */
function subPixelOptimize$1(position, lineWidth, positiveOrNegative) {
    // Assure that (position + lineWidth / 2) is near integer edge,
    // otherwise line will be fuzzy in canvas.
    var doubledPosition = round(position * 2);
    return (doubledPosition + round(lineWidth)) % 2 === 0
        ? doubledPosition / 2
        : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
}

/**
 * 矩形
 * @module zrender/graphic/shape/Rect
 */

// Avoid create repeatly.
var subPixelOptimizeOutputShape = {};

var Rect = Path.extend({

    type: 'rect',

    shape: {
        // 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4
        // r缩写为1         相当于 [1, 1, 1, 1]
        // r缩写为[1]       相当于 [1, 1, 1, 1]
        // r缩写为[1, 2]    相当于 [1, 2, 1, 2]
        // r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2]
        r: 0,

        x: 0,
        y: 0,
        width: 0,
        height: 0
    },

    buildPath: function (ctx, shape) {
        var x;
        var y;
        var width;
        var height;

        if (this.subPixelOptimize) {
            subPixelOptimizeRect$1(subPixelOptimizeOutputShape, shape, this.style);
            x = subPixelOptimizeOutputShape.x;
            y = subPixelOptimizeOutputShape.y;
            width = subPixelOptimizeOutputShape.width;
            height = subPixelOptimizeOutputShape.height;
            subPixelOptimizeOutputShape.r = shape.r;
            shape = subPixelOptimizeOutputShape;
        }
        else {
            x = shape.x;
            y = shape.y;
            width = shape.width;
            height = shape.height;
        }

        if (!shape.r) {
            ctx.rect(x, y, width, height);
        }
        else {
            buildPath(ctx, shape);
        }
        ctx.closePath();
        return;
    }
});

/**
 * 直线
 * @module zrender/graphic/shape/Line
 */

// Avoid create repeatly.
var subPixelOptimizeOutputShape$1 = {};

var Line = Path.extend({

    type: 'line',

    shape: {
        // Start point
        x1: 0,
        y1: 0,
        // End point
        x2: 0,
        y2: 0,

        percent: 1
    },

    style: {
        stroke: '#000',
        fill: null
    },

    buildPath: function (ctx, shape) {
        var x1;
        var y1;
        var x2;
        var y2;

        if (this.subPixelOptimize) {
            subPixelOptimizeLine$1(subPixelOptimizeOutputShape$1, shape, this.style);
            x1 = subPixelOptimizeOutputShape$1.x1;
            y1 = subPixelOptimizeOutputShape$1.y1;
            x2 = subPixelOptimizeOutputShape$1.x2;
            y2 = subPixelOptimizeOutputShape$1.y2;
        }
        else {
            x1 = shape.x1;
            y1 = shape.y1;
            x2 = shape.x2;
            y2 = shape.y2;
        }

        var percent = shape.percent;

        if (percent === 0) {
            return;
        }

        ctx.moveTo(x1, y1);

        if (percent < 1) {
            x2 = x1 * (1 - percent) + x2 * percent;
            y2 = y1 * (1 - percent) + y2 * percent;
        }
        ctx.lineTo(x2, y2);
    },

    /**
     * Get point at percent
     * @param  {number} percent
     * @return {Array.<number>}
     */
    pointAt: function (p) {
        var shape = this.shape;
        return [
            shape.x1 * (1 - p) + shape.x2 * p,
            shape.y1 * (1 - p) + shape.y2 * p
        ];
    }
});

/**
 * 贝塞尔曲线
 * @module zrender/shape/BezierCurve
 */

var out = [];

function someVectorAt(shape, t, isTangent) {
    var cpx2 = shape.cpx2;
    var cpy2 = shape.cpy2;
    if (cpx2 === null || cpy2 === null) {
        return [
            (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t),
            (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)
        ];
    }
    else {
        return [
            (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t),
            (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)
        ];
    }
}

var BezierCurve = Path.extend({

    type: 'bezier-curve',

    shape: {
        x1: 0,
        y1: 0,
        x2: 0,
        y2: 0,
        cpx1: 0,
        cpy1: 0,
        // cpx2: 0,
        // cpy2: 0

        // Curve show percent, for animating
        percent: 1
    },

    style: {
        stroke: '#000',
        fill: null
    },

    buildPath: function (ctx, shape) {
        var x1 = shape.x1;
        var y1 = shape.y1;
        var x2 = shape.x2;
        var y2 = shape.y2;
        var cpx1 = shape.cpx1;
        var cpy1 = shape.cpy1;
        var cpx2 = shape.cpx2;
        var cpy2 = shape.cpy2;
        var percent = shape.percent;
        if (percent === 0) {
            return;
        }

        ctx.moveTo(x1, y1);

        if (cpx2 == null || cpy2 == null) {
            if (percent < 1) {
                quadraticSubdivide(
                    x1, cpx1, x2, percent, out
                );
                cpx1 = out[1];
                x2 = out[2];
                quadraticSubdivide(
                    y1, cpy1, y2, percent, out
                );
                cpy1 = out[1];
                y2 = out[2];
            }

            ctx.quadraticCurveTo(
                cpx1, cpy1,
                x2, y2
            );
        }
        else {
            if (percent < 1) {
                cubicSubdivide(
                    x1, cpx1, cpx2, x2, percent, out
                );
                cpx1 = out[1];
                cpx2 = out[2];
                x2 = out[3];
                cubicSubdivide(
                    y1, cpy1, cpy2, y2, percent, out
                );
                cpy1 = out[1];
                cpy2 = out[2];
                y2 = out[3];
            }
            ctx.bezierCurveTo(
                cpx1, cpy1,
                cpx2, cpy2,
                x2, y2
            );
        }
    },

    /**
     * Get point at percent
     * @param  {number} t
     * @return {Array.<number>}
     */
    pointAt: function (t) {
        return someVectorAt(this.shape, t, false);
    },

    /**
     * Get tangent at percent
     * @param  {number} t
     * @return {Array.<number>}
     */
    tangentAt: function (t) {
        var p = someVectorAt(this.shape, t, true);
        return normalize(p, p);
    }
});

/**
 * 圆弧
 * @module zrender/graphic/shape/Arc
 */

var Arc = Path.extend({

    type: 'arc',

    shape: {

        cx: 0,

        cy: 0,

        r: 0,

        startAngle: 0,

        endAngle: Math.PI * 2,

        clockwise: true
    },

    style: {

        stroke: '#000',

        fill: null
    },

    buildPath: function (ctx, shape) {

        var x = shape.cx;
        var y = shape.cy;
        var r = Math.max(shape.r, 0);
        var startAngle = shape.startAngle;
        var endAngle = shape.endAngle;
        var clockwise = shape.clockwise;

        var unitX = Math.cos(startAngle);
        var unitY = Math.sin(startAngle);

        ctx.moveTo(unitX * r + x, unitY * r + y);
        ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
    }
});

// CompoundPath to improve performance

var CompoundPath = Path.extend({

    type: 'compound',

    shape: {

        paths: null
    },

    _updatePathDirty: function () {
        var dirtyPath = this.__dirtyPath;
        var paths = this.shape.paths;
        for (var i = 0; i < paths.length; i++) {
            // Mark as dirty if any subpath is dirty
            dirtyPath = dirtyPath || paths[i].__dirtyPath;
        }
        this.__dirtyPath = dirtyPath;
        this.__dirty = this.__dirty || dirtyPath;
    },

    beforeBrush: function () {
        this._updatePathDirty();
        var paths = this.shape.paths || [];
        var scale = this.getGlobalScale();
        // Update path scale
        for (var i = 0; i < paths.length; i++) {
            if (!paths[i].path) {
                paths[i].createPathProxy();
            }
            paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold);
        }
    },

    buildPath: function (ctx, shape) {
        var paths = shape.paths || [];
        for (var i = 0; i < paths.length; i++) {
            paths[i].buildPath(ctx, paths[i].shape, true);
        }
    },

    afterBrush: function () {
        var paths = this.shape.paths || [];
        for (var i = 0; i < paths.length; i++) {
            paths[i].__dirtyPath = false;
        }
    },

    getBoundingRect: function () {
        this._updatePathDirty();
        return Path.prototype.getBoundingRect.call(this);
    }
});

/**
 * @param {Array.<Object>} colorStops
 */
var Gradient = function (colorStops) {

    this.colorStops = colorStops || [];

};

Gradient.prototype = {

    constructor: Gradient,

    addColorStop: function (offset, color) {
        this.colorStops.push({

            offset: offset,

            color: color
        });
    }

};

/**
 * x, y, x2, y2 are all percent from 0 to 1
 * @param {number} [x=0]
 * @param {number} [y=0]
 * @param {number} [x2=1]
 * @param {number} [y2=0]
 * @param {Array.<Object>} colorStops
 * @param {boolean} [globalCoord=false]
 */
var LinearGradient = function (x, y, x2, y2, colorStops, globalCoord) {
    // Should do nothing more in this constructor. Because gradient can be
    // declard by `color: {type: 'linear', colorStops: ...}`, where
    // this constructor will not be called.

    this.x = x == null ? 0 : x;

    this.y = y == null ? 0 : y;

    this.x2 = x2 == null ? 1 : x2;

    this.y2 = y2 == null ? 0 : y2;

    // Can be cloned
    this.type = 'linear';

    // If use global coord
    this.global = globalCoord || false;

    Gradient.call(this, colorStops);
};

LinearGradient.prototype = {

    constructor: LinearGradient
};

inherits(LinearGradient, Gradient);

/**
 * x, y, r are all percent from 0 to 1
 * @param {number} [x=0.5]
 * @param {number} [y=0.5]
 * @param {number} [r=0.5]
 * @param {Array.<Object>} [colorStops]
 * @param {boolean} [globalCoord=false]
 */
var RadialGradient = function (x, y, r, colorStops, globalCoord) {
    // Should do nothing more in this constructor. Because gradient can be
    // declard by `color: {type: 'radial', colorStops: ...}`, where
    // this constructor will not be called.

    this.x = x == null ? 0.5 : x;

    this.y = y == null ? 0.5 : y;

    this.r = r == null ? 0.5 : r;

    // Can be cloned
    this.type = 'radial';

    // If use global coord
    this.global = globalCoord || false;

    Gradient.call(this, colorStops);
};

RadialGradient.prototype = {

    constructor: RadialGradient
};

inherits(RadialGradient, Gradient);

/**
 * Displayable for incremental rendering. It will be rendered in a separate layer
 * IncrementalDisplay have two main methods. `clearDisplayables` and `addDisplayables`
 * addDisplayables will render the added displayables incremetally.
 *
 * It use a not clearFlag to tell the painter don't clear the layer if it's the first element.
 */
// TODO Style override ?
function IncrementalDisplayble(opts) {

    Displayable.call(this, opts);

    this._displayables = [];

    this._temporaryDisplayables = [];

    this._cursor = 0;

    this.notClear = true;
}

IncrementalDisplayble.prototype.incremental = true;

IncrementalDisplayble.prototype.clearDisplaybles = function () {
    this._displayables = [];
    this._temporaryDisplayables = [];
    this._cursor = 0;
    this.dirty();

    this.notClear = false;
};

IncrementalDisplayble.prototype.addDisplayable = function (displayable, notPersistent) {
    if (notPersistent) {
        this._temporaryDisplayables.push(displayable);
    }
    else {
        this._displayables.push(displayable);
    }
    this.dirty();
};

IncrementalDisplayble.prototype.addDisplayables = function (displayables, notPersistent) {
    notPersistent = notPersistent || false;
    for (var i = 0; i < displayables.length; i++) {
        this.addDisplayable(displayables[i], notPersistent);
    }
};

IncrementalDisplayble.prototype.eachPendingDisplayable = function (cb) {
    for (var i = this._cursor; i < this._displayables.length; i++) {
        cb && cb(this._displayables[i]);
    }
    for (var i = 0; i < this._temporaryDisplayables.length; i++) {
        cb && cb(this._temporaryDisplayables[i]);
    }
};

IncrementalDisplayble.prototype.update = function () {
    this.updateTransform();
    for (var i = this._cursor; i < this._displayables.length; i++) {
        var displayable = this._displayables[i];
        // PENDING
        displayable.parent = this;
        displayable.update();
        displayable.parent = null;
    }
    for (var i = 0; i < this._temporaryDisplayables.length; i++) {
        var displayable = this._temporaryDisplayables[i];
        // PENDING
        displayable.parent = this;
        displayable.update();
        displayable.parent = null;
    }
};

IncrementalDisplayble.prototype.brush = function (ctx, prevEl) {
    // Render persistant displayables.
    for (var i = this._cursor; i < this._displayables.length; i++) {
        var displayable = this._displayables[i];
        displayable.beforeBrush && displayable.beforeBrush(ctx);
        displayable.brush(ctx, i === this._cursor ? null : this._displayables[i - 1]);
        displayable.afterBrush && displayable.afterBrush(ctx);
    }
    this._cursor = i;
    // Render temporary displayables.
    for (var i = 0; i < this._temporaryDisplayables.length; i++) {
        var displayable = this._temporaryDisplayables[i];
        displayable.beforeBrush && displayable.beforeBrush(ctx);
        displayable.brush(ctx, i === 0 ? null : this._temporaryDisplayables[i - 1]);
        displayable.afterBrush && displayable.afterBrush(ctx);
    }

    this._temporaryDisplayables = [];

    this.notClear = true;
};

var m = [];
IncrementalDisplayble.prototype.getBoundingRect = function () {
    if (!this._rect) {
        var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity);
        for (var i = 0; i < this._displayables.length; i++) {
            var displayable = this._displayables[i];
            var childRect = displayable.getBoundingRect().clone();
            if (displayable.needLocalTransform()) {
                childRect.applyTransform(displayable.getLocalTransform(m));
            }
            rect.union(childRect);
        }
        this._rect = rect;
    }
    return this._rect;
};

IncrementalDisplayble.prototype.contain = function (x, y) {
    var localPos = this.transformCoordToLocal(x, y);
    var rect = this.getBoundingRect();

    if (rect.contain(localPos[0], localPos[1])) {
        for (var i = 0; i < this._displayables.length; i++) {
            var displayable = this._displayables[i];
            if (displayable.contain(x, y)) {
                return true;
            }
        }
    }
    return false;
};

inherits(IncrementalDisplayble, Displayable);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var mathMax$1 = Math.max;
var mathMin$1 = Math.min;

var EMPTY_OBJ = {};

var Z2_EMPHASIS_LIFT = 1;

// key: label model property nane, value: style property name.
var CACHED_LABEL_STYLE_PROPERTIES = {
    color: 'textFill',
    textBorderColor: 'textStroke',
    textBorderWidth: 'textStrokeWidth'
};

var EMPHASIS = 'emphasis';
var NORMAL = 'normal';

// Reserve 0 as default.
var _highlightNextDigit = 1;
var _highlightKeyMap = {};

var _customShapeMap = {};


/**
 * Extend shape with parameters
 */
function extendShape(opts) {
    return Path.extend(opts);
}

/**
 * Extend path
 */
function extendPath(pathData, opts) {
    return extendFromString(pathData, opts);
}

/**
 * Register a user defined shape.
 * The shape class can be fetched by `getShapeClass`
 * This method will overwrite the registered shapes, including
 * the registered built-in shapes, if using the same `name`.
 * The shape can be used in `custom series` and
 * `graphic component` by declaring `{type: name}`.
 *
 * @param {string} name
 * @param {Object} ShapeClass Can be generated by `extendShape`.
 */
function registerShape(name, ShapeClass) {
    _customShapeMap[name] = ShapeClass;
}

/**
 * Find shape class registered by `registerShape`. Usually used in
 * fetching user defined shape.
 *
 * [Caution]:
 * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared
 * to use user registered shapes.
 * Because the built-in shape (see `getBuiltInShape`) will be registered by
 * `registerShape` by default. That enables users to get both built-in
 * shapes as well as the shapes belonging to themsleves. But users can overwrite
 * the built-in shapes by using names like 'circle', 'rect' via calling
 * `registerShape`. So the echarts inner featrues should not fetch shapes from here
 * in case that it is overwritten by users, except that some features, like
 * `custom series`, `graphic component`, do it deliberately.
 *
 * (2) In the features like `custom series`, `graphic component`, the user input
 * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic
 * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names
 * are reserved names, that is, if some user register a shape named `'image'`,
 * the shape will not be used. If we intending to add some more reserved names
 * in feature, that might bring break changes (disable some existing user shape
 * names). But that case probably rearly happen. So we dont make more mechanism
 * to resolve this issue here.
 *
 * @param {string} name
 * @return {Object} The shape class. If not found, return nothing.
 */
function getShapeClass(name) {
    if (_customShapeMap.hasOwnProperty(name)) {
        return _customShapeMap[name];
    }
}

/**
 * Create a path element from path data string
 * @param {string} pathData
 * @param {Object} opts
 * @param {module:zrender/core/BoundingRect} rect
 * @param {string} [layout=cover] 'center' or 'cover'
 */
function makePath(pathData, opts, rect, layout) {
    var path = createFromString(pathData, opts);
    if (rect) {
        if (layout === 'center') {
            rect = centerGraphic(rect, path.getBoundingRect());
        }
        resizePath(path, rect);
    }
    return path;
}

/**
 * Create a image element from image url
 * @param {string} imageUrl image url
 * @param {Object} opts options
 * @param {module:zrender/core/BoundingRect} rect constrain rect
 * @param {string} [layout=cover] 'center' or 'cover'
 */
function makeImage(imageUrl, rect, layout) {
    var path = new ZImage({
        style: {
            image: imageUrl,
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
        },
        onload: function (img) {
            if (layout === 'center') {
                var boundingRect = {
                    width: img.width,
                    height: img.height
                };
                path.setStyle(centerGraphic(rect, boundingRect));
            }
        }
    });
    return path;
}

/**
 * Get position of centered element in bounding box.
 *
 * @param  {Object} rect         element local bounding box
 * @param  {Object} boundingRect constraint bounding box
 * @return {Object} element position containing x, y, width, and height
 */
function centerGraphic(rect, boundingRect) {
    // Set rect to center, keep width / height ratio.
    var aspect = boundingRect.width / boundingRect.height;
    var width = rect.height * aspect;
    var height;
    if (width <= rect.width) {
        height = rect.height;
    }
    else {
        width = rect.width;
        height = width / aspect;
    }
    var cx = rect.x + rect.width / 2;
    var cy = rect.y + rect.height / 2;

    return {
        x: cx - width / 2,
        y: cy - height / 2,
        width: width,
        height: height
    };
}

var mergePath = mergePath$1;

/**
 * Resize a path to fit the rect
 * @param {module:zrender/graphic/Path} path
 * @param {Object} rect
 */
function resizePath(path, rect) {
    if (!path.applyTransform) {
        return;
    }

    var pathRect = path.getBoundingRect();

    var m = pathRect.calculateTransform(rect);

    path.applyTransform(m);
}

/**
 * Sub pixel optimize line for canvas
 *
 * @param {Object} param
 * @param {Object} [param.shape]
 * @param {number} [param.shape.x1]
 * @param {number} [param.shape.y1]
 * @param {number} [param.shape.x2]
 * @param {number} [param.shape.y2]
 * @param {Object} [param.style]
 * @param {number} [param.style.lineWidth]
 * @return {Object} Modified param
 */
function subPixelOptimizeLine(param) {
    subPixelOptimizeLine$1(param.shape, param.shape, param.style);
    return param;
}

/**
 * Sub pixel optimize rect for canvas
 *
 * @param {Object} param
 * @param {Object} [param.shape]
 * @param {number} [param.shape.x]
 * @param {number} [param.shape.y]
 * @param {number} [param.shape.width]
 * @param {number} [param.shape.height]
 * @param {Object} [param.style]
 * @param {number} [param.style.lineWidth]
 * @return {Object} Modified param
 */
function subPixelOptimizeRect(param) {
    subPixelOptimizeRect$1(param.shape, param.shape, param.style);
    return param;
}

/**
 * Sub pixel optimize for canvas
 *
 * @param {number} position Coordinate, such as x, y
 * @param {number} lineWidth Should be nonnegative integer.
 * @param {boolean=} positiveOrNegative Default false (negative).
 * @return {number} Optimized position.
 */
var subPixelOptimize = subPixelOptimize$1;


function hasFillOrStroke(fillOrStroke) {
    return fillOrStroke != null && fillOrStroke !== 'none';
}

// Most lifted color are duplicated.
var liftedColorMap = createHashMap();
var liftedColorCount = 0;

function liftColor(color) {
    if (typeof color !== 'string') {
        return color;
    }
    var liftedColor = liftedColorMap.get(color);
    if (!liftedColor) {
        liftedColor = lift(color, -0.1);
        if (liftedColorCount < 10000) {
            liftedColorMap.set(color, liftedColor);
            liftedColorCount++;
        }
    }
    return liftedColor;
}

function cacheElementStl(el) {
    if (!el.__hoverStlDirty) {
        return;
    }
    el.__hoverStlDirty = false;

    var hoverStyle = el.__hoverStl;
    if (!hoverStyle) {
        el.__cachedNormalStl = el.__cachedNormalZ2 = null;
        return;
    }

    var normalStyle = el.__cachedNormalStl = {};
    el.__cachedNormalZ2 = el.z2;
    var elStyle = el.style;

    for (var name in hoverStyle) {
        // See comment in `singleEnterEmphasis`.
        if (hoverStyle[name] != null) {
            normalStyle[name] = elStyle[name];
        }
    }

    // Always cache fill and stroke to normalStyle for lifting color.
    normalStyle.fill = elStyle.fill;
    normalStyle.stroke = elStyle.stroke;
}

function singleEnterEmphasis(el) {
    var hoverStl = el.__hoverStl;

    if (!hoverStl || el.__highlighted) {
        return;
    }

    var zr = el.__zr;

    var useHoverLayer = el.useHoverLayer && zr && zr.painter.type === 'canvas';
    el.__highlighted = useHoverLayer ? 'layer' : 'plain';

    if (el.isGroup || (!zr && el.useHoverLayer)) {
        return;
    }

    var elTarget = el;
    var targetStyle = el.style;

    if (useHoverLayer) {
        elTarget = zr.addHover(el);
        targetStyle = elTarget.style;
    }

    rollbackDefaultTextStyle(targetStyle);

    if (!useHoverLayer) {
        cacheElementStl(elTarget);
    }

    // styles can be:
    // {
    //    label: {
    //        show: false,
    //        position: 'outside',
    //        fontSize: 18
    //    },
    //    emphasis: {
    //        label: {
    //            show: true
    //        }
    //    }
    // },
    // where properties of `emphasis` may not appear in `normal`. We previously use
    // module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`.
    // But consider rich text and setOption in merge mode, it is impossible to cover
    // all properties in merge. So we use merge mode when setting style here.
    // But we choose the merge strategy that only properties that is not `null/undefined`.
    // Because when making a textStyle (espacially rich text), it is not easy to distinguish
    // `hasOwnProperty` and `null/undefined` in code, so we trade them as the same for simplicity.
    // But this strategy brings a trouble that `null/undefined` can not be used to remove
    // style any more in `emphasis`. Users can both set properties directly on normal and
    // emphasis to avoid this issue, or we might support `'none'` for this case if required.
    targetStyle.extendFrom(hoverStl);

    setDefaultHoverFillStroke(targetStyle, hoverStl, 'fill');
    setDefaultHoverFillStroke(targetStyle, hoverStl, 'stroke');

    applyDefaultTextStyle(targetStyle);

    if (!useHoverLayer) {
        el.dirty(false);
        el.z2 += Z2_EMPHASIS_LIFT;
    }
}

function setDefaultHoverFillStroke(targetStyle, hoverStyle, prop) {
    if (!hasFillOrStroke(hoverStyle[prop]) && hasFillOrStroke(targetStyle[prop])) {
        targetStyle[prop] = liftColor(targetStyle[prop]);
    }
}

function singleEnterNormal(el) {
    var highlighted = el.__highlighted;

    if (!highlighted) {
        return;
    }

    el.__highlighted = false;

    if (el.isGroup) {
        return;
    }

    if (highlighted === 'layer') {
        el.__zr && el.__zr.removeHover(el);
    }
    else {
        var style = el.style;

        var normalStl = el.__cachedNormalStl;
        if (normalStl) {
            rollbackDefaultTextStyle(style);
            el.setStyle(normalStl);
            applyDefaultTextStyle(style);
        }
        // `__cachedNormalZ2` will not be reset if calling `setElementHoverStyle`
        // when `el` is on emphasis state. So here by comparing with 1, we try
        // hard to make the bug case rare.
        var normalZ2 = el.__cachedNormalZ2;
        if (normalZ2 != null && el.z2 - normalZ2 === Z2_EMPHASIS_LIFT) {
            el.z2 = normalZ2;
        }
    }
}

function traverseUpdate(el, updater, commonParam) {
    // If root is group, also enter updater for `highDownOnUpdate`.
    var fromState = NORMAL;
    var toState = NORMAL;
    var trigger;
    // See the rule of `highDownOnUpdate` on `graphic.setAsHighDownDispatcher`.
    el.__highlighted && (fromState = EMPHASIS, trigger = true);
    updater(el, commonParam);
    el.__highlighted && (toState = EMPHASIS, trigger = true);

    el.isGroup && el.traverse(function (child) {
        !child.isGroup && updater(child, commonParam);
    });

    trigger && el.__highDownOnUpdate && el.__highDownOnUpdate(fromState, toState);
}

/**
 * Set hover style (namely "emphasis style") of element, based on the current
 * style of the given `el`.
 * This method should be called after all of the normal styles have been adopted
 * to the `el`. See the reason on `setHoverStyle`.
 *
 * @param {module:zrender/Element} el Should not be `zrender/container/Group`.
 * @param {Object} [el.hoverStyle] Can be set on el or its descendants,
 *        e.g., `el.hoverStyle = ...; graphic.setHoverStyle(el); `.
 *        Often used when item group has a label element and it's hoverStyle is different.
 * @param {Object|boolean} [hoverStl] The specified hover style.
 *        If set as `false`, disable the hover style.
 *        Similarly, The `el.hoverStyle` can alse be set
 *        as `false` to disable the hover style.
 *        Otherwise, use the default hover style if not provided.
 */
function setElementHoverStyle(el, hoverStl) {
    // For performance consideration, it might be better to make the "hover style" only the
    // difference properties from the "normal style", but not a entire copy of all styles.
    hoverStl = el.__hoverStl = hoverStl !== false && (el.hoverStyle || hoverStl || {});
    el.__hoverStlDirty = true;

    // FIXME
    // It is not completely right to save "normal"/"emphasis" flag on elements.
    // It probably should be saved on `data` of series. Consider the cases:
    // (1) A highlighted elements are moved out of the view port and re-enter
    // again by dataZoom.
    // (2) call `setOption` and replace elements totally when they are highlighted.
    if (el.__highlighted) {
        // Consider the case:
        // The styles of a highlighted `el` is being updated. The new "emphasis style"
        // should be adapted to the `el`. Notice here new "normal styles" should have
        // been set outside and the cached "normal style" is out of date.
        el.__cachedNormalStl = null;
        // Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint
        // of this method. In most cases, `z2` is not set and hover style should be able
        // to rollback. Of course, that would bring bug, but only in a rare case, see
        // `doSingleLeaveHover` for details.
        singleEnterNormal(el);

        singleEnterEmphasis(el);
    }
}

function onElementMouseOver(e) {
    !shouldSilent(this, e)
        // "emphasis" event highlight has higher priority than mouse highlight.
        && !this.__highByOuter
        && traverseUpdate(this, singleEnterEmphasis);
}

function onElementMouseOut(e) {
    !shouldSilent(this, e)
        // "emphasis" event highlight has higher priority than mouse highlight.
        && !this.__highByOuter
        && traverseUpdate(this, singleEnterNormal);
}

function onElementEmphasisEvent(highlightDigit) {
    this.__highByOuter |= 1 << (highlightDigit || 0);
    traverseUpdate(this, singleEnterEmphasis);
}

function onElementNormalEvent(highlightDigit) {
    !(this.__highByOuter &= ~(1 << (highlightDigit || 0)))
        && traverseUpdate(this, singleEnterNormal);
}

function shouldSilent(el, e) {
    return el.__highDownSilentOnTouch && e.zrByTouch;
}

/**
 * Set hover style (namely "emphasis style") of element,
 * based on the current style of the given `el`.
 *
 * (1)
 * **CONSTRAINTS** for this method:
 * <A> This method MUST be called after all of the normal styles having been adopted
 * to the `el`.
 * <B> The input `hoverStyle` (that is, "emphasis style") MUST be the subset of the
 * "normal style" having been set to the el.
 * <C> `color` MUST be one of the "normal styles" (because color might be lifted as
 * a default hover style).
 *
 * The reason: this method treat the current style of the `el` as the "normal style"
 * and cache them when enter/update the "emphasis style". Consider the case: the `el`
 * is in "emphasis" state and `setOption`/`dispatchAction` trigger the style updating
 * logic, where the el should shift from the original emphasis style to the new
 * "emphasis style" and should be able to "downplay" back to the new "normal style".
 *
 * Indeed, it is error-prone to make a interface has so many constraints, but I have
 * not found a better solution yet to fit the backward compatibility, performance and
 * the current programming style.
 *
 * (2)
 * Call the method for a "root" element once. Do not call it for each descendants.
 * If the descendants elemenets of a group has itself hover style different from the
 * root group, we can simply mount the style on `el.hoverStyle` for them, but should
 * not call this method for them.
 *
 * (3) These input parameters can be set directly on `el`:
 *
 * @param {module:zrender/Element} el
 * @param {Object} [el.hoverStyle] See `graphic.setElementHoverStyle`.
 * @param {boolean} [el.highDownSilentOnTouch=false] See `graphic.setAsHighDownDispatcher`.
 * @param {Function} [el.highDownOnUpdate] See `graphic.setAsHighDownDispatcher`.
 * @param {Object|boolean} [hoverStyle] See `graphic.setElementHoverStyle`.
 */
function setHoverStyle(el, hoverStyle) {
    setAsHighDownDispatcher(el, true);
    traverseUpdate(el, setElementHoverStyle, hoverStyle);
}

/**
 * @param {module:zrender/Element} el
 * @param {Function} [el.highDownOnUpdate] Called when state updated.
 *        Since `setHoverStyle` has the constraint that it must be called after
 *        all of the normal style updated, `highDownOnUpdate` is not needed to
 *        trigger if both `fromState` and `toState` is 'normal', and needed to
 *        trigger if both `fromState` and `toState` is 'emphasis', which enables
 *        to sync outside style settings to "emphasis" state.
 *        @this {string} This dispatcher `el`.
 *        @param {string} fromState Can be "normal" or "emphasis".
 *               `fromState` might equal to `toState`,
 *               for example, when this method is called when `el` is
 *               on "emphasis" state.
 *        @param {string} toState Can be "normal" or "emphasis".
 *
 *        FIXME
 *        CAUTION: Do not expose `highDownOnUpdate` outside echarts.
 *        Because it is not a complete solution. The update
 *        listener should not have been mount in element,
 *        and the normal/emphasis state should not have
 *        mantained on elements.
 *
 * @param {boolean} [el.highDownSilentOnTouch=false]
 *        In touch device, mouseover event will be trigger on touchstart event
 *        (see module:zrender/dom/HandlerProxy). By this mechanism, we can
 *        conveniently use hoverStyle when tap on touch screen without additional
 *        code for compatibility.
 *        But if the chart/component has select feature, which usually also use
 *        hoverStyle, there might be conflict between 'select-highlight' and
 *        'hover-highlight' especially when roam is enabled (see geo for example).
 *        In this case, `highDownSilentOnTouch` should be used to disable
 *        hover-highlight on touch device.
 * @param {boolean} [asDispatcher=true] If `false`, do not set as "highDownDispatcher".
 */
function setAsHighDownDispatcher(el, asDispatcher) {
    var disable = asDispatcher === false;
    // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after
    // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
    el.__highDownSilentOnTouch = el.highDownSilentOnTouch;
    el.__highDownOnUpdate = el.highDownOnUpdate;

    // Simple optimize, since this method might be
    // called for each elements of a group in some cases.
    if (!disable || el.__highDownDispatcher) {
        var method = disable ? 'off' : 'on';

        // Duplicated function will be auto-ignored, see Eventful.js.
        el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut);
        // Emphasis, normal can be triggered manually by API or other components like hover link.
        el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
        // Also keep previous record.
        el.__highByOuter = el.__highByOuter || 0;

        el.__highDownDispatcher = !disable;
    }
}

/**
 * @param {module:zrender/src/Element} el
 * @return {boolean}
 */
function isHighDownDispatcher(el) {
    return !!(el && el.__highDownDispatcher);
}

/**
 * Support hightlight/downplay record on each elements.
 * For the case: hover highlight/downplay (legend, visualMap, ...) and
 * user triggerred hightlight/downplay should not conflict.
 * Only all of the highlightDigit cleared, return to normal.
 * @param {string} highlightKey
 * @return {number} highlightDigit
 */
function getHighlightDigit(highlightKey) {
    var highlightDigit = _highlightKeyMap[highlightKey];
    if (highlightDigit == null && _highlightNextDigit <= 32) {
        highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++;
    }
    return highlightDigit;
}

/**
 * See more info in `setTextStyleCommon`.
 * @param {Object|module:zrender/graphic/Style} normalStyle
 * @param {Object} emphasisStyle
 * @param {module:echarts/model/Model} normalModel
 * @param {module:echarts/model/Model} emphasisModel
 * @param {Object} opt Check `opt` of `setTextStyleCommon` to find other props.
 * @param {string|Function} [opt.defaultText]
 * @param {module:echarts/model/Model} [opt.labelFetcher] Fetch text by
 *      `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
 * @param {module:echarts/model/Model} [opt.labelDataIndex] Fetch text by
 *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
 * @param {module:echarts/model/Model} [opt.labelDimIndex] Fetch text by
 *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)`
 * @param {Object} [normalSpecified]
 * @param {Object} [emphasisSpecified]
 */
function setLabelStyle(
    normalStyle, emphasisStyle,
    normalModel, emphasisModel,
    opt,
    normalSpecified, emphasisSpecified
) {
    opt = opt || EMPTY_OBJ;
    var labelFetcher = opt.labelFetcher;
    var labelDataIndex = opt.labelDataIndex;
    var labelDimIndex = opt.labelDimIndex;

    // This scenario, `label.normal.show = true; label.emphasis.show = false`,
    // is not supported util someone requests.

    var showNormal = normalModel.getShallow('show');
    var showEmphasis = emphasisModel.getShallow('show');

    // Consider performance, only fetch label when necessary.
    // If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set,
    // label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.
    var baseText;
    if (showNormal || showEmphasis) {
        if (labelFetcher) {
            baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex);
        }
        if (baseText == null) {
            baseText = isFunction$1(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText;
        }
    }
    var normalStyleText = showNormal ? baseText : null;
    var emphasisStyleText = showEmphasis
        ? retrieve2(
            labelFetcher
                ? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex)
                : null,
            baseText
        )
        : null;

    // Optimize: If style.text is null, text will not be drawn.
    if (normalStyleText != null || emphasisStyleText != null) {
        // Always set `textStyle` even if `normalStyle.text` is null, because default
        // values have to be set on `normalStyle`.
        // If we set default values on `emphasisStyle`, consider case:
        // Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);`
        // Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);`
        // Then the 'red' will not work on emphasis.
        setTextStyle(normalStyle, normalModel, normalSpecified, opt);
        setTextStyle(emphasisStyle, emphasisModel, emphasisSpecified, opt, true);
    }

    normalStyle.text = normalStyleText;
    emphasisStyle.text = emphasisStyleText;
}

/**
 * Modify label style manually.
 * Only works after `setLabelStyle` and `setElementHoverStyle` called.
 *
 * @param {module:zrender/src/Element} el
 * @param {Object} [normalStyleProps] optional
 * @param {Object} [emphasisStyleProps] optional
 */
function modifyLabelStyle(el, normalStyleProps, emphasisStyleProps) {
    var elStyle = el.style;
    if (normalStyleProps) {
        rollbackDefaultTextStyle(elStyle);
        el.setStyle(normalStyleProps);
        applyDefaultTextStyle(elStyle);
    }
    elStyle = el.__hoverStl;
    if (emphasisStyleProps && elStyle) {
        rollbackDefaultTextStyle(elStyle);
        extend(elStyle, emphasisStyleProps);
        applyDefaultTextStyle(elStyle);
    }
}

/**
 * Set basic textStyle properties.
 * See more info in `setTextStyleCommon`.
 * @param {Object|module:zrender/graphic/Style} textStyle
 * @param {module:echarts/model/Model} model
 * @param {Object} [specifiedTextStyle] Can be overrided by settings in model.
 * @param {Object} [opt] See `opt` of `setTextStyleCommon`.
 * @param {boolean} [isEmphasis]
 */
function setTextStyle(
    textStyle, textStyleModel, specifiedTextStyle, opt, isEmphasis
) {
    setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis);
    specifiedTextStyle && extend(textStyle, specifiedTextStyle);
    // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);

    return textStyle;
}

/**
 * Set text option in the style.
 * See more info in `setTextStyleCommon`.
 * @deprecated
 * @param {Object} textStyle
 * @param {module:echarts/model/Model} labelModel
 * @param {string|boolean} defaultColor Default text color.
 *        If set as false, it will be processed as a emphasis style.
 */
function setText(textStyle, labelModel, defaultColor) {
    var opt = {isRectText: true};
    var isEmphasis;

    if (defaultColor === false) {
        isEmphasis = true;
    }
    else {
        // Support setting color as 'auto' to get visual color.
        opt.autoColor = defaultColor;
    }
    setTextStyleCommon(textStyle, labelModel, opt, isEmphasis);
    // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);
}

/**
 * The uniform entry of set text style, that is, retrieve style definitions
 * from `model` and set to `textStyle` object.
 *
 * Never in merge mode, but in overwrite mode, that is, all of the text style
 * properties will be set. (Consider the states of normal and emphasis and
 * default value can be adopted, merge would make the logic too complicated
 * to manage.)
 *
 * The `textStyle` object can either be a plain object or an instance of
 * `zrender/src/graphic/Style`, and either be the style of normal or emphasis.
 * After this mothod called, the `textStyle` object can then be used in
 * `el.setStyle(textStyle)` or `el.hoverStyle = textStyle`.
 *
 * Default value will be adopted and `insideRollbackOpt` will be created.
 * See `applyDefaultTextStyle` `rollbackDefaultTextStyle` for more details.
 *
 * opt: {
 *      disableBox: boolean, Whether diable drawing box of block (outer most).
 *      isRectText: boolean,
 *      autoColor: string, specify a color when color is 'auto',
 *              for textFill, textStroke, textBackgroundColor, and textBorderColor.
 *              If autoColor specified, it is used as default textFill.
 *      useInsideStyle:
 *              `true`: Use inside style (textFill, textStroke, textStrokeWidth)
 *                  if `textFill` is not specified.
 *              `false`: Do not use inside style.
 *              `null/undefined`: use inside style if `isRectText` is true and
 *                  `textFill` is not specified and textPosition contains `'inside'`.
 *      forceRich: boolean
 * }
 */
function setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis) {
    // Consider there will be abnormal when merge hover style to normal style if given default value.
    opt = opt || EMPTY_OBJ;

    if (opt.isRectText) {
        var textPosition;
        if (opt.getTextPosition) {
            textPosition = opt.getTextPosition(textStyleModel, isEmphasis);
        }
        else {
            textPosition = textStyleModel.getShallow('position')
                || (isEmphasis ? null : 'inside');
            // 'outside' is not a valid zr textPostion value, but used
            // in bar series, and magric type should be considered.
            textPosition === 'outside' && (textPosition = 'top');
        }

        textStyle.textPosition = textPosition;
        textStyle.textOffset = textStyleModel.getShallow('offset');
        var labelRotate = textStyleModel.getShallow('rotate');
        labelRotate != null && (labelRotate *= Math.PI / 180);
        textStyle.textRotation = labelRotate;
        textStyle.textDistance = retrieve2(
            textStyleModel.getShallow('distance'), isEmphasis ? null : 5
        );
    }

    var ecModel = textStyleModel.ecModel;
    var globalTextStyle = ecModel && ecModel.option.textStyle;

    // Consider case:
    // {
    //     data: [{
    //         value: 12,
    //         label: {
    //             rich: {
    //                 // no 'a' here but using parent 'a'.
    //             }
    //         }
    //     }],
    //     rich: {
    //         a: { ... }
    //     }
    // }
    var richItemNames = getRichItemNames(textStyleModel);
    var richResult;
    if (richItemNames) {
        richResult = {};
        for (var name in richItemNames) {
            if (richItemNames.hasOwnProperty(name)) {
                // Cascade is supported in rich.
                var richTextStyle = textStyleModel.getModel(['rich', name]);
                // In rich, never `disableBox`.
                // FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`,
                // the default color `'blue'` will not be adopted if no color declared in `rich`.
                // That might confuses users. So probably we should put `textStyleModel` as the
                // root ancestor of the `richTextStyle`. But that would be a break change.
                setTokenTextStyle(richResult[name] = {}, richTextStyle, globalTextStyle, opt, isEmphasis);
            }
        }
    }
    textStyle.rich = richResult;

    setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, true);

    if (opt.forceRich && !opt.textStyle) {
        opt.textStyle = {};
    }

    return textStyle;
}

// Consider case:
// {
//     data: [{
//         value: 12,
//         label: {
//             rich: {
//                 // no 'a' here but using parent 'a'.
//             }
//         }
//     }],
//     rich: {
//         a: { ... }
//     }
// }
function getRichItemNames(textStyleModel) {
    // Use object to remove duplicated names.
    var richItemNameMap;
    while (textStyleModel && textStyleModel !== textStyleModel.ecModel) {
        var rich = (textStyleModel.option || EMPTY_OBJ).rich;
        if (rich) {
            richItemNameMap = richItemNameMap || {};
            for (var name in rich) {
                if (rich.hasOwnProperty(name)) {
                    richItemNameMap[name] = 1;
                }
            }
        }
        textStyleModel = textStyleModel.parentModel;
    }
    return richItemNameMap;
}

function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, isBlock) {
    // In merge mode, default value should not be given.
    globalTextStyle = !isEmphasis && globalTextStyle || EMPTY_OBJ;

    textStyle.textFill = getAutoColor(textStyleModel.getShallow('color'), opt)
        || globalTextStyle.color;
    textStyle.textStroke = getAutoColor(textStyleModel.getShallow('textBorderColor'), opt)
        || globalTextStyle.textBorderColor;
    textStyle.textStrokeWidth = retrieve2(
        textStyleModel.getShallow('textBorderWidth'),
        globalTextStyle.textBorderWidth
    );

    if (!isEmphasis) {
        if (isBlock) {
            textStyle.insideRollbackOpt = opt;
            applyDefaultTextStyle(textStyle);
        }

        // Set default finally.
        if (textStyle.textFill == null) {
            textStyle.textFill = opt.autoColor;
        }
    }

    // Do not use `getFont` here, because merge should be supported, where
    // part of these properties may be changed in emphasis style, and the
    // others should remain their original value got from normal style.
    textStyle.fontStyle = textStyleModel.getShallow('fontStyle') || globalTextStyle.fontStyle;
    textStyle.fontWeight = textStyleModel.getShallow('fontWeight') || globalTextStyle.fontWeight;
    textStyle.fontSize = textStyleModel.getShallow('fontSize') || globalTextStyle.fontSize;
    textStyle.fontFamily = textStyleModel.getShallow('fontFamily') || globalTextStyle.fontFamily;

    textStyle.textAlign = textStyleModel.getShallow('align');
    textStyle.textVerticalAlign = textStyleModel.getShallow('verticalAlign')
        || textStyleModel.getShallow('baseline');

    textStyle.textLineHeight = textStyleModel.getShallow('lineHeight');
    textStyle.textWidth = textStyleModel.getShallow('width');
    textStyle.textHeight = textStyleModel.getShallow('height');
    textStyle.textTag = textStyleModel.getShallow('tag');

    if (!isBlock || !opt.disableBox) {
        textStyle.textBackgroundColor = getAutoColor(textStyleModel.getShallow('backgroundColor'), opt);
        textStyle.textPadding = textStyleModel.getShallow('padding');
        textStyle.textBorderColor = getAutoColor(textStyleModel.getShallow('borderColor'), opt);
        textStyle.textBorderWidth = textStyleModel.getShallow('borderWidth');
        textStyle.textBorderRadius = textStyleModel.getShallow('borderRadius');

        textStyle.textBoxShadowColor = textStyleModel.getShallow('shadowColor');
        textStyle.textBoxShadowBlur = textStyleModel.getShallow('shadowBlur');
        textStyle.textBoxShadowOffsetX = textStyleModel.getShallow('shadowOffsetX');
        textStyle.textBoxShadowOffsetY = textStyleModel.getShallow('shadowOffsetY');
    }

    textStyle.textShadowColor = textStyleModel.getShallow('textShadowColor')
        || globalTextStyle.textShadowColor;
    textStyle.textShadowBlur = textStyleModel.getShallow('textShadowBlur')
        || globalTextStyle.textShadowBlur;
    textStyle.textShadowOffsetX = textStyleModel.getShallow('textShadowOffsetX')
        || globalTextStyle.textShadowOffsetX;
    textStyle.textShadowOffsetY = textStyleModel.getShallow('textShadowOffsetY')
        || globalTextStyle.textShadowOffsetY;
}

function getAutoColor(color, opt) {
    return color !== 'auto' ? color : (opt && opt.autoColor) ? opt.autoColor : null;
}

/**
 * Give some default value to the input `textStyle` object, based on the current settings
 * in this `textStyle` object.
 *
 * The Scenario:
 * when text position is `inside` and `textFill` is not specified, we show
 * text border by default for better view. But it should be considered that text position
 * might be changed when hovering or being emphasis, where the `insideRollback` is used to
 * restore the style.
 *
 * Usage (& NOTICE):
 * When a style object (eithor plain object or instance of `zrender/src/graphic/Style`) is
 * about to be modified on its text related properties, `rollbackDefaultTextStyle` should
 * be called before the modification and `applyDefaultTextStyle` should be called after that.
 * (For the case that all of the text related properties is reset, like `setTextStyleCommon`
 * does, `rollbackDefaultTextStyle` is not needed to be called).
 */
function applyDefaultTextStyle(textStyle) {
    var textPosition = textStyle.textPosition;
    var opt = textStyle.insideRollbackOpt;
    var insideRollback;

    if (opt && textStyle.textFill == null) {
        var autoColor = opt.autoColor;
        var isRectText = opt.isRectText;
        var useInsideStyle = opt.useInsideStyle;

        var useInsideStyleCache = useInsideStyle !== false
            && (useInsideStyle === true
                || (isRectText
                    && textPosition
                    // textPosition can be [10, 30]
                    && typeof textPosition === 'string'
                    && textPosition.indexOf('inside') >= 0
                )
            );
        var useAutoColorCache = !useInsideStyleCache && autoColor != null;

        // All of the props declared in `CACHED_LABEL_STYLE_PROPERTIES` are to be cached.
        if (useInsideStyleCache || useAutoColorCache) {
            insideRollback = {
                textFill: textStyle.textFill,
                textStroke: textStyle.textStroke,
                textStrokeWidth: textStyle.textStrokeWidth
            };
        }
        if (useInsideStyleCache) {
            textStyle.textFill = '#fff';
            // Consider text with #fff overflow its container.
            if (textStyle.textStroke == null) {
                textStyle.textStroke = autoColor;
                textStyle.textStrokeWidth == null && (textStyle.textStrokeWidth = 2);
            }
        }
        if (useAutoColorCache) {
            textStyle.textFill = autoColor;
        }
    }

    // Always set `insideRollback`, so that the previous one can be cleared.
    textStyle.insideRollback = insideRollback;
}

/**
 * Consider the case: in a scatter,
 * label: {
 *     normal: {position: 'inside'},
 *     emphasis: {position: 'top'}
 * }
 * In the normal state, the `textFill` will be set as '#fff' for pretty view (see
 * `applyDefaultTextStyle`), but when switching to emphasis state, the `textFill`
 * should be retured to 'autoColor', but not keep '#fff'.
 */
function rollbackDefaultTextStyle(style) {
    var insideRollback = style.insideRollback;
    if (insideRollback) {
        // Reset all of the props in `CACHED_LABEL_STYLE_PROPERTIES`.
        style.textFill = insideRollback.textFill;
        style.textStroke = insideRollback.textStroke;
        style.textStrokeWidth = insideRollback.textStrokeWidth;
        style.insideRollback = null;
    }
}

function getFont(opt, ecModel) {
    // ecModel or default text style model.
    var gTextStyleModel = ecModel || ecModel.getModel('textStyle');
    return trim([
        // FIXME in node-canvas fontWeight is before fontStyle
        opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '',
        opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '',
        (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px',
        opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'
    ].join(' '));
}

function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) {
    if (typeof dataIndex === 'function') {
        cb = dataIndex;
        dataIndex = null;
    }
    // Do not check 'animation' property directly here. Consider this case:
    // animation model is an `itemModel`, whose does not have `isAnimationEnabled`
    // but its parent model (`seriesModel`) does.
    var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();

    if (animationEnabled) {
        var postfix = isUpdate ? 'Update' : '';
        var duration = animatableModel.getShallow('animationDuration' + postfix);
        var animationEasing = animatableModel.getShallow('animationEasing' + postfix);
        var animationDelay = animatableModel.getShallow('animationDelay' + postfix);
        if (typeof animationDelay === 'function') {
            animationDelay = animationDelay(
                dataIndex,
                animatableModel.getAnimationDelayParams
                    ? animatableModel.getAnimationDelayParams(el, dataIndex)
                    : null
            );
        }
        if (typeof duration === 'function') {
            duration = duration(dataIndex);
        }

        duration > 0
            ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb, !!cb)
            : (el.stopAnimation(), el.attr(props), cb && cb());
    }
    else {
        el.stopAnimation();
        el.attr(props);
        cb && cb();
    }
}

/**
 * Update graphic element properties with or without animation according to the
 * configuration in series.
 *
 * Caution: this method will stop previous animation.
 * So if do not use this method to one element twice before
 * animation starts, unless you know what you are doing.
 *
 * @param {module:zrender/Element} el
 * @param {Object} props
 * @param {module:echarts/model/Model} [animatableModel]
 * @param {number} [dataIndex]
 * @param {Function} [cb]
 * @example
 *     graphic.updateProps(el, {
 *         position: [100, 100]
 *     }, seriesModel, dataIndex, function () { console.log('Animation done!'); });
 *     // Or
 *     graphic.updateProps(el, {
 *         position: [100, 100]
 *     }, seriesModel, function () { console.log('Animation done!'); });
 */
function updateProps(el, props, animatableModel, dataIndex, cb) {
    animateOrSetProps(true, el, props, animatableModel, dataIndex, cb);
}

/**
 * Init graphic element properties with or without animation according to the
 * configuration in series.
 *
 * Caution: this method will stop previous animation.
 * So if do not use this method to one element twice before
 * animation starts, unless you know what you are doing.
 *
 * @param {module:zrender/Element} el
 * @param {Object} props
 * @param {module:echarts/model/Model} [animatableModel]
 * @param {number} [dataIndex]
 * @param {Function} cb
 */
function initProps(el, props, animatableModel, dataIndex, cb) {
    animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);
}

/**
 * Get transform matrix of target (param target),
 * in coordinate of its ancestor (param ancestor)
 *
 * @param {module:zrender/mixin/Transformable} target
 * @param {module:zrender/mixin/Transformable} [ancestor]
 */
function getTransform(target, ancestor) {
    var mat = identity([]);

    while (target && target !== ancestor) {
        mul$1(mat, target.getLocalTransform(), mat);
        target = target.parent;
    }

    return mat;
}

/**
 * Apply transform to an vertex.
 * @param {Array.<number>} target [x, y]
 * @param {Array.<number>|TypedArray.<number>|Object} transform Can be:
 *      + Transform matrix: like [1, 0, 0, 1, 0, 0]
 *      + {position, rotation, scale}, the same as `zrender/Transformable`.
 * @param {boolean=} invert Whether use invert matrix.
 * @return {Array.<number>} [x, y]
 */
function applyTransform$1(target, transform, invert$$1) {
    if (transform && !isArrayLike(transform)) {
        transform = Transformable.getLocalTransform(transform);
    }

    if (invert$$1) {
        transform = invert([], transform);
    }
    return applyTransform([], target, transform);
}

/**
 * @param {string} direction 'left' 'right' 'top' 'bottom'
 * @param {Array.<number>} transform Transform matrix: like [1, 0, 0, 1, 0, 0]
 * @param {boolean=} invert Whether use invert matrix.
 * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom'
 */
function transformDirection(direction, transform, invert$$1) {

    // Pick a base, ensure that transform result will not be (0, 0).
    var hBase = (transform[4] === 0 || transform[5] === 0 || transform[0] === 0)
        ? 1 : Math.abs(2 * transform[4] / transform[0]);
    var vBase = (transform[4] === 0 || transform[5] === 0 || transform[2] === 0)
        ? 1 : Math.abs(2 * transform[4] / transform[2]);

    var vertex = [
        direction === 'left' ? -hBase : direction === 'right' ? hBase : 0,
        direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0
    ];

    vertex = applyTransform$1(vertex, transform, invert$$1);

    return Math.abs(vertex[0]) > Math.abs(vertex[1])
        ? (vertex[0] > 0 ? 'right' : 'left')
        : (vertex[1] > 0 ? 'bottom' : 'top');
}

/**
 * Apply group transition animation from g1 to g2.
 * If no animatableModel, no animation.
 */
function groupTransition(g1, g2, animatableModel, cb) {
    if (!g1 || !g2) {
        return;
    }

    function getElMap(g) {
        var elMap = {};
        g.traverse(function (el) {
            if (!el.isGroup && el.anid) {
                elMap[el.anid] = el;
            }
        });
        return elMap;
    }
    function getAnimatableProps(el) {
        var obj = {
            position: clone$1(el.position),
            rotation: el.rotation
        };
        if (el.shape) {
            obj.shape = extend({}, el.shape);
        }
        return obj;
    }
    var elMap1 = getElMap(g1);

    g2.traverse(function (el) {
        if (!el.isGroup && el.anid) {
            var oldEl = elMap1[el.anid];
            if (oldEl) {
                var newProp = getAnimatableProps(el);
                el.attr(getAnimatableProps(oldEl));
                updateProps(el, newProp, animatableModel, el.dataIndex);
            }
            // else {
            //     if (el.previousProps) {
            //         graphic.updateProps
            //     }
            // }
        }
    });
}

/**
 * @param {Array.<Array.<number>>} points Like: [[23, 44], [53, 66], ...]
 * @param {Object} rect {x, y, width, height}
 * @return {Array.<Array.<number>>} A new clipped points.
 */
function clipPointsByRect(points, rect) {
    // FIXME: this way migth be incorrect when grpahic clipped by a corner.
    // and when element have border.
    return map(points, function (point) {
        var x = point[0];
        x = mathMax$1(x, rect.x);
        x = mathMin$1(x, rect.x + rect.width);
        var y = point[1];
        y = mathMax$1(y, rect.y);
        y = mathMin$1(y, rect.y + rect.height);
        return [x, y];
    });
}

/**
 * @param {Object} targetRect {x, y, width, height}
 * @param {Object} rect {x, y, width, height}
 * @return {Object} A new clipped rect. If rect size are negative, return undefined.
 */
function clipRectByRect(targetRect, rect) {
    var x = mathMax$1(targetRect.x, rect.x);
    var x2 = mathMin$1(targetRect.x + targetRect.width, rect.x + rect.width);
    var y = mathMax$1(targetRect.y, rect.y);
    var y2 = mathMin$1(targetRect.y + targetRect.height, rect.y + rect.height);

    // If the total rect is cliped, nothing, including the border,
    // should be painted. So return undefined.
    if (x2 >= x && y2 >= y) {
        return {
            x: x,
            y: y,
            width: x2 - x,
            height: y2 - y
        };
    }
}

/**
 * @param {string} iconStr Support 'image://' or 'path://' or direct svg path.
 * @param {Object} [opt] Properties of `module:zrender/Element`, except `style`.
 * @param {Object} [rect] {x, y, width, height}
 * @return {module:zrender/Element} Icon path or image element.
 */
function createIcon(iconStr, opt, rect) {
    opt = extend({rectHover: true}, opt);
    var style = opt.style = {strokeNoScale: true};
    rect = rect || {x: -1, y: -1, width: 2, height: 2};

    if (iconStr) {
        return iconStr.indexOf('image://') === 0
            ? (
                style.image = iconStr.slice(8),
                defaults(style, rect),
                new ZImage(opt)
            )
            : (
                makePath(
                    iconStr.replace('path://', ''),
                    opt,
                    rect,
                    'center'
                )
            );
    }
}

/**
 * Return `true` if the given line (line `a`) and the given polygon
 * are intersect.
 * Note that we do not count colinear as intersect here because no
 * requirement for that. We could do that if required in future.
 *
 * @param {number} a1x
 * @param {number} a1y
 * @param {number} a2x
 * @param {number} a2y
 * @param {Array.<Array.<number>>} points Points of the polygon.
 * @return {boolean}
 */
function linePolygonIntersect(a1x, a1y, a2x, a2y, points) {
    for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {
        var p = points[i];
        if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) {
            return true;
        }
        p2 = p;
    }
}

/**
 * Return `true` if the given two lines (line `a` and line `b`)
 * are intersect.
 * Note that we do not count colinear as intersect here because no
 * requirement for that. We could do that if required in future.
 *
 * @param {number} a1x
 * @param {number} a1y
 * @param {number} a2x
 * @param {number} a2y
 * @param {number} b1x
 * @param {number} b1y
 * @param {number} b2x
 * @param {number} b2y
 * @return {boolean}
 */
function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {
    // let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`.
    var mx = a2x - a1x;
    var my = a2y - a1y;
    var nx = b2x - b1x;
    var ny = b2y - b1y;

    // `vec_m` and `vec_n` are parallel iff
    //     exising `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`.
    var nmCrossProduct = crossProduct2d(nx, ny, mx, my);
    if (nearZero(nmCrossProduct)) {
        return false;
    }

    // `vec_m` and `vec_n` are intersect iff
    //     existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`,
    //     such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)`
    //           and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`.
    var b1a1x = a1x - b1x;
    var b1a1y = a1y - b1y;
    var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct;
    if (q < 0 || q > 1) {
        return false;
    }
    var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct;
    if (p < 0 || p > 1) {
        return false;
    }

    return true;
}

/**
 * Cross product of 2-dimension vector.
 */
function crossProduct2d(x1, y1, x2, y2) {
    return x1 * y2 - x2 * y1;
}

function nearZero(val) {
    return val <= (1e-6) && val >= -(1e-6);
}

// Register built-in shapes. These shapes might be overwirtten
// by users, although we do not recommend that.
registerShape('circle', Circle);
registerShape('sector', Sector);
registerShape('ring', Ring);
registerShape('polygon', Polygon);
registerShape('polyline', Polyline);
registerShape('rect', Rect);
registerShape('line', Line);
registerShape('bezierCurve', BezierCurve);
registerShape('arc', Arc);




var graphic = (Object.freeze || Object)({
	Z2_EMPHASIS_LIFT: Z2_EMPHASIS_LIFT,
	CACHED_LABEL_STYLE_PROPERTIES: CACHED_LABEL_STYLE_PROPERTIES,
	extendShape: extendShape,
	extendPath: extendPath,
	registerShape: registerShape,
	getShapeClass: getShapeClass,
	makePath: makePath,
	makeImage: makeImage,
	mergePath: mergePath,
	resizePath: resizePath,
	subPixelOptimizeLine: subPixelOptimizeLine,
	subPixelOptimizeRect: subPixelOptimizeRect,
	subPixelOptimize: subPixelOptimize,
	setElementHoverStyle: setElementHoverStyle,
	setHoverStyle: setHoverStyle,
	setAsHighDownDispatcher: setAsHighDownDispatcher,
	isHighDownDispatcher: isHighDownDispatcher,
	getHighlightDigit: getHighlightDigit,
	setLabelStyle: setLabelStyle,
	modifyLabelStyle: modifyLabelStyle,
	setTextStyle: setTextStyle,
	setText: setText,
	getFont: getFont,
	updateProps: updateProps,
	initProps: initProps,
	getTransform: getTransform,
	applyTransform: applyTransform$1,
	transformDirection: transformDirection,
	groupTransition: groupTransition,
	clipPointsByRect: clipPointsByRect,
	clipRectByRect: clipRectByRect,
	createIcon: createIcon,
	linePolygonIntersect: linePolygonIntersect,
	lineLineIntersect: lineLineIntersect,
	Group: Group,
	Image: ZImage,
	Text: Text,
	Circle: Circle,
	Sector: Sector,
	Ring: Ring,
	Polygon: Polygon,
	Polyline: Polyline,
	Rect: Rect,
	Line: Line,
	BezierCurve: BezierCurve,
	Arc: Arc,
	IncrementalDisplayable: IncrementalDisplayble,
	CompoundPath: CompoundPath,
	LinearGradient: LinearGradient,
	RadialGradient: RadialGradient,
	BoundingRect: BoundingRect
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PATH_COLOR = ['textStyle', 'color'];

var textStyleMixin = {
    /**
     * Get color property or get color from option.textStyle.color
     * @param {boolean} [isEmphasis]
     * @return {string}
     */
    getTextColor: function (isEmphasis) {
        var ecModel = this.ecModel;
        return this.getShallow('color')
            || (
                (!isEmphasis && ecModel) ? ecModel.get(PATH_COLOR) : null
            );
    },

    /**
     * Create font string from fontStyle, fontWeight, fontSize, fontFamily
     * @return {string}
     */
    getFont: function () {
        return getFont({
            fontStyle: this.getShallow('fontStyle'),
            fontWeight: this.getShallow('fontWeight'),
            fontSize: this.getShallow('fontSize'),
            fontFamily: this.getShallow('fontFamily')
        }, this.ecModel);
    },

    getTextRect: function (text) {
        return getBoundingRect(
            text,
            this.getFont(),
            this.getShallow('align'),
            this.getShallow('verticalAlign') || this.getShallow('baseline'),
            this.getShallow('padding'),
            this.getShallow('lineHeight'),
            this.getShallow('rich'),
            this.getShallow('truncateText')
        );
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var getItemStyle = makeStyleMapper(
    [
        ['fill', 'color'],
        ['stroke', 'borderColor'],
        ['lineWidth', 'borderWidth'],
        ['opacity'],
        ['shadowBlur'],
        ['shadowOffsetX'],
        ['shadowOffsetY'],
        ['shadowColor'],
        ['textPosition'],
        ['textAlign']
    ]
);

var itemStyleMixin = {
    getItemStyle: function (excludes, includes) {
        var style = getItemStyle(this, excludes, includes);
        var lineDash = this.getBorderLineDash();
        lineDash && (style.lineDash = lineDash);
        return style;
    },

    getBorderLineDash: function () {
        var lineType = this.get('borderType');
        return (lineType === 'solid' || lineType == null) ? null
            : (lineType === 'dashed' ? [5, 5] : [1, 1]);
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/model/Model
 */

var mixin$1 = mixin;
var inner = makeInner();

/**
 * @alias module:echarts/model/Model
 * @constructor
 * @param {Object} [option]
 * @param {module:echarts/model/Model} [parentModel]
 * @param {module:echarts/model/Global} [ecModel]
 */
function Model(option, parentModel, ecModel) {
    /**
     * @type {module:echarts/model/Model}
     * @readOnly
     */
    this.parentModel = parentModel;

    /**
     * @type {module:echarts/model/Global}
     * @readOnly
     */
    this.ecModel = ecModel;

    /**
     * @type {Object}
     * @protected
     */
    this.option = option;

    // Simple optimization
    // if (this.init) {
    //     if (arguments.length <= 4) {
    //         this.init(option, parentModel, ecModel, extraOpt);
    //     }
    //     else {
    //         this.init.apply(this, arguments);
    //     }
    // }
}

Model.prototype = {

    constructor: Model,

    /**
     * Model 的初始化函数
     * @param {Object} option
     */
    init: null,

    /**
     * 从新的 Option merge
     */
    mergeOption: function (option) {
        merge(this.option, option, true);
    },

    /**
     * @param {string|Array.<string>} path
     * @param {boolean} [ignoreParent=false]
     * @return {*}
     */
    get: function (path, ignoreParent) {
        if (path == null) {
            return this.option;
        }

        return doGet(
            this.option,
            this.parsePath(path),
            !ignoreParent && getParent(this, path)
        );
    },

    /**
     * @param {string} key
     * @param {boolean} [ignoreParent=false]
     * @return {*}
     */
    getShallow: function (key, ignoreParent) {
        var option = this.option;

        var val = option == null ? option : option[key];
        var parentModel = !ignoreParent && getParent(this, key);
        if (val == null && parentModel) {
            val = parentModel.getShallow(key);
        }
        return val;
    },

    /**
     * @param {string|Array.<string>} [path]
     * @param {module:echarts/model/Model} [parentModel]
     * @return {module:echarts/model/Model}
     */
    getModel: function (path, parentModel) {
        var obj = path == null
            ? this.option
            : doGet(this.option, path = this.parsePath(path));

        var thisParentModel;
        parentModel = parentModel || (
            (thisParentModel = getParent(this, path))
                && thisParentModel.getModel(path)
        );

        return new Model(obj, parentModel, this.ecModel);
    },

    /**
     * If model has option
     */
    isEmpty: function () {
        return this.option == null;
    },

    restoreData: function () {},

    // Pending
    clone: function () {
        var Ctor = this.constructor;
        return new Ctor(clone(this.option));
    },

    setReadOnly: function (properties) {
        // clazzUtil.setReadOnly(this, properties);
    },

    // If path is null/undefined, return null/undefined.
    parsePath: function (path) {
        if (typeof path === 'string') {
            path = path.split('.');
        }
        return path;
    },

    /**
     * @param {Function} getParentMethod
     *        param {Array.<string>|string} path
     *        return {module:echarts/model/Model}
     */
    customizeGetParent: function (getParentMethod) {
        inner(this).getParent = getParentMethod;
    },

    isAnimationEnabled: function () {
        if (!env$1.node) {
            if (this.option.animation != null) {
                return !!this.option.animation;
            }
            else if (this.parentModel) {
                return this.parentModel.isAnimationEnabled();
            }
        }
    }

};

function doGet(obj, pathArr, parentModel) {
    for (var i = 0; i < pathArr.length; i++) {
        // Ignore empty
        if (!pathArr[i]) {
            continue;
        }
        // obj could be number/string/... (like 0)
        obj = (obj && typeof obj === 'object') ? obj[pathArr[i]] : null;
        if (obj == null) {
            break;
        }
    }
    if (obj == null && parentModel) {
        obj = parentModel.get(pathArr);
    }
    return obj;
}

// `path` can be null/undefined
function getParent(model, path) {
    var getParentMethod = inner(model).getParent;
    return getParentMethod ? getParentMethod.call(model, path) : model.parentModel;
}

// Enable Model.extend.
enableClassExtend(Model);
enableClassCheck(Model);

mixin$1(Model, lineStyleMixin);
mixin$1(Model, areaStyleMixin);
mixin$1(Model, textStyleMixin);
mixin$1(Model, itemStyleMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var base = 0;

/**
 * @public
 * @param {string} type
 * @return {string}
 */
function getUID(type) {
    // Considering the case of crossing js context,
    // use Math.random to make id as unique as possible.
    return [(type || ''), base++, Math.random().toFixed(5)].join('_');
}

/**
 * @inner
 */
function enableSubTypeDefaulter(entity) {

    var subTypeDefaulters = {};

    entity.registerSubTypeDefaulter = function (componentType, defaulter) {
        componentType = parseClassType$1(componentType);
        subTypeDefaulters[componentType.main] = defaulter;
    };

    entity.determineSubType = function (componentType, option) {
        var type = option.type;
        if (!type) {
            var componentTypeMain = parseClassType$1(componentType).main;
            if (entity.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) {
                type = subTypeDefaulters[componentTypeMain](option);
            }
        }
        return type;
    };

    return entity;
}

/**
 * Topological travel on Activity Network (Activity On Vertices).
 * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
 *
 * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
 *
 * If there is circle dependencey, Error will be thrown.
 *
 */
function enableTopologicalTravel(entity, dependencyGetter) {

    /**
     * @public
     * @param {Array.<string>} targetNameList Target Component type list.
     *                                           Can be ['aa', 'bb', 'aa.xx']
     * @param {Array.<string>} fullNameList By which we can build dependency graph.
     * @param {Function} callback Params: componentType, dependencies.
     * @param {Object} context Scope of callback.
     */
    entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) {
        if (!targetNameList.length) {
            return;
        }

        var result = makeDepndencyGraph(fullNameList);
        var graph = result.graph;
        var stack = result.noEntryList;

        var targetNameSet = {};
        each$1(targetNameList, function (name) {
            targetNameSet[name] = true;
        });

        while (stack.length) {
            var currComponentType = stack.pop();
            var currVertex = graph[currComponentType];
            var isInTargetNameSet = !!targetNameSet[currComponentType];
            if (isInTargetNameSet) {
                callback.call(context, currComponentType, currVertex.originalDeps.slice());
                delete targetNameSet[currComponentType];
            }
            each$1(
                currVertex.successor,
                isInTargetNameSet ? removeEdgeAndAdd : removeEdge
            );
        }

        each$1(targetNameSet, function () {
            throw new Error('Circle dependency may exists');
        });

        function removeEdge(succComponentType) {
            graph[succComponentType].entryCount--;
            if (graph[succComponentType].entryCount === 0) {
                stack.push(succComponentType);
            }
        }

        // Consider this case: legend depends on series, and we call
        // chart.setOption({series: [...]}), where only series is in option.
        // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will
        // not be called, but only sereis.mergeOption is called. Thus legend
        // have no chance to update its local record about series (like which
        // name of series is available in legend).
        function removeEdgeAndAdd(succComponentType) {
            targetNameSet[succComponentType] = true;
            removeEdge(succComponentType);
        }
    };

    /**
     * DepndencyGraph: {Object}
     * key: conponentType,
     * value: {
     *     successor: [conponentTypes...],
     *     originalDeps: [conponentTypes...],
     *     entryCount: {number}
     * }
     */
    function makeDepndencyGraph(fullNameList) {
        var graph = {};
        var noEntryList = [];

        each$1(fullNameList, function (name) {

            var thisItem = createDependencyGraphItem(graph, name);
            var originalDeps = thisItem.originalDeps = dependencyGetter(name);

            var availableDeps = getAvailableDependencies(originalDeps, fullNameList);
            thisItem.entryCount = availableDeps.length;
            if (thisItem.entryCount === 0) {
                noEntryList.push(name);
            }

            each$1(availableDeps, function (dependentName) {
                if (indexOf(thisItem.predecessor, dependentName) < 0) {
                    thisItem.predecessor.push(dependentName);
                }
                var thatItem = createDependencyGraphItem(graph, dependentName);
                if (indexOf(thatItem.successor, dependentName) < 0) {
                    thatItem.successor.push(name);
                }
            });
        });

        return {graph: graph, noEntryList: noEntryList};
    }

    function createDependencyGraphItem(graph, name) {
        if (!graph[name]) {
            graph[name] = {predecessor: [], successor: []};
        }
        return graph[name];
    }

    function getAvailableDependencies(originalDeps, fullNameList) {
        var availableDeps = [];
        each$1(originalDeps, function (dep) {
            indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep);
        });
        return availableDeps;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* A third-party license is embeded for some of the code in this file:
* The method "quantile" was copied from "d3.js".
* (See more details in the comment of the method below.)
* The use of the source code of this file is also subject to the terms
* and consitions of the license of "d3.js" (BSD-3Clause, see
* </licenses/LICENSE-d3>).
*/

var RADIAN_EPSILON = 1e-4;

function _trim(str) {
    return str.replace(/^\s+|\s+$/g, '');
}

/**
 * Linear mapping a value from domain to range
 * @memberOf module:echarts/util/number
 * @param  {(number|Array.<number>)} val
 * @param  {Array.<number>} domain Domain extent domain[0] can be bigger than domain[1]
 * @param  {Array.<number>} range  Range extent range[0] can be bigger than range[1]
 * @param  {boolean} clamp
 * @return {(number|Array.<number>}
 */
function linearMap(val, domain, range, clamp) {
    var subDomain = domain[1] - domain[0];
    var subRange = range[1] - range[0];

    if (subDomain === 0) {
        return subRange === 0
            ? range[0]
            : (range[0] + range[1]) / 2;
    }

    // Avoid accuracy problem in edge, such as
    // 146.39 - 62.83 === 83.55999999999999.
    // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError
    // It is a little verbose for efficiency considering this method
    // is a hotspot.
    if (clamp) {
        if (subDomain > 0) {
            if (val <= domain[0]) {
                return range[0];
            }
            else if (val >= domain[1]) {
                return range[1];
            }
        }
        else {
            if (val >= domain[0]) {
                return range[0];
            }
            else if (val <= domain[1]) {
                return range[1];
            }
        }
    }
    else {
        if (val === domain[0]) {
            return range[0];
        }
        if (val === domain[1]) {
            return range[1];
        }
    }

    return (val - domain[0]) / subDomain * subRange + range[0];
}

/**
 * Convert a percent string to absolute number.
 * Returns NaN if percent is not a valid string or number
 * @memberOf module:echarts/util/number
 * @param {string|number} percent
 * @param {number} all
 * @return {number}
 */
function parsePercent$1(percent, all) {
    switch (percent) {
        case 'center':
        case 'middle':
            percent = '50%';
            break;
        case 'left':
        case 'top':
            percent = '0%';
            break;
        case 'right':
        case 'bottom':
            percent = '100%';
            break;
    }
    if (typeof percent === 'string') {
        if (_trim(percent).match(/%$/)) {
            return parseFloat(percent) / 100 * all;
        }

        return parseFloat(percent);
    }

    return percent == null ? NaN : +percent;
}

/**
 * (1) Fix rounding error of float numbers.
 * (2) Support return string to avoid scientific notation like '3.5e-7'.
 *
 * @param {number} x
 * @param {number} [precision]
 * @param {boolean} [returnStr]
 * @return {number|string}
 */
function round$1(x, precision, returnStr) {
    if (precision == null) {
        precision = 10;
    }
    // Avoid range error
    precision = Math.min(Math.max(0, precision), 20);
    x = (+x).toFixed(precision);
    return returnStr ? x : +x;
}

/**
 * asc sort arr.
 * The input arr will be modified.
 *
 * @param {Array} arr
 * @return {Array} The input arr.
 */
function asc(arr) {
    arr.sort(function (a, b) {
        return a - b;
    });
    return arr;
}

/**
 * Get precision
 * @param {number} val
 */
function getPrecision(val) {
    val = +val;
    if (isNaN(val)) {
        return 0;
    }
    // It is much faster than methods converting number to string as follows
    //      var tmp = val.toString();
    //      return tmp.length - 1 - tmp.indexOf('.');
    // especially when precision is low
    var e = 1;
    var count = 0;
    while (Math.round(val * e) / e !== val) {
        e *= 10;
        count++;
    }
    return count;
}

/**
 * @param {string|number} val
 * @return {number}
 */
function getPrecisionSafe(val) {
    var str = val.toString();

    // Consider scientific notation: '3.4e-12' '3.4e+12'
    var eIndex = str.indexOf('e');
    if (eIndex > 0) {
        var precision = +str.slice(eIndex + 1);
        return precision < 0 ? -precision : 0;
    }
    else {
        var dotIndex = str.indexOf('.');
        return dotIndex < 0 ? 0 : str.length - 1 - dotIndex;
    }
}

/**
 * Minimal dicernible data precisioin according to a single pixel.
 *
 * @param {Array.<number>} dataExtent
 * @param {Array.<number>} pixelExtent
 * @return {number} precision
 */
function getPixelPrecision(dataExtent, pixelExtent) {
    var log = Math.log;
    var LN10 = Math.LN10;
    var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
    var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10);
    // toFixed() digits argument must be between 0 and 20.
    var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20);
    return !isFinite(precision) ? 20 : precision;
}

/**
 * Get a data of given precision, assuring the sum of percentages
 * in valueList is 1.
 * The largest remainer method is used.
 * https://en.wikipedia.org/wiki/Largest_remainder_method
 *
 * @param {Array.<number>} valueList a list of all data
 * @param {number} idx index of the data to be processed in valueList
 * @param {number} precision integer number showing digits of precision
 * @return {number} percent ranging from 0 to 100
 */
function getPercentWithPrecision(valueList, idx, precision) {
    if (!valueList[idx]) {
        return 0;
    }

    var sum = reduce(valueList, function (acc, val) {
        return acc + (isNaN(val) ? 0 : val);
    }, 0);
    if (sum === 0) {
        return 0;
    }

    var digits = Math.pow(10, precision);
    var votesPerQuota = map(valueList, function (val) {
        return (isNaN(val) ? 0 : val) / sum * digits * 100;
    });
    var targetSeats = digits * 100;

    var seats = map(votesPerQuota, function (votes) {
        // Assign automatic seats.
        return Math.floor(votes);
    });
    var currentSum = reduce(seats, function (acc, val) {
        return acc + val;
    }, 0);

    var remainder = map(votesPerQuota, function (votes, idx) {
        return votes - seats[idx];
    });

    // Has remainding votes.
    while (currentSum < targetSeats) {
        // Find next largest remainder.
        var max = Number.NEGATIVE_INFINITY;
        var maxId = null;
        for (var i = 0, len = remainder.length; i < len; ++i) {
            if (remainder[i] > max) {
                max = remainder[i];
                maxId = i;
            }
        }

        // Add a vote to max remainder.
        ++seats[maxId];
        remainder[maxId] = 0;
        ++currentSum;
    }

    return seats[idx] / digits;
}

// Number.MAX_SAFE_INTEGER, ie do not support.
var MAX_SAFE_INTEGER = 9007199254740991;

/**
 * To 0 - 2 * PI, considering negative radian.
 * @param {number} radian
 * @return {number}
 */
function remRadian(radian) {
    var pi2 = Math.PI * 2;
    return (radian % pi2 + pi2) % pi2;
}

/**
 * @param {type} radian
 * @return {boolean}
 */
function isRadianAroundZero(val) {
    return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
}

/* eslint-disable */
var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line
/* eslint-enable */

/**
 * @param {string|Date|number} value These values can be accepted:
 *   + An instance of Date, represent a time in its own time zone.
 *   + Or string in a subset of ISO 8601, only including:
 *     + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',
 *     + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123',
 *     + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00',
 *     all of which will be treated as local time if time zone is not specified
 *     (see <https://momentjs.com/>).
 *   + Or other string format, including (all of which will be treated as loacal time):
 *     '2012', '2012-3-1', '2012/3/1', '2012/03/01',
 *     '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'
 *   + a timestamp, which represent a time in UTC.
 * @return {Date} date
 */
function parseDate(value) {
    if (value instanceof Date) {
        return value;
    }
    else if (typeof value === 'string') {
        // Different browsers parse date in different way, so we parse it manually.
        // Some other issues:
        // new Date('1970-01-01') is UTC,
        // new Date('1970/01/01') and new Date('1970-1-01') is local.
        // See issue #3623
        var match = TIME_REG.exec(value);

        if (!match) {
            // return Invalid Date.
            return new Date(NaN);
        }

        // Use local time when no timezone offset specifed.
        if (!match[8]) {
            // match[n] can only be string or undefined.
            // But take care of '12' + 1 => '121'.
            return new Date(
                +match[1],
                +(match[2] || 1) - 1,
                +match[3] || 1,
                +match[4] || 0,
                +(match[5] || 0),
                +match[6] || 0,
                +match[7] || 0
            );
        }
        // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time,
        // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment).
        // For example, system timezone is set as "Time Zone: America/Toronto",
        // then these code will get different result:
        // `new Date(1478411999999).getTimezoneOffset();  // get 240`
        // `new Date(1478412000000).getTimezoneOffset();  // get 300`
        // So we should not use `new Date`, but use `Date.UTC`.
        else {
            var hour = +match[4] || 0;
            if (match[8].toUpperCase() !== 'Z') {
                hour -= match[8].slice(0, 3);
            }
            return new Date(Date.UTC(
                +match[1],
                +(match[2] || 1) - 1,
                +match[3] || 1,
                hour,
                +(match[5] || 0),
                +match[6] || 0,
                +match[7] || 0
            ));
        }
    }
    else if (value == null) {
        return new Date(NaN);
    }

    return new Date(Math.round(value));
}

/**
 * Quantity of a number. e.g. 0.1, 1, 10, 100
 *
 * @param  {number} val
 * @return {number}
 */
function quantity(val) {
    return Math.pow(10, quantityExponent(val));
}

/**
 * Exponent of the quantity of a number
 * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3
 *
 * @param  {number} val non-negative value
 * @return {number}
 */
function quantityExponent(val) {
    if (val === 0) {
        return 0;
    }

    var exp = Math.floor(Math.log(val) / Math.LN10);
    /**
     * exp is expected to be the rounded-down result of the base-10 log of val.
     * But due to the precision loss with Math.log(val), we need to restore it
     * using 10^exp to make sure we can get val back from exp. #11249
     */
    if (val / Math.pow(10, exp) >= 10) {
        exp++;
    }
    return exp;
}

/**
 * find a “nice” number approximately equal to x. Round the number if round = true,
 * take ceiling if round = false. The primary observation is that the “nicest”
 * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers.
 *
 * See "Nice Numbers for Graph Labels" of Graphic Gems.
 *
 * @param  {number} val Non-negative value.
 * @param  {boolean} round
 * @return {number}
 */
function nice(val, round) {
    var exponent = quantityExponent(val);
    var exp10 = Math.pow(10, exponent);
    var f = val / exp10; // 1 <= f < 10
    var nf;
    if (round) {
        if (f < 1.5) {
            nf = 1;
        }
        else if (f < 2.5) {
            nf = 2;
        }
        else if (f < 4) {
            nf = 3;
        }
        else if (f < 7) {
            nf = 5;
        }
        else {
            nf = 10;
        }
    }
    else {
        if (f < 1) {
            nf = 1;
        }
        else if (f < 2) {
            nf = 2;
        }
        else if (f < 3) {
            nf = 3;
        }
        else if (f < 5) {
            nf = 5;
        }
        else {
            nf = 10;
        }
    }
    val = nf * exp10;

    // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
    // 20 is the uppper bound of toFixed.
    return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
}

/**
 * This code was copied from "d3.js"
 * <https://github.com/d3/d3/blob/9cc9a875e636a1dcf36cc1e07bdf77e1ad6e2c74/src/arrays/quantile.js>.
 * See the license statement at the head of this file.
 * @param {Array.<number>} ascArr
 */
function quantile(ascArr, p) {
    var H = (ascArr.length - 1) * p + 1;
    var h = Math.floor(H);
    var v = +ascArr[h - 1];
    var e = H - h;
    return e ? v + e * (ascArr[h] - v) : v;
}

/**
 * Order intervals asc, and split them when overlap.
 * expect(numberUtil.reformIntervals([
 *     {interval: [18, 62], close: [1, 1]},
 *     {interval: [-Infinity, -70], close: [0, 0]},
 *     {interval: [-70, -26], close: [1, 1]},
 *     {interval: [-26, 18], close: [1, 1]},
 *     {interval: [62, 150], close: [1, 1]},
 *     {interval: [106, 150], close: [1, 1]},
 *     {interval: [150, Infinity], close: [0, 0]}
 * ])).toEqual([
 *     {interval: [-Infinity, -70], close: [0, 0]},
 *     {interval: [-70, -26], close: [1, 1]},
 *     {interval: [-26, 18], close: [0, 1]},
 *     {interval: [18, 62], close: [0, 1]},
 *     {interval: [62, 150], close: [0, 1]},
 *     {interval: [150, Infinity], close: [0, 0]}
 * ]);
 * @param {Array.<Object>} list, where `close` mean open or close
 *        of the interval, and Infinity can be used.
 * @return {Array.<Object>} The origin list, which has been reformed.
 */
function reformIntervals(list) {
    list.sort(function (a, b) {
        return littleThan(a, b, 0) ? -1 : 1;
    });

    var curr = -Infinity;
    var currClose = 1;
    for (var i = 0; i < list.length;) {
        var interval = list[i].interval;
        var close = list[i].close;

        for (var lg = 0; lg < 2; lg++) {
            if (interval[lg] <= curr) {
                interval[lg] = curr;
                close[lg] = !lg ? 1 - currClose : 1;
            }
            curr = interval[lg];
            currClose = close[lg];
        }

        if (interval[0] === interval[1] && close[0] * close[1] !== 1) {
            list.splice(i, 1);
        }
        else {
            i++;
        }
    }

    return list;

    function littleThan(a, b, lg) {
        return a.interval[lg] < b.interval[lg]
            || (
                a.interval[lg] === b.interval[lg]
                && (
                    (a.close[lg] - b.close[lg] === (!lg ? 1 : -1))
                    || (!lg && littleThan(a, b, 1))
                )
            );
    }
}

/**
 * parseFloat NaNs numeric-cast false positives (null|true|false|"")
 * ...but misinterprets leading-number strings, particularly hex literals ("0x...")
 * subtraction forces infinities to NaN
 *
 * @param {*} v
 * @return {boolean}
 */
function isNumeric(v) {
    return v - parseFloat(v) >= 0;
}


var number = (Object.freeze || Object)({
	linearMap: linearMap,
	parsePercent: parsePercent$1,
	round: round$1,
	asc: asc,
	getPrecision: getPrecision,
	getPrecisionSafe: getPrecisionSafe,
	getPixelPrecision: getPixelPrecision,
	getPercentWithPrecision: getPercentWithPrecision,
	MAX_SAFE_INTEGER: MAX_SAFE_INTEGER,
	remRadian: remRadian,
	isRadianAroundZero: isRadianAroundZero,
	parseDate: parseDate,
	quantity: quantity,
	quantityExponent: quantityExponent,
	nice: nice,
	quantile: quantile,
	reformIntervals: reformIntervals,
	isNumeric: isNumeric
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// import Text from 'zrender/src/graphic/Text';

/**
 * 每三位默认加,格式化
 * @param {string|number} x
 * @return {string}
 */
function addCommas(x) {
    if (isNaN(x)) {
        return '-';
    }
    x = (x + '').split('.');
    return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,')
            + (x.length > 1 ? ('.' + x[1]) : '');
}

/**
 * @param {string} str
 * @param {boolean} [upperCaseFirst=false]
 * @return {string} str
 */
function toCamelCase(str, upperCaseFirst) {
    str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) {
        return group1.toUpperCase();
    });

    if (upperCaseFirst && str) {
        str = str.charAt(0).toUpperCase() + str.slice(1);
    }

    return str;
}

var normalizeCssArray$1 = normalizeCssArray;


var replaceReg = /([&<>"'])/g;
var replaceMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    '\'': '&#39;'
};

function encodeHTML(source) {
    return source == null
        ? ''
        : (source + '').replace(replaceReg, function (str, c) {
            return replaceMap[c];
        });
}

var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

var wrapVar = function (varName, seriesIdx) {
    return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
};

/**
 * Template formatter
 * @param {string} tpl
 * @param {Array.<Object>|Object} paramsList
 * @param {boolean} [encode=false]
 * @return {string}
 */
function formatTpl(tpl, paramsList, encode) {
    if (!isArray(paramsList)) {
        paramsList = [paramsList];
    }
    var seriesLen = paramsList.length;
    if (!seriesLen) {
        return '';
    }

    var $vars = paramsList[0].$vars || [];
    for (var i = 0; i < $vars.length; i++) {
        var alias = TPL_VAR_ALIAS[i];
        tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0));
    }
    for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
        for (var k = 0; k < $vars.length; k++) {
            var val = paramsList[seriesIdx][$vars[k]];
            tpl = tpl.replace(
                wrapVar(TPL_VAR_ALIAS[k], seriesIdx),
                encode ? encodeHTML(val) : val
            );
        }
    }

    return tpl;
}

/**
 * simple Template formatter
 *
 * @param {string} tpl
 * @param {Object} param
 * @param {boolean} [encode=false]
 * @return {string}
 */
function formatTplSimple(tpl, param, encode) {
    each$1(param, function (value, key) {
        tpl = tpl.replace(
            '{' + key + '}',
            encode ? encodeHTML(value) : value
        );
    });
    return tpl;
}

/**
 * @param {Object|string} [opt] If string, means color.
 * @param {string} [opt.color]
 * @param {string} [opt.extraCssText]
 * @param {string} [opt.type='item'] 'item' or 'subItem'
 * @param {string} [opt.renderMode='html'] render mode of tooltip, 'html' or 'richText'
 * @param {string} [opt.markerId='X'] id name for marker. If only one marker is in a rich text, this can be omitted.
 * @return {string}
 */
function getTooltipMarker(opt, extraCssText) {
    opt = isString(opt) ? {color: opt, extraCssText: extraCssText} : (opt || {});
    var color = opt.color;
    var type = opt.type;
    var extraCssText = opt.extraCssText;
    var renderMode = opt.renderMode || 'html';
    var markerId = opt.markerId || 'X';

    if (!color) {
        return '';
    }

    if (renderMode === 'html') {
        return type === 'subItem'
        ? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;'
            + 'border-radius:4px;width:4px;height:4px;background-color:'
            + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>'
        : '<span style="display:inline-block;margin-right:5px;'
            + 'border-radius:10px;width:10px;height:10px;background-color:'
            + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>';
    }
    else {
        // Space for rich element marker
        return {
            renderMode: renderMode,
            content: '{marker' + markerId + '|}  ',
            style: {
                color: color
            }
        };
    }
}

function pad(str, len) {
    str += '';
    return '0000'.substr(0, len - str.length) + str;
}


/**
 * ISO Date format
 * @param {string} tpl
 * @param {number} value
 * @param {boolean} [isUTC=false] Default in local time.
 *           see `module:echarts/scale/Time`
 *           and `module:echarts/util/number#parseDate`.
 * @inner
 */
function formatTime(tpl, value, isUTC) {
    if (tpl === 'week'
        || tpl === 'month'
        || tpl === 'quarter'
        || tpl === 'half-year'
        || tpl === 'year'
    ) {
        tpl = 'MM-dd\nyyyy';
    }

    var date = parseDate(value);
    var utc = isUTC ? 'UTC' : '';
    var y = date['get' + utc + 'FullYear']();
    var M = date['get' + utc + 'Month']() + 1;
    var d = date['get' + utc + 'Date']();
    var h = date['get' + utc + 'Hours']();
    var m = date['get' + utc + 'Minutes']();
    var s = date['get' + utc + 'Seconds']();
    var S = date['get' + utc + 'Milliseconds']();

    tpl = tpl.replace('MM', pad(M, 2))
        .replace('M', M)
        .replace('yyyy', y)
        .replace('yy', y % 100)
        .replace('dd', pad(d, 2))
        .replace('d', d)
        .replace('hh', pad(h, 2))
        .replace('h', h)
        .replace('mm', pad(m, 2))
        .replace('m', m)
        .replace('ss', pad(s, 2))
        .replace('s', s)
        .replace('SSS', pad(S, 3));

    return tpl;
}

/**
 * Capital first
 * @param {string} str
 * @return {string}
 */
function capitalFirst(str) {
    return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
}

var truncateText$1 = truncateText;

/**
 * @public
 * @param {Object} opt
 * @param {string} opt.text
 * @param {string} opt.font
 * @param {string} [opt.textAlign='left']
 * @param {string} [opt.textVerticalAlign='top']
 * @param {Array.<number>} [opt.textPadding]
 * @param {number} [opt.textLineHeight]
 * @param {Object} [opt.rich]
 * @param {Object} [opt.truncate]
 * @return {Object} {x, y, width, height, lineHeight}
 */
function getTextBoundingRect(opt) {
    return getBoundingRect(
        opt.text,
        opt.font,
        opt.textAlign,
        opt.textVerticalAlign,
        opt.textPadding,
        opt.textLineHeight,
        opt.rich,
        opt.truncate
    );
}

/**
 * @deprecated
 * the `textLineHeight` was added later.
 * For backward compatiblility, put it as the last parameter.
 * But deprecated this interface. Please use `getTextBoundingRect` instead.
 */
function getTextRect(
    text, font, textAlign, textVerticalAlign, textPadding, rich, truncate, textLineHeight
) {
    return getBoundingRect(
        text, font, textAlign, textVerticalAlign, textPadding, textLineHeight, rich, truncate
    );
}


var format = (Object.freeze || Object)({
	addCommas: addCommas,
	toCamelCase: toCamelCase,
	normalizeCssArray: normalizeCssArray$1,
	encodeHTML: encodeHTML,
	formatTpl: formatTpl,
	formatTplSimple: formatTplSimple,
	getTooltipMarker: getTooltipMarker,
	formatTime: formatTime,
	capitalFirst: capitalFirst,
	truncateText: truncateText$1,
	getTextBoundingRect: getTextBoundingRect,
	getTextRect: getTextRect
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Layout helpers for each component positioning

var each$3 = each$1;

/**
 * @public
 */
var LOCATION_PARAMS = [
    'left', 'right', 'top', 'bottom', 'width', 'height'
];

/**
 * @public
 */
var HV_NAMES = [
    ['width', 'left', 'right'],
    ['height', 'top', 'bottom']
];

function boxLayout(orient, group, gap, maxWidth, maxHeight) {
    var x = 0;
    var y = 0;

    if (maxWidth == null) {
        maxWidth = Infinity;
    }
    if (maxHeight == null) {
        maxHeight = Infinity;
    }
    var currentLineMaxSize = 0;

    group.eachChild(function (child, idx) {
        var position = child.position;
        var rect = child.getBoundingRect();
        var nextChild = group.childAt(idx + 1);
        var nextChildRect = nextChild && nextChild.getBoundingRect();
        var nextX;
        var nextY;

        if (orient === 'horizontal') {
            var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0);
            nextX = x + moveX;
            // Wrap when width exceeds maxWidth or meet a `newline` group
            // FIXME compare before adding gap?
            if (nextX > maxWidth || child.newline) {
                x = 0;
                nextX = moveX;
                y += currentLineMaxSize + gap;
                currentLineMaxSize = rect.height;
            }
            else {
                // FIXME: consider rect.y is not `0`?
                currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
            }
        }
        else {
            var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);
            nextY = y + moveY;
            // Wrap when width exceeds maxHeight or meet a `newline` group
            if (nextY > maxHeight || child.newline) {
                x += currentLineMaxSize + gap;
                y = 0;
                nextY = moveY;
                currentLineMaxSize = rect.width;
            }
            else {
                currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
            }
        }

        if (child.newline) {
            return;
        }

        position[0] = x;
        position[1] = y;

        orient === 'horizontal'
            ? (x = nextX + gap)
            : (y = nextY + gap);
    });
}

/**
 * VBox or HBox layouting
 * @param {string} orient
 * @param {module:zrender/container/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */
var box = boxLayout;

/**
 * VBox layouting
 * @param {module:zrender/container/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */
var vbox = curry(boxLayout, 'vertical');

/**
 * HBox layouting
 * @param {module:zrender/container/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */
var hbox = curry(boxLayout, 'horizontal');

/**
 * If x or x2 is not specified or 'center' 'left' 'right',
 * the width would be as long as possible.
 * If y or y2 is not specified or 'middle' 'top' 'bottom',
 * the height would be as long as possible.
 *
 * @param {Object} positionInfo
 * @param {number|string} [positionInfo.x]
 * @param {number|string} [positionInfo.y]
 * @param {number|string} [positionInfo.x2]
 * @param {number|string} [positionInfo.y2]
 * @param {Object} containerRect {width, height}
 * @param {string|number} margin
 * @return {Object} {width, height}
 */
function getAvailableSize(positionInfo, containerRect, margin) {
    var containerWidth = containerRect.width;
    var containerHeight = containerRect.height;

    var x = parsePercent$1(positionInfo.x, containerWidth);
    var y = parsePercent$1(positionInfo.y, containerHeight);
    var x2 = parsePercent$1(positionInfo.x2, containerWidth);
    var y2 = parsePercent$1(positionInfo.y2, containerHeight);

    (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0);
    (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth);
    (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0);
    (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight);

    margin = normalizeCssArray$1(margin || 0);

    return {
        width: Math.max(x2 - x - margin[1] - margin[3], 0),
        height: Math.max(y2 - y - margin[0] - margin[2], 0)
    };
}

/**
 * Parse position info.
 *
 * @param {Object} positionInfo
 * @param {number|string} [positionInfo.left]
 * @param {number|string} [positionInfo.top]
 * @param {number|string} [positionInfo.right]
 * @param {number|string} [positionInfo.bottom]
 * @param {number|string} [positionInfo.width]
 * @param {number|string} [positionInfo.height]
 * @param {number|string} [positionInfo.aspect] Aspect is width / height
 * @param {Object} containerRect
 * @param {string|number} [margin]
 *
 * @return {module:zrender/core/BoundingRect}
 */
function getLayoutRect(
    positionInfo, containerRect, margin
) {
    margin = normalizeCssArray$1(margin || 0);

    var containerWidth = containerRect.width;
    var containerHeight = containerRect.height;

    var left = parsePercent$1(positionInfo.left, containerWidth);
    var top = parsePercent$1(positionInfo.top, containerHeight);
    var right = parsePercent$1(positionInfo.right, containerWidth);
    var bottom = parsePercent$1(positionInfo.bottom, containerHeight);
    var width = parsePercent$1(positionInfo.width, containerWidth);
    var height = parsePercent$1(positionInfo.height, containerHeight);

    var verticalMargin = margin[2] + margin[0];
    var horizontalMargin = margin[1] + margin[3];
    var aspect = positionInfo.aspect;

    // If width is not specified, calculate width from left and right
    if (isNaN(width)) {
        width = containerWidth - right - horizontalMargin - left;
    }
    if (isNaN(height)) {
        height = containerHeight - bottom - verticalMargin - top;
    }

    if (aspect != null) {
        // If width and height are not given
        // 1. Graph should not exceeds the container
        // 2. Aspect must be keeped
        // 3. Graph should take the space as more as possible
        // FIXME
        // Margin is not considered, because there is no case that both
        // using margin and aspect so far.
        if (isNaN(width) && isNaN(height)) {
            if (aspect > containerWidth / containerHeight) {
                width = containerWidth * 0.8;
            }
            else {
                height = containerHeight * 0.8;
            }
        }

        // Calculate width or height with given aspect
        if (isNaN(width)) {
            width = aspect * height;
        }
        if (isNaN(height)) {
            height = width / aspect;
        }
    }

    // If left is not specified, calculate left from right and width
    if (isNaN(left)) {
        left = containerWidth - right - width - horizontalMargin;
    }
    if (isNaN(top)) {
        top = containerHeight - bottom - height - verticalMargin;
    }

    // Align left and top
    switch (positionInfo.left || positionInfo.right) {
        case 'center':
            left = containerWidth / 2 - width / 2 - margin[3];
            break;
        case 'right':
            left = containerWidth - width - horizontalMargin;
            break;
    }
    switch (positionInfo.top || positionInfo.bottom) {
        case 'middle':
        case 'center':
            top = containerHeight / 2 - height / 2 - margin[0];
            break;
        case 'bottom':
            top = containerHeight - height - verticalMargin;
            break;
    }
    // If something is wrong and left, top, width, height are calculated as NaN
    left = left || 0;
    top = top || 0;
    if (isNaN(width)) {
        // Width may be NaN if only one value is given except width
        width = containerWidth - horizontalMargin - left - (right || 0);
    }
    if (isNaN(height)) {
        // Height may be NaN if only one value is given except height
        height = containerHeight - verticalMargin - top - (bottom || 0);
    }

    var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
    rect.margin = margin;
    return rect;
}


/**
 * Position a zr element in viewport
 *  Group position is specified by either
 *  {left, top}, {right, bottom}
 *  If all properties exists, right and bottom will be igonred.
 *
 * Logic:
 *     1. Scale (against origin point in parent coord)
 *     2. Rotate (against origin point in parent coord)
 *     3. Traslate (with el.position by this method)
 * So this method only fixes the last step 'Traslate', which does not affect
 * scaling and rotating.
 *
 * If be called repeatly with the same input el, the same result will be gotten.
 *
 * @param {module:zrender/Element} el Should have `getBoundingRect` method.
 * @param {Object} positionInfo
 * @param {number|string} [positionInfo.left]
 * @param {number|string} [positionInfo.top]
 * @param {number|string} [positionInfo.right]
 * @param {number|string} [positionInfo.bottom]
 * @param {number|string} [positionInfo.width] Only for opt.boundingModel: 'raw'
 * @param {number|string} [positionInfo.height] Only for opt.boundingModel: 'raw'
 * @param {Object} containerRect
 * @param {string|number} margin
 * @param {Object} [opt]
 * @param {Array.<number>} [opt.hv=[1,1]] Only horizontal or only vertical.
 * @param {Array.<number>} [opt.boundingMode='all']
 *        Specify how to calculate boundingRect when locating.
 *        'all': Position the boundingRect that is transformed and uioned
 *               both itself and its descendants.
 *               This mode simplies confine the elements in the bounding
 *               of their container (e.g., using 'right: 0').
 *        'raw': Position the boundingRect that is not transformed and only itself.
 *               This mode is useful when you want a element can overflow its
 *               container. (Consider a rotated circle needs to be located in a corner.)
 *               In this mode positionInfo.width/height can only be number.
 */
function positionElement(el, positionInfo, containerRect, margin, opt) {
    var h = !opt || !opt.hv || opt.hv[0];
    var v = !opt || !opt.hv || opt.hv[1];
    var boundingMode = opt && opt.boundingMode || 'all';

    if (!h && !v) {
        return;
    }

    var rect;
    if (boundingMode === 'raw') {
        rect = el.type === 'group'
            ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0)
            : el.getBoundingRect();
    }
    else {
        rect = el.getBoundingRect();
        if (el.needLocalTransform()) {
            var transform = el.getLocalTransform();
            // Notice: raw rect may be inner object of el,
            // which should not be modified.
            rect = rect.clone();
            rect.applyTransform(transform);
        }
    }

    // The real width and height can not be specified but calculated by the given el.
    positionInfo = getLayoutRect(
        defaults(
            {width: rect.width, height: rect.height},
            positionInfo
        ),
        containerRect,
        margin
    );

    // Because 'tranlate' is the last step in transform
    // (see zrender/core/Transformable#getLocalTransform),
    // we can just only modify el.position to get final result.
    var elPos = el.position;
    var dx = h ? positionInfo.x - rect.x : 0;
    var dy = v ? positionInfo.y - rect.y : 0;

    el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]);
}

/**
 * @param {Object} option Contains some of the properties in HV_NAMES.
 * @param {number} hvIdx 0: horizontal; 1: vertical.
 */
function sizeCalculable(option, hvIdx) {
    return option[HV_NAMES[hvIdx][0]] != null
        || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null);
}

/**
 * Consider Case:
 * When defulat option has {left: 0, width: 100}, and we set {right: 0}
 * through setOption or media query, using normal zrUtil.merge will cause
 * {right: 0} does not take effect.
 *
 * @example
 * ComponentModel.extend({
 *     init: function () {
 *         ...
 *         var inputPositionParams = layout.getLayoutParams(option);
 *         this.mergeOption(inputPositionParams);
 *     },
 *     mergeOption: function (newOption) {
 *         newOption && zrUtil.merge(thisOption, newOption, true);
 *         layout.mergeLayoutParam(thisOption, newOption);
 *     }
 * });
 *
 * @param {Object} targetOption
 * @param {Object} newOption
 * @param {Object|string} [opt]
 * @param {boolean|Array.<boolean>} [opt.ignoreSize=false] Used for the components
 *  that width (or height) should not be calculated by left and right (or top and bottom).
 */
function mergeLayoutParam(targetOption, newOption, opt) {
    !isObject$1(opt) && (opt = {});

    var ignoreSize = opt.ignoreSize;
    !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);

    var hResult = merge$$1(HV_NAMES[0], 0);
    var vResult = merge$$1(HV_NAMES[1], 1);

    copy(HV_NAMES[0], targetOption, hResult);
    copy(HV_NAMES[1], targetOption, vResult);

    function merge$$1(names, hvIdx) {
        var newParams = {};
        var newValueCount = 0;
        var merged = {};
        var mergedValueCount = 0;
        var enoughParamNumber = 2;

        each$3(names, function (name) {
            merged[name] = targetOption[name];
        });
        each$3(names, function (name) {
            // Consider case: newOption.width is null, which is
            // set by user for removing width setting.
            hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
            hasValue(newParams, name) && newValueCount++;
            hasValue(merged, name) && mergedValueCount++;
        });

        if (ignoreSize[hvIdx]) {
            // Only one of left/right is premitted to exist.
            if (hasValue(newOption, names[1])) {
                merged[names[2]] = null;
            }
            else if (hasValue(newOption, names[2])) {
                merged[names[1]] = null;
            }
            return merged;
        }

        // Case: newOption: {width: ..., right: ...},
        // or targetOption: {right: ...} and newOption: {width: ...},
        // There is no conflict when merged only has params count
        // little than enoughParamNumber.
        if (mergedValueCount === enoughParamNumber || !newValueCount) {
            return merged;
        }
        // Case: newOption: {width: ..., right: ...},
        // Than we can make sure user only want those two, and ignore
        // all origin params in targetOption.
        else if (newValueCount >= enoughParamNumber) {
            return newParams;
        }
        else {
            // Chose another param from targetOption by priority.
            for (var i = 0; i < names.length; i++) {
                var name = names[i];
                if (!hasProp(newParams, name) && hasProp(targetOption, name)) {
                    newParams[name] = targetOption[name];
                    break;
                }
            }
            return newParams;
        }
    }

    function hasProp(obj, name) {
        return obj.hasOwnProperty(name);
    }

    function hasValue(obj, name) {
        return obj[name] != null && obj[name] !== 'auto';
    }

    function copy(names, target, source) {
        each$3(names, function (name) {
            target[name] = source[name];
        });
    }
}

/**
 * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
 * @param {Object} source
 * @return {Object} Result contains those props.
 */
function getLayoutParams(source) {
    return copyLayoutParams({}, source);
}

/**
 * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
 * @param {Object} source
 * @return {Object} Result contains those props.
 */
function copyLayoutParams(target, source) {
    source && target && each$3(LOCATION_PARAMS, function (name) {
        source.hasOwnProperty(name) && (target[name] = source[name]);
    });
    return target;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var boxLayoutMixin = {
    getBoxLayoutParams: function () {
        return {
            left: this.get('left'),
            top: this.get('top'),
            right: this.get('right'),
            bottom: this.get('bottom'),
            width: this.get('width'),
            height: this.get('height')
        };
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Component model
 *
 * @module echarts/model/Component
 */

var inner$1 = makeInner();

/**
 * @alias module:echarts/model/Component
 * @constructor
 * @param {Object} option
 * @param {module:echarts/model/Model} parentModel
 * @param {module:echarts/model/Model} ecModel
 */
var ComponentModel = Model.extend({

    type: 'component',

    /**
     * @readOnly
     * @type {string}
     */
    id: '',

    /**
     * Because simplified concept is probably better, series.name (or component.name)
     * has been having too many resposibilities:
     * (1) Generating id (which requires name in option should not be modified).
     * (2) As an index to mapping series when merging option or calling API (a name
     * can refer to more then one components, which is convinient is some case).
     * (3) Display.
     * @readOnly
     */
    name: '',

    /**
     * @readOnly
     * @type {string}
     */
    mainType: '',

    /**
     * @readOnly
     * @type {string}
     */
    subType: '',

    /**
     * @readOnly
     * @type {number}
     */
    componentIndex: 0,

    /**
     * @type {Object}
     * @protected
     */
    defaultOption: null,

    /**
     * @type {module:echarts/model/Global}
     * @readOnly
     */
    ecModel: null,

    /**
     * key: componentType
     * value:  Component model list, can not be null.
     * @type {Object.<string, Array.<module:echarts/model/Model>>}
     * @readOnly
     */
    dependentModels: [],

    /**
     * @type {string}
     * @readOnly
     */
    uid: null,

    /**
     * Support merge layout params.
     * Only support 'box' now (left/right/top/bottom/width/height).
     * @type {string|Object} Object can be {ignoreSize: true}
     * @readOnly
     */
    layoutMode: null,

    $constructor: function (option, parentModel, ecModel, extraOpt) {
        Model.call(this, option, parentModel, ecModel, extraOpt);

        this.uid = getUID('ec_cpt_model');
    },

    init: function (option, parentModel, ecModel, extraOpt) {
        this.mergeDefaultAndTheme(option, ecModel);
    },

    mergeDefaultAndTheme: function (option, ecModel) {
        var layoutMode = this.layoutMode;
        var inputPositionParams = layoutMode
            ? getLayoutParams(option) : {};

        var themeModel = ecModel.getTheme();
        merge(option, themeModel.get(this.mainType));
        merge(option, this.getDefaultOption());

        if (layoutMode) {
            mergeLayoutParam(option, inputPositionParams, layoutMode);
        }
    },

    mergeOption: function (option, extraOpt) {
        merge(this.option, option, true);

        var layoutMode = this.layoutMode;
        if (layoutMode) {
            mergeLayoutParam(this.option, option, layoutMode);
        }
    },

    // Hooker after init or mergeOption
    optionUpdated: function (newCptOption, isInit) {},

    getDefaultOption: function () {
        var fields = inner$1(this);
        if (!fields.defaultOption) {
            var optList = [];
            var Class = this.constructor;
            while (Class) {
                var opt = Class.prototype.defaultOption;
                opt && optList.push(opt);
                Class = Class.superClass;
            }

            var defaultOption = {};
            for (var i = optList.length - 1; i >= 0; i--) {
                defaultOption = merge(defaultOption, optList[i], true);
            }
            fields.defaultOption = defaultOption;
        }
        return fields.defaultOption;
    },

    getReferringComponents: function (mainType) {
        return this.ecModel.queryComponents({
            mainType: mainType,
            index: this.get(mainType + 'Index', true),
            id: this.get(mainType + 'Id', true)
        });
    }

});

// Reset ComponentModel.extend, add preConstruct.
// clazzUtil.enableClassExtend(
//     ComponentModel,
//     function (option, parentModel, ecModel, extraOpt) {
//         // Set dependentModels, componentIndex, name, id, mainType, subType.
//         zrUtil.extend(this, extraOpt);

//         this.uid = componentUtil.getUID('componentModel');

//         // this.setReadOnly([
//         //     'type', 'id', 'uid', 'name', 'mainType', 'subType',
//         //     'dependentModels', 'componentIndex'
//         // ]);
//     }
// );

// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
enableClassManagement(
    ComponentModel, {registerWhenExtend: true}
);
enableSubTypeDefaulter(ComponentModel);

// Add capability of ComponentModel.topologicalTravel.
enableTopologicalTravel(ComponentModel, getDependencies);

function getDependencies(componentType) {
    var deps = [];
    each$1(ComponentModel.getClassesByMainType(componentType), function (Clazz) {
        deps = deps.concat(Clazz.prototype.dependencies || []);
    });

    // Ensure main type.
    deps = map(deps, function (type) {
        return parseClassType$1(type).main;
    });

    // Hack dataset for convenience.
    if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) {
        deps.unshift('dataset');
    }

    return deps;
}

mixin(ComponentModel, boxLayoutMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var platform = '';
// Navigator not exists in node
if (typeof navigator !== 'undefined') {
    platform = navigator.platform || '';
}

var globalDefault = {
    // backgroundColor: 'rgba(0,0,0,0)',

    // https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization
    // color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],
    // Light colors:
    // color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],
    // color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],
    // Dark colors:
    color: [
        '#c23531', '#2f4554', '#61a0a8', '#d48265', '#91c7ae', '#749f83',
        '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'
    ],

    gradientColor: ['#f6efa6', '#d88273', '#bf444c'],

    // If xAxis and yAxis declared, grid is created by default.
    // grid: {},

    textStyle: {
        // color: '#000',
        // decoration: 'none',
        // PENDING
        fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
        // fontFamily: 'Arial, Verdana, sans-serif',
        fontSize: 12,
        fontStyle: 'normal',
        fontWeight: 'normal'
    },

    // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/
    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
    // Default is source-over
    blendMode: null,

    animation: 'auto',
    animationDuration: 1000,
    animationDurationUpdate: 300,
    animationEasing: 'exponentialOut',
    animationEasingUpdate: 'cubicOut',

    animationThreshold: 2000,
    // Configuration for progressive/incremental rendering
    progressiveThreshold: 3000,
    progressive: 400,

    // Threshold of if use single hover layer to optimize.
    // It is recommended that `hoverLayerThreshold` is equivalent to or less than
    // `progressiveThreshold`, otherwise hover will cause restart of progressive,
    // which is unexpected.
    // see example <echarts/test/heatmap-large.html>.
    hoverLayerThreshold: 3000,

    // See: module:echarts/scale/Time
    useUTC: false
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$2 = makeInner();

function getNearestColorPalette(colors, requestColorNum) {
    var paletteNum = colors.length;
    // TODO colors must be in order
    for (var i = 0; i < paletteNum; i++) {
        if (colors[i].length > requestColorNum) {
            return colors[i];
        }
    }
    return colors[paletteNum - 1];
}

var colorPaletteMixin = {
    clearColorPalette: function () {
        inner$2(this).colorIdx = 0;
        inner$2(this).colorNameMap = {};
    },

    /**
     * @param {string} name MUST NOT be null/undefined. Otherwise call this function
     *                 twise with the same parameters will get different result.
     * @param {Object} [scope=this]
     * @param {Object} [requestColorNum]
     * @return {string} color string.
     */
    getColorFromPalette: function (name, scope, requestColorNum) {
        scope = scope || this;
        var scopeFields = inner$2(scope);
        var colorIdx = scopeFields.colorIdx || 0;
        var colorNameMap = scopeFields.colorNameMap = scopeFields.colorNameMap || {};
        // Use `hasOwnProperty` to avoid conflict with Object.prototype.
        if (colorNameMap.hasOwnProperty(name)) {
            return colorNameMap[name];
        }
        var defaultColorPalette = normalizeToArray(this.get('color', true));
        var layeredColorPalette = this.get('colorLayer', true);
        var colorPalette = ((requestColorNum == null || !layeredColorPalette)
            ? defaultColorPalette : getNearestColorPalette(layeredColorPalette, requestColorNum));

        // In case can't find in layered color palette.
        colorPalette = colorPalette || defaultColorPalette;

        if (!colorPalette || !colorPalette.length) {
            return;
        }

        var color = colorPalette[colorIdx];
        if (name) {
            colorNameMap[name] = color;
        }
        scopeFields.colorIdx = (colorIdx + 1) % colorPalette.length;

        return color;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Helper for model references.
 * There are many manners to refer axis/coordSys.
 */

// TODO
// merge relevant logic to this file?
// check: "modelHelper" of tooltip and "BrushTargetManager".

/**
 * @return {Object} For example:
 * {
 *     coordSysName: 'cartesian2d',
 *     coordSysDims: ['x', 'y', ...],
 *     axisMap: HashMap({
 *         x: xAxisModel,
 *         y: yAxisModel
 *     }),
 *     categoryAxisMap: HashMap({
 *         x: xAxisModel,
 *         y: undefined
 *     }),
 *     // It also indicate that whether there is category axis.
 *     firstCategoryDimIndex: 1,
 *     // To replace user specified encode.
 * }
 */
function getCoordSysDefineBySeries(seriesModel) {
    var coordSysName = seriesModel.get('coordinateSystem');
    var result = {
        coordSysName: coordSysName,
        coordSysDims: [],
        axisMap: createHashMap(),
        categoryAxisMap: createHashMap()
    };
    var fetch = fetchers[coordSysName];
    if (fetch) {
        fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
        return result;
    }
}

var fetchers = {

    cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
        var xAxisModel = seriesModel.getReferringComponents('xAxis')[0];
        var yAxisModel = seriesModel.getReferringComponents('yAxis')[0];

        if (__DEV__) {
            if (!xAxisModel) {
                throw new Error('xAxis "' + retrieve(
                    seriesModel.get('xAxisIndex'),
                    seriesModel.get('xAxisId'),
                    0
                ) + '" not found');
            }
            if (!yAxisModel) {
                throw new Error('yAxis "' + retrieve(
                    seriesModel.get('xAxisIndex'),
                    seriesModel.get('yAxisId'),
                    0
                ) + '" not found');
            }
        }

        result.coordSysDims = ['x', 'y'];
        axisMap.set('x', xAxisModel);
        axisMap.set('y', yAxisModel);

        if (isCategory(xAxisModel)) {
            categoryAxisMap.set('x', xAxisModel);
            result.firstCategoryDimIndex = 0;
        }
        if (isCategory(yAxisModel)) {
            categoryAxisMap.set('y', yAxisModel);
            result.firstCategoryDimIndex = 1;
        }
    },

    singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
        var singleAxisModel = seriesModel.getReferringComponents('singleAxis')[0];

        if (__DEV__) {
            if (!singleAxisModel) {
                throw new Error('singleAxis should be specified.');
            }
        }

        result.coordSysDims = ['single'];
        axisMap.set('single', singleAxisModel);

        if (isCategory(singleAxisModel)) {
            categoryAxisMap.set('single', singleAxisModel);
            result.firstCategoryDimIndex = 0;
        }
    },

    polar: function (seriesModel, result, axisMap, categoryAxisMap) {
        var polarModel = seriesModel.getReferringComponents('polar')[0];
        var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
        var angleAxisModel = polarModel.findAxisModel('angleAxis');

        if (__DEV__) {
            if (!angleAxisModel) {
                throw new Error('angleAxis option not found');
            }
            if (!radiusAxisModel) {
                throw new Error('radiusAxis option not found');
            }
        }

        result.coordSysDims = ['radius', 'angle'];
        axisMap.set('radius', radiusAxisModel);
        axisMap.set('angle', angleAxisModel);

        if (isCategory(radiusAxisModel)) {
            categoryAxisMap.set('radius', radiusAxisModel);
            result.firstCategoryDimIndex = 0;
        }
        if (isCategory(angleAxisModel)) {
            categoryAxisMap.set('angle', angleAxisModel);
            result.firstCategoryDimIndex = 1;
        }
    },

    geo: function (seriesModel, result, axisMap, categoryAxisMap) {
        result.coordSysDims = ['lng', 'lat'];
    },

    parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
        var ecModel = seriesModel.ecModel;
        var parallelModel = ecModel.getComponent(
            'parallel', seriesModel.get('parallelIndex')
        );
        var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();

        each$1(parallelModel.parallelAxisIndex, function (axisIndex, index) {
            var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
            var axisDim = coordSysDims[index];
            axisMap.set(axisDim, axisModel);

            if (isCategory(axisModel) && result.firstCategoryDimIndex == null) {
                categoryAxisMap.set(axisDim, axisModel);
                result.firstCategoryDimIndex = index;
            }
        });
    }
};

function isCategory(axisModel) {
    return axisModel.get('type') === 'category';
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Avoid typo.
var SOURCE_FORMAT_ORIGINAL = 'original';
var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows';
var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows';
var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns';
var SOURCE_FORMAT_UNKNOWN = 'unknown';
// ??? CHANGE A NAME
var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray';

var SERIES_LAYOUT_BY_COLUMN = 'column';
var SERIES_LAYOUT_BY_ROW = 'row';

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * [sourceFormat]
 *
 * + "original":
 * This format is only used in series.data, where
 * itemStyle can be specified in data item.
 *
 * + "arrayRows":
 * [
 *     ['product', 'score', 'amount'],
 *     ['Matcha Latte', 89.3, 95.8],
 *     ['Milk Tea', 92.1, 89.4],
 *     ['Cheese Cocoa', 94.4, 91.2],
 *     ['Walnut Brownie', 85.4, 76.9]
 * ]
 *
 * + "objectRows":
 * [
 *     {product: 'Matcha Latte', score: 89.3, amount: 95.8},
 *     {product: 'Milk Tea', score: 92.1, amount: 89.4},
 *     {product: 'Cheese Cocoa', score: 94.4, amount: 91.2},
 *     {product: 'Walnut Brownie', score: 85.4, amount: 76.9}
 * ]
 *
 * + "keyedColumns":
 * {
 *     'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],
 *     'count': [823, 235, 1042, 988],
 *     'score': [95.8, 81.4, 91.2, 76.9]
 * }
 *
 * + "typedArray"
 *
 * + "unknown"
 */

/**
 * @constructor
 * @param {Object} fields
 * @param {string} fields.sourceFormat
 * @param {Array|Object} fields.fromDataset
 * @param {Array|Object} [fields.data]
 * @param {string} [seriesLayoutBy='column']
 * @param {Array.<Object|string>} [dimensionsDefine]
 * @param {Objet|HashMap} [encodeDefine]
 * @param {number} [startIndex=0]
 * @param {number} [dimensionsDetectCount]
 */
function Source(fields) {

    /**
     * @type {boolean}
     */
    this.fromDataset = fields.fromDataset;

    /**
     * Not null/undefined.
     * @type {Array|Object}
     */
    this.data = fields.data || (
        fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []
    );

    /**
     * See also "detectSourceFormat".
     * Not null/undefined.
     * @type {string}
     */
    this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN;

    /**
     * 'row' or 'column'
     * Not null/undefined.
     * @type {string} seriesLayoutBy
     */
    this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN;

    /**
     * dimensions definition in option.
     * can be null/undefined.
     * @type {Array.<Object|string>}
     */
    this.dimensionsDefine = fields.dimensionsDefine;

    /**
     * encode definition in option.
     * can be null/undefined.
     * @type {Objet|HashMap}
     */
    this.encodeDefine = fields.encodeDefine && createHashMap(fields.encodeDefine);

    /**
     * Not null/undefined, uint.
     * @type {number}
     */
    this.startIndex = fields.startIndex || 0;

    /**
     * Can be null/undefined (when unknown), uint.
     * @type {number}
     */
    this.dimensionsDetectCount = fields.dimensionsDetectCount;
}

/**
 * Wrap original series data for some compatibility cases.
 */
Source.seriesDataToSource = function (data) {
    return new Source({
        data: data,
        sourceFormat: isTypedArray(data)
            ? SOURCE_FORMAT_TYPED_ARRAY
            : SOURCE_FORMAT_ORIGINAL,
        fromDataset: false
    });
};

enableClassCheck(Source);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$3 = makeInner();

/**
 * @see {module:echarts/data/Source}
 * @param {module:echarts/component/dataset/DatasetModel} datasetModel
 * @return {string} sourceFormat
 */
function detectSourceFormat(datasetModel) {
    var data = datasetModel.option.source;
    var sourceFormat = SOURCE_FORMAT_UNKNOWN;

    if (isTypedArray(data)) {
        sourceFormat = SOURCE_FORMAT_TYPED_ARRAY;
    }
    else if (isArray(data)) {
        // FIXME Whether tolerate null in top level array?
        if (data.length === 0) {
            sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
        }

        for (var i = 0, len = data.length; i < len; i++) {
            var item = data[i];

            if (item == null) {
                continue;
            }
            else if (isArray(item)) {
                sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
                break;
            }
            else if (isObject$1(item)) {
                sourceFormat = SOURCE_FORMAT_OBJECT_ROWS;
                break;
            }
        }
    }
    else if (isObject$1(data)) {
        for (var key in data) {
            if (data.hasOwnProperty(key) && isArrayLike(data[key])) {
                sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS;
                break;
            }
        }
    }
    else if (data != null) {
        throw new Error('Invalid data');
    }

    inner$3(datasetModel).sourceFormat = sourceFormat;
}

/**
 * [Scenarios]:
 * (1) Provide source data directly:
 *     series: {
 *         encode: {...},
 *         dimensions: [...]
 *         seriesLayoutBy: 'row',
 *         data: [[...]]
 *     }
 * (2) Refer to datasetModel.
 *     series: [{
 *         encode: {...}
 *         // Ignore datasetIndex means `datasetIndex: 0`
 *         // and the dimensions defination in dataset is used
 *     }, {
 *         encode: {...},
 *         seriesLayoutBy: 'column',
 *         datasetIndex: 1
 *     }]
 *
 * Get data from series itself or datset.
 * @return {module:echarts/data/Source} source
 */
function getSource(seriesModel) {
    return inner$3(seriesModel).source;
}

/**
 * MUST be called before mergeOption of all series.
 * @param {module:echarts/model/Global} ecModel
 */
function resetSourceDefaulter(ecModel) {
    // `datasetMap` is used to make default encode.
    inner$3(ecModel).datasetMap = createHashMap();
}

/**
 * [Caution]:
 * MUST be called after series option merged and
 * before "series.getInitailData()" called.
 *
 * [The rule of making default encode]:
 * Category axis (if exists) alway map to the first dimension.
 * Each other axis occupies a subsequent dimension.
 *
 * [Why make default encode]:
 * Simplify the typing of encode in option, avoiding the case like that:
 * series: [{encode: {x: 0, y: 1}}, {encode: {x: 0, y: 2}}, {encode: {x: 0, y: 3}}],
 * where the "y" have to be manually typed as "1, 2, 3, ...".
 *
 * @param {module:echarts/model/Series} seriesModel
 */
function prepareSource(seriesModel) {
    var seriesOption = seriesModel.option;

    var data = seriesOption.data;
    var sourceFormat = isTypedArray(data)
        ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL;
    var fromDataset = false;

    var seriesLayoutBy = seriesOption.seriesLayoutBy;
    var sourceHeader = seriesOption.sourceHeader;
    var dimensionsDefine = seriesOption.dimensions;

    var datasetModel = getDatasetModel(seriesModel);
    if (datasetModel) {
        var datasetOption = datasetModel.option;

        data = datasetOption.source;
        sourceFormat = inner$3(datasetModel).sourceFormat;
        fromDataset = true;

        // These settings from series has higher priority.
        seriesLayoutBy = seriesLayoutBy || datasetOption.seriesLayoutBy;
        sourceHeader == null && (sourceHeader = datasetOption.sourceHeader);
        dimensionsDefine = dimensionsDefine || datasetOption.dimensions;
    }

    var completeResult = completeBySourceData(
        data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine
    );

    // Note: dataset option does not have `encode`.
    var encodeDefine = seriesOption.encode;
    if (!encodeDefine && datasetModel) {
        encodeDefine = makeDefaultEncode(
            seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult
        );
    }

    inner$3(seriesModel).source = new Source({
        data: data,
        fromDataset: fromDataset,
        seriesLayoutBy: seriesLayoutBy,
        sourceFormat: sourceFormat,
        dimensionsDefine: completeResult.dimensionsDefine,
        startIndex: completeResult.startIndex,
        dimensionsDetectCount: completeResult.dimensionsDetectCount,
        encodeDefine: encodeDefine
    });
}

// return {startIndex, dimensionsDefine, dimensionsCount}
function completeBySourceData(data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine) {
    if (!data) {
        return {dimensionsDefine: normalizeDimensionsDefine(dimensionsDefine)};
    }

    var dimensionsDetectCount;
    var startIndex;
    var findPotentialName;

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
        // Rule: Most of the first line are string: it is header.
        // Caution: consider a line with 5 string and 1 number,
        // it still can not be sure it is a head, because the
        // 5 string may be 5 values of category columns.
        if (sourceHeader === 'auto' || sourceHeader == null) {
            arrayRowsTravelFirst(function (val) {
                // '-' is regarded as null/undefined.
                if (val != null && val !== '-') {
                    if (isString(val)) {
                        startIndex == null && (startIndex = 1);
                    }
                    else {
                        startIndex = 0;
                    }
                }
            // 10 is an experience number, avoid long loop.
            }, seriesLayoutBy, data, 10);
        }
        else {
            startIndex = sourceHeader ? 1 : 0;
        }

        if (!dimensionsDefine && startIndex === 1) {
            dimensionsDefine = [];
            arrayRowsTravelFirst(function (val, index) {
                dimensionsDefine[index] = val != null ? val : '';
            }, seriesLayoutBy, data);
        }

        dimensionsDetectCount = dimensionsDefine
            ? dimensionsDefine.length
            : seriesLayoutBy === SERIES_LAYOUT_BY_ROW
            ? data.length
            : data[0]
            ? data[0].length
            : null;
    }
    else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
        if (!dimensionsDefine) {
            dimensionsDefine = objectRowsCollectDimensions(data);
            findPotentialName = true;
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
        if (!dimensionsDefine) {
            dimensionsDefine = [];
            findPotentialName = true;
            each$1(data, function (colArr, key) {
                dimensionsDefine.push(key);
            });
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
        var value0 = getDataItemValue(data[0]);
        dimensionsDetectCount = isArray(value0) && value0.length || 1;
    }
    else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
        if (__DEV__) {
            assert$1(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.');
        }
    }

    var potentialNameDimIndex;
    if (findPotentialName) {
        each$1(dimensionsDefine, function (dim, idx) {
            if ((isObject$1(dim) ? dim.name : dim) === 'name') {
                potentialNameDimIndex = idx;
            }
        });
    }

    return {
        startIndex: startIndex,
        dimensionsDefine: normalizeDimensionsDefine(dimensionsDefine),
        dimensionsDetectCount: dimensionsDetectCount,
        potentialNameDimIndex: potentialNameDimIndex
        // TODO: potentialIdDimIdx
    };
}

// Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'],
// which is reasonable. But dimension name is duplicated.
// Returns undefined or an array contains only object without null/undefiend or string.
function normalizeDimensionsDefine(dimensionsDefine) {
    if (!dimensionsDefine) {
        // The meaning of null/undefined is different from empty array.
        return;
    }
    var nameMap = createHashMap();
    return map(dimensionsDefine, function (item, index) {
        item = extend({}, isObject$1(item) ? item : {name: item});

        // User can set null in dimensions.
        // We dont auto specify name, othewise a given name may
        // cause it be refered unexpectedly.
        if (item.name == null) {
            return item;
        }

        // Also consider number form like 2012.
        item.name += '';
        // User may also specify displayName.
        // displayName will always exists except user not
        // specified or dim name is not specified or detected.
        // (A auto generated dim name will not be used as
        // displayName).
        if (item.displayName == null) {
            item.displayName = item.name;
        }

        var exist = nameMap.get(item.name);
        if (!exist) {
            nameMap.set(item.name, {count: 1});
        }
        else {
            item.name += '-' + exist.count++;
        }

        return item;
    });
}

function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) {
    maxLoop == null && (maxLoop = Infinity);
    if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
        for (var i = 0; i < data.length && i < maxLoop; i++) {
            cb(data[i] ? data[i][0] : null, i);
        }
    }
    else {
        var value0 = data[0] || [];
        for (var i = 0; i < value0.length && i < maxLoop; i++) {
            cb(value0[i], i);
        }
    }
}

function objectRowsCollectDimensions(data) {
    var firstIndex = 0;
    var obj;
    while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line
    if (obj) {
        var dimensions = [];
        each$1(obj, function (value, key) {
            dimensions.push(key);
        });
        return dimensions;
    }
}

// ??? TODO merge to completedimensions, where also has
// default encode making logic. And the default rule
// should depends on series? consider 'map'.
function makeDefaultEncode(
    seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult
) {
    var coordSysDefine = getCoordSysDefineBySeries(seriesModel);
    var encode = {};
    // var encodeTooltip = [];
    // var encodeLabel = [];
    var encodeItemName = [];
    var encodeSeriesName = [];
    var seriesType = seriesModel.subType;

    // ??? TODO refactor: provide by series itself.
    // Consider the case: 'map' series is based on geo coordSys,
    // 'graph', 'heatmap' can be based on cartesian. But can not
    // give default rule simply here.
    var nSeriesMap = createHashMap(['pie', 'map', 'funnel']);
    var cSeriesMap = createHashMap([
        'line', 'bar', 'pictorialBar', 'scatter', 'effectScatter', 'candlestick', 'boxplot'
    ]);

    // Usually in this case series will use the first data
    // dimension as the "value" dimension, or other default
    // processes respectively.
    if (coordSysDefine && cSeriesMap.get(seriesType) != null) {
        var ecModel = seriesModel.ecModel;
        var datasetMap = inner$3(ecModel).datasetMap;
        var key = datasetModel.uid + '_' + seriesLayoutBy;
        var datasetRecord = datasetMap.get(key)
            || datasetMap.set(key, {categoryWayDim: 1, valueWayDim: 0});

        // TODO
        // Auto detect first time axis and do arrangement.
        each$1(coordSysDefine.coordSysDims, function (coordDim) {
            // In value way.
            if (coordSysDefine.firstCategoryDimIndex == null) {
                var dataDim = datasetRecord.valueWayDim++;
                encode[coordDim] = dataDim;

                // ??? TODO give a better default series name rule?
                // especially when encode x y specified.
                // consider: when mutiple series share one dimension
                // category axis, series name should better use
                // the other dimsion name. On the other hand, use
                // both dimensions name.

                encodeSeriesName.push(dataDim);
                // encodeTooltip.push(dataDim);
                // encodeLabel.push(dataDim);
            }
            // In category way, category axis.
            else if (coordSysDefine.categoryAxisMap.get(coordDim)) {
                encode[coordDim] = 0;
                encodeItemName.push(0);
            }
            // In category way, non-category axis.
            else {
                var dataDim = datasetRecord.categoryWayDim++;
                encode[coordDim] = dataDim;
                // encodeTooltip.push(dataDim);
                // encodeLabel.push(dataDim);
                encodeSeriesName.push(dataDim);
            }
        });
    }
    // Do not make a complex rule! Hard to code maintain and not necessary.
    // ??? TODO refactor: provide by series itself.
    // [{name: ..., value: ...}, ...] like:
    else if (nSeriesMap.get(seriesType) != null) {
        // Find the first not ordinal. (5 is an experience value)
        var firstNotOrdinal;
        for (var i = 0; i < 5 && firstNotOrdinal == null; i++) {
            if (!doGuessOrdinal(
                data, sourceFormat, seriesLayoutBy,
                completeResult.dimensionsDefine, completeResult.startIndex, i
            )) {
                firstNotOrdinal = i;
            }
        }
        if (firstNotOrdinal != null) {
            encode.value = firstNotOrdinal;
            var nameDimIndex = completeResult.potentialNameDimIndex
                || Math.max(firstNotOrdinal - 1, 0);
            // By default, label use itemName in charts.
            // So we dont set encodeLabel here.
            encodeSeriesName.push(nameDimIndex);
            encodeItemName.push(nameDimIndex);
            // encodeTooltip.push(firstNotOrdinal);
        }
    }

    // encodeTooltip.length && (encode.tooltip = encodeTooltip);
    // encodeLabel.length && (encode.label = encodeLabel);
    encodeItemName.length && (encode.itemName = encodeItemName);
    encodeSeriesName.length && (encode.seriesName = encodeSeriesName);

    return encode;
}

/**
 * If return null/undefined, indicate that should not use datasetModel.
 */
function getDatasetModel(seriesModel) {
    var option = seriesModel.option;
    // Caution: consider the scenario:
    // A dataset is declared and a series is not expected to use the dataset,
    // and at the beginning `setOption({series: { noData })` (just prepare other
    // option but no data), then `setOption({series: {data: [...]}); In this case,
    // the user should set an empty array to avoid that dataset is used by default.
    var thisData = option.data;
    if (!thisData) {
        return seriesModel.ecModel.getComponent('dataset', option.datasetIndex || 0);
    }
}

/**
 * The rule should not be complex, otherwise user might not
 * be able to known where the data is wrong.
 * The code is ugly, but how to make it neat?
 *
 * @param {module:echars/data/Source} source
 * @param {number} dimIndex
 * @return {boolean} Whether ordinal.
 */
function guessOrdinal(source, dimIndex) {
    return doGuessOrdinal(
        source.data,
        source.sourceFormat,
        source.seriesLayoutBy,
        source.dimensionsDefine,
        source.startIndex,
        dimIndex
    );
}

// dimIndex may be overflow source data.
function doGuessOrdinal(
    data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex
) {
    var result;
    // Experience value.
    var maxLoop = 5;

    if (isTypedArray(data)) {
        return false;
    }

    // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine
    // always exists in source.
    var dimName;
    if (dimensionsDefine) {
        dimName = dimensionsDefine[dimIndex];
        dimName = isObject$1(dimName) ? dimName.name : dimName;
    }

    if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
        if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
            var sample = data[dimIndex];
            for (var i = 0; i < (sample || []).length && i < maxLoop; i++) {
                if ((result = detectValue(sample[startIndex + i])) != null) {
                    return result;
                }
            }
        }
        else {
            for (var i = 0; i < data.length && i < maxLoop; i++) {
                var row = data[startIndex + i];
                if (row && (result = detectValue(row[dimIndex])) != null) {
                    return result;
                }
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
        if (!dimName) {
            return;
        }
        for (var i = 0; i < data.length && i < maxLoop; i++) {
            var item = data[i];
            if (item && (result = detectValue(item[dimName])) != null) {
                return result;
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
        if (!dimName) {
            return;
        }
        var sample = data[dimName];
        if (!sample || isTypedArray(sample)) {
            return false;
        }
        for (var i = 0; i < sample.length && i < maxLoop; i++) {
            if ((result = detectValue(sample[i])) != null) {
                return result;
            }
        }
    }
    else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
        for (var i = 0; i < data.length && i < maxLoop; i++) {
            var item = data[i];
            var val = getDataItemValue(item);
            if (!isArray(val)) {
                return false;
            }
            if ((result = detectValue(val[dimIndex])) != null) {
                return result;
            }
        }
    }

    function detectValue(val) {
        // Consider usage convenience, '1', '2' will be treated as "number".
        // `isFinit('')` get `true`.
        if (val != null && isFinite(val) && val !== '') {
            return false;
        }
        else if (isString(val) && val !== '-') {
            return true;
        }
    }

    return false;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * ECharts global model
 *
 * @module {echarts/model/Global}
 */


/**
 * Caution: If the mechanism should be changed some day, these cases
 * should be considered:
 *
 * (1) In `merge option` mode, if using the same option to call `setOption`
 * many times, the result should be the same (try our best to ensure that).
 * (2) In `merge option` mode, if a component has no id/name specified, it
 * will be merged by index, and the result sequence of the components is
 * consistent to the original sequence.
 * (3) `reset` feature (in toolbox). Find detailed info in comments about
 * `mergeOption` in module:echarts/model/OptionManager.
 */

var OPTION_INNER_KEY = '\0_ec_inner';

/**
 * @alias module:echarts/model/Global
 *
 * @param {Object} option
 * @param {module:echarts/model/Model} parentModel
 * @param {Object} theme
 */
var GlobalModel = Model.extend({

    init: function (option, parentModel, theme, optionManager) {
        theme = theme || {};

        this.option = null; // Mark as not initialized.

        /**
         * @type {module:echarts/model/Model}
         * @private
         */
        this._theme = new Model(theme);

        /**
         * @type {module:echarts/model/OptionManager}
         */
        this._optionManager = optionManager;
    },

    setOption: function (option, optionPreprocessorFuncs) {
        assert$1(
            !(OPTION_INNER_KEY in option),
            'please use chart.getOption()'
        );

        this._optionManager.setOption(option, optionPreprocessorFuncs);

        this.resetOption(null);
    },

    /**
     * @param {string} type null/undefined: reset all.
     *                      'recreate': force recreate all.
     *                      'timeline': only reset timeline option
     *                      'media': only reset media query option
     * @return {boolean} Whether option changed.
     */
    resetOption: function (type) {
        var optionChanged = false;
        var optionManager = this._optionManager;

        if (!type || type === 'recreate') {
            var baseOption = optionManager.mountOption(type === 'recreate');

            if (!this.option || type === 'recreate') {
                initBase.call(this, baseOption);
            }
            else {
                this.restoreData();
                this.mergeOption(baseOption);
            }
            optionChanged = true;
        }

        if (type === 'timeline' || type === 'media') {
            this.restoreData();
        }

        if (!type || type === 'recreate' || type === 'timeline') {
            var timelineOption = optionManager.getTimelineOption(this);
            timelineOption && (this.mergeOption(timelineOption), optionChanged = true);
        }

        if (!type || type === 'recreate' || type === 'media') {
            var mediaOptions = optionManager.getMediaOption(this, this._api);
            if (mediaOptions.length) {
                each$1(mediaOptions, function (mediaOption) {
                    this.mergeOption(mediaOption, optionChanged = true);
                }, this);
            }
        }

        return optionChanged;
    },

    /**
     * @protected
     */
    mergeOption: function (newOption) {
        var option = this.option;
        var componentsMap = this._componentsMap;
        var newCptTypes = [];

        resetSourceDefaulter(this);

        // If no component class, merge directly.
        // For example: color, animaiton options, etc.
        each$1(newOption, function (componentOption, mainType) {
            if (componentOption == null) {
                return;
            }

            if (!ComponentModel.hasClass(mainType)) {
                // globalSettingTask.dirty();
                option[mainType] = option[mainType] == null
                    ? clone(componentOption)
                    : merge(option[mainType], componentOption, true);
            }
            else if (mainType) {
                newCptTypes.push(mainType);
            }
        });

        ComponentModel.topologicalTravel(
            newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this
        );

        function visitComponent(mainType, dependencies) {

            var newCptOptionList = normalizeToArray(newOption[mainType]);

            var mapResult = mappingToExists(
                componentsMap.get(mainType), newCptOptionList
            );

            makeIdAndName(mapResult);

            // Set mainType and complete subType.
            each$1(mapResult, function (item, index) {
                var opt = item.option;
                if (isObject$1(opt)) {
                    item.keyInfo.mainType = mainType;
                    item.keyInfo.subType = determineSubType(mainType, opt, item.exist);
                }
            });

            var dependentModels = getComponentsByTypes(
                componentsMap, dependencies
            );

            option[mainType] = [];
            componentsMap.set(mainType, []);

            each$1(mapResult, function (resultItem, index) {
                var componentModel = resultItem.exist;
                var newCptOption = resultItem.option;

                assert$1(
                    isObject$1(newCptOption) || componentModel,
                    'Empty component definition'
                );

                // Consider where is no new option and should be merged using {},
                // see removeEdgeAndAdd in topologicalTravel and
                // ComponentModel.getAllClassMainTypes.
                if (!newCptOption) {
                    componentModel.mergeOption({}, this);
                    componentModel.optionUpdated({}, false);
                }
                else {
                    var ComponentModelClass = ComponentModel.getClass(
                        mainType, resultItem.keyInfo.subType, true
                    );

                    if (componentModel && componentModel.constructor === ComponentModelClass) {
                        componentModel.name = resultItem.keyInfo.name;
                        // componentModel.settingTask && componentModel.settingTask.dirty();
                        componentModel.mergeOption(newCptOption, this);
                        componentModel.optionUpdated(newCptOption, false);
                    }
                    else {
                        // PENDING Global as parent ?
                        var extraOpt = extend(
                            {
                                dependentModels: dependentModels,
                                componentIndex: index
                            },
                            resultItem.keyInfo
                        );
                        componentModel = new ComponentModelClass(
                            newCptOption, this, this, extraOpt
                        );
                        extend(componentModel, extraOpt);
                        componentModel.init(newCptOption, this, this, extraOpt);

                        // Call optionUpdated after init.
                        // newCptOption has been used as componentModel.option
                        // and may be merged with theme and default, so pass null
                        // to avoid confusion.
                        componentModel.optionUpdated(null, true);
                    }
                }

                componentsMap.get(mainType)[index] = componentModel;
                option[mainType][index] = componentModel.option;
            }, this);

            // Backup series for filtering.
            if (mainType === 'series') {
                createSeriesIndices(this, componentsMap.get('series'));
            }
        }

        this._seriesIndicesMap = createHashMap(
            this._seriesIndices = this._seriesIndices || []
        );
    },

    /**
     * Get option for output (cloned option and inner info removed)
     * @public
     * @return {Object}
     */
    getOption: function () {
        var option = clone(this.option);

        each$1(option, function (opts, mainType) {
            if (ComponentModel.hasClass(mainType)) {
                var opts = normalizeToArray(opts);
                for (var i = opts.length - 1; i >= 0; i--) {
                    // Remove options with inner id.
                    if (isIdInner(opts[i])) {
                        opts.splice(i, 1);
                    }
                }
                option[mainType] = opts;
            }
        });

        delete option[OPTION_INNER_KEY];

        return option;
    },

    /**
     * @return {module:echarts/model/Model}
     */
    getTheme: function () {
        return this._theme;
    },

    /**
     * @param {string} mainType
     * @param {number} [idx=0]
     * @return {module:echarts/model/Component}
     */
    getComponent: function (mainType, idx) {
        var list = this._componentsMap.get(mainType);
        if (list) {
            return list[idx || 0];
        }
    },

    /**
     * If none of index and id and name used, return all components with mainType.
     * @param {Object} condition
     * @param {string} condition.mainType
     * @param {string} [condition.subType] If ignore, only query by mainType
     * @param {number|Array.<number>} [condition.index] Either input index or id or name.
     * @param {string|Array.<string>} [condition.id] Either input index or id or name.
     * @param {string|Array.<string>} [condition.name] Either input index or id or name.
     * @return {Array.<module:echarts/model/Component>}
     */
    queryComponents: function (condition) {
        var mainType = condition.mainType;
        if (!mainType) {
            return [];
        }

        var index = condition.index;
        var id = condition.id;
        var name = condition.name;

        var cpts = this._componentsMap.get(mainType);

        if (!cpts || !cpts.length) {
            return [];
        }

        var result;

        if (index != null) {
            if (!isArray(index)) {
                index = [index];
            }
            result = filter(map(index, function (idx) {
                return cpts[idx];
            }), function (val) {
                return !!val;
            });
        }
        else if (id != null) {
            var isIdArray = isArray(id);
            result = filter(cpts, function (cpt) {
                return (isIdArray && indexOf(id, cpt.id) >= 0)
                    || (!isIdArray && cpt.id === id);
            });
        }
        else if (name != null) {
            var isNameArray = isArray(name);
            result = filter(cpts, function (cpt) {
                return (isNameArray && indexOf(name, cpt.name) >= 0)
                    || (!isNameArray && cpt.name === name);
            });
        }
        else {
            // Return all components with mainType
            result = cpts.slice();
        }

        return filterBySubType(result, condition);
    },

    /**
     * The interface is different from queryComponents,
     * which is convenient for inner usage.
     *
     * @usage
     * var result = findComponents(
     *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
     * );
     * var result = findComponents(
     *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
     * );
     * var result = findComponents(
     *     {mainType: 'series',
     *     filter: function (model, index) {...}}
     * );
     * // result like [component0, componnet1, ...]
     *
     * @param {Object} condition
     * @param {string} condition.mainType Mandatory.
     * @param {string} [condition.subType] Optional.
     * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName},
     *        where xxx is mainType.
     *        If query attribute is null/undefined or has no index/id/name,
     *        do not filtering by query conditions, which is convenient for
     *        no-payload situations or when target of action is global.
     * @param {Function} [condition.filter] parameter: component, return boolean.
     * @return {Array.<module:echarts/model/Component>}
     */
    findComponents: function (condition) {
        var query = condition.query;
        var mainType = condition.mainType;

        var queryCond = getQueryCond(query);
        var result = queryCond
            ? this.queryComponents(queryCond)
            : this._componentsMap.get(mainType);

        return doFilter(filterBySubType(result, condition));

        function getQueryCond(q) {
            var indexAttr = mainType + 'Index';
            var idAttr = mainType + 'Id';
            var nameAttr = mainType + 'Name';
            return q && (
                    q[indexAttr] != null
                    || q[idAttr] != null
                    || q[nameAttr] != null
                )
                ? {
                    mainType: mainType,
                    // subType will be filtered finally.
                    index: q[indexAttr],
                    id: q[idAttr],
                    name: q[nameAttr]
                }
                : null;
        }

        function doFilter(res) {
            return condition.filter
                    ? filter(res, condition.filter)
                    : res;
        }
    },

    /**
     * @usage
     * eachComponent('legend', function (legendModel, index) {
     *     ...
     * });
     * eachComponent(function (componentType, model, index) {
     *     // componentType does not include subType
     *     // (componentType is 'xxx' but not 'xxx.aa')
     * });
     * eachComponent(
     *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}},
     *     function (model, index) {...}
     * );
     * eachComponent(
     *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}},
     *     function (model, index) {...}
     * );
     *
     * @param {string|Object=} mainType When mainType is object, the definition
     *                                  is the same as the method 'findComponents'.
     * @param {Function} cb
     * @param {*} context
     */
    eachComponent: function (mainType, cb, context) {
        var componentsMap = this._componentsMap;

        if (typeof mainType === 'function') {
            context = cb;
            cb = mainType;
            componentsMap.each(function (components, componentType) {
                each$1(components, function (component, index) {
                    cb.call(context, componentType, component, index);
                });
            });
        }
        else if (isString(mainType)) {
            each$1(componentsMap.get(mainType), cb, context);
        }
        else if (isObject$1(mainType)) {
            var queryResult = this.findComponents(mainType);
            each$1(queryResult, cb, context);
        }
    },

    /**
     * @param {string} name
     * @return {Array.<module:echarts/model/Series>}
     */
    getSeriesByName: function (name) {
        var series = this._componentsMap.get('series');
        return filter(series, function (oneSeries) {
            return oneSeries.name === name;
        });
    },

    /**
     * @param {number} seriesIndex
     * @return {module:echarts/model/Series}
     */
    getSeriesByIndex: function (seriesIndex) {
        return this._componentsMap.get('series')[seriesIndex];
    },

    /**
     * Get series list before filtered by type.
     * FIXME: rename to getRawSeriesByType?
     *
     * @param {string} subType
     * @return {Array.<module:echarts/model/Series>}
     */
    getSeriesByType: function (subType) {
        var series = this._componentsMap.get('series');
        return filter(series, function (oneSeries) {
            return oneSeries.subType === subType;
        });
    },

    /**
     * @return {Array.<module:echarts/model/Series>}
     */
    getSeries: function () {
        return this._componentsMap.get('series').slice();
    },

    /**
     * @return {number}
     */
    getSeriesCount: function () {
        return this._componentsMap.get('series').length;
    },

    /**
     * After filtering, series may be different
     * frome raw series.
     *
     * @param {Function} cb
     * @param {*} context
     */
    eachSeries: function (cb, context) {
        assertSeriesInitialized(this);
        each$1(this._seriesIndices, function (rawSeriesIndex) {
            var series = this._componentsMap.get('series')[rawSeriesIndex];
            cb.call(context, series, rawSeriesIndex);
        }, this);
    },

    /**
     * Iterate raw series before filtered.
     *
     * @param {Function} cb
     * @param {*} context
     */
    eachRawSeries: function (cb, context) {
        each$1(this._componentsMap.get('series'), cb, context);
    },

    /**
     * After filtering, series may be different.
     * frome raw series.
     *
     * @param {string} subType.
     * @param {Function} cb
     * @param {*} context
     */
    eachSeriesByType: function (subType, cb, context) {
        assertSeriesInitialized(this);
        each$1(this._seriesIndices, function (rawSeriesIndex) {
            var series = this._componentsMap.get('series')[rawSeriesIndex];
            if (series.subType === subType) {
                cb.call(context, series, rawSeriesIndex);
            }
        }, this);
    },

    /**
     * Iterate raw series before filtered of given type.
     *
     * @parma {string} subType
     * @param {Function} cb
     * @param {*} context
     */
    eachRawSeriesByType: function (subType, cb, context) {
        return each$1(this.getSeriesByType(subType), cb, context);
    },

    /**
     * @param {module:echarts/model/Series} seriesModel
     */
    isSeriesFiltered: function (seriesModel) {
        assertSeriesInitialized(this);
        return this._seriesIndicesMap.get(seriesModel.componentIndex) == null;
    },

    /**
     * @return {Array.<number>}
     */
    getCurrentSeriesIndices: function () {
        return (this._seriesIndices || []).slice();
    },

    /**
     * @param {Function} cb
     * @param {*} context
     */
    filterSeries: function (cb, context) {
        assertSeriesInitialized(this);
        var filteredSeries = filter(
            this._componentsMap.get('series'), cb, context
        );
        createSeriesIndices(this, filteredSeries);
    },

    restoreData: function (payload) {
        var componentsMap = this._componentsMap;

        createSeriesIndices(this, componentsMap.get('series'));

        var componentTypes = [];
        componentsMap.each(function (components, componentType) {
            componentTypes.push(componentType);
        });

        ComponentModel.topologicalTravel(
            componentTypes,
            ComponentModel.getAllClassMainTypes(),
            function (componentType, dependencies) {
                each$1(componentsMap.get(componentType), function (component) {
                    (componentType !== 'series' || !isNotTargetSeries(component, payload))
                        && component.restoreData();
                });
            }
        );
    }

});

function isNotTargetSeries(seriesModel, payload) {
    if (payload) {
        var index = payload.seiresIndex;
        var id = payload.seriesId;
        var name = payload.seriesName;
        return (index != null && seriesModel.componentIndex !== index)
            || (id != null && seriesModel.id !== id)
            || (name != null && seriesModel.name !== name);
    }
}

/**
 * @inner
 */
function mergeTheme(option, theme) {
    // PENDING
    // NOT use `colorLayer` in theme if option has `color`
    var notMergeColorLayer = option.color && !option.colorLayer;

    each$1(theme, function (themeItem, name) {
        if (name === 'colorLayer' && notMergeColorLayer) {
            return;
        }
        // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
        if (!ComponentModel.hasClass(name)) {
            if (typeof themeItem === 'object') {
                option[name] = !option[name]
                    ? clone(themeItem)
                    : merge(option[name], themeItem, false);
            }
            else {
                if (option[name] == null) {
                    option[name] = themeItem;
                }
            }
        }
    });
}

function initBase(baseOption) {
    baseOption = baseOption;

    // Using OPTION_INNER_KEY to mark that this option can not be used outside,
    // i.e. `chart.setOption(chart.getModel().option);` is forbiden.
    this.option = {};
    this.option[OPTION_INNER_KEY] = 1;

    /**
     * Init with series: [], in case of calling findSeries method
     * before series initialized.
     * @type {Object.<string, Array.<module:echarts/model/Model>>}
     * @private
     */
    this._componentsMap = createHashMap({series: []});

    /**
     * Mapping between filtered series list and raw series list.
     * key: filtered series indices, value: raw series indices.
     * @type {Array.<nubmer>}
     * @private
     */
    this._seriesIndices;

    this._seriesIndicesMap;

    mergeTheme(baseOption, this._theme.option);

    // TODO Needs clone when merging to the unexisted property
    merge(baseOption, globalDefault, false);

    this.mergeOption(baseOption);
}

/**
 * @inner
 * @param {Array.<string>|string} types model types
 * @return {Object} key: {string} type, value: {Array.<Object>} models
 */
function getComponentsByTypes(componentsMap, types) {
    if (!isArray(types)) {
        types = types ? [types] : [];
    }

    var ret = {};
    each$1(types, function (type) {
        ret[type] = (componentsMap.get(type) || []).slice();
    });

    return ret;
}

/**
 * @inner
 */
function determineSubType(mainType, newCptOption, existComponent) {
    var subType = newCptOption.type
        ? newCptOption.type
        : existComponent
        ? existComponent.subType
        // Use determineSubType only when there is no existComponent.
        : ComponentModel.determineSubType(mainType, newCptOption);

    // tooltip, markline, markpoint may always has no subType
    return subType;
}

/**
 * @inner
 */
function createSeriesIndices(ecModel, seriesModels) {
    ecModel._seriesIndicesMap = createHashMap(
        ecModel._seriesIndices = map(seriesModels, function (series) {
            return series.componentIndex;
        }) || []
    );
}

/**
 * @inner
 */
function filterBySubType(components, condition) {
    // Using hasOwnProperty for restrict. Consider
    // subType is undefined in user payload.
    return condition.hasOwnProperty('subType')
        ? filter(components, function (cpt) {
            return cpt.subType === condition.subType;
        })
        : components;
}

/**
 * @inner
 */
function assertSeriesInitialized(ecModel) {
    // Components that use _seriesIndices should depends on series component,
    // which make sure that their initialization is after series.
    if (__DEV__) {
        if (!ecModel._seriesIndices) {
            throw new Error('Option should contains series.');
        }
    }
}

mixin(GlobalModel, colorPaletteMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var echartsAPIList = [
    'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed',
    'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption',
    'getViewOfComponentModel', 'getViewOfSeriesModel'
];
// And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js

function ExtensionAPI(chartInstance) {
    each$1(echartsAPIList, function (name) {
        this[name] = bind(chartInstance[name], chartInstance);
    }, this);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var coordinateSystemCreators = {};

function CoordinateSystemManager() {

    this._coordinateSystems = [];
}

CoordinateSystemManager.prototype = {

    constructor: CoordinateSystemManager,

    create: function (ecModel, api) {
        var coordinateSystems = [];
        each$1(coordinateSystemCreators, function (creater, type) {
            var list = creater.create(ecModel, api);
            coordinateSystems = coordinateSystems.concat(list || []);
        });

        this._coordinateSystems = coordinateSystems;
    },

    update: function (ecModel, api) {
        each$1(this._coordinateSystems, function (coordSys) {
            coordSys.update && coordSys.update(ecModel, api);
        });
    },

    getCoordinateSystems: function () {
        return this._coordinateSystems.slice();
    }
};

CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
    coordinateSystemCreators[type] = coordinateSystemCreator;
};

CoordinateSystemManager.get = function (type) {
    return coordinateSystemCreators[type];
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * ECharts option manager
 *
 * @module {echarts/model/OptionManager}
 */


var each$4 = each$1;
var clone$3 = clone;
var map$1 = map;
var merge$1 = merge;

var QUERY_REG = /^(min|max)?(.+)$/;

/**
 * TERM EXPLANATIONS:
 *
 * [option]:
 *
 *     An object that contains definitions of components. For example:
 *     var option = {
 *         title: {...},
 *         legend: {...},
 *         visualMap: {...},
 *         series: [
 *             {data: [...]},
 *             {data: [...]},
 *             ...
 *         ]
 *     };
 *
 * [rawOption]:
 *
 *     An object input to echarts.setOption. 'rawOption' may be an
 *     'option', or may be an object contains multi-options. For example:
 *     var option = {
 *         baseOption: {
 *             title: {...},
 *             legend: {...},
 *             series: [
 *                 {data: [...]},
 *                 {data: [...]},
 *                 ...
 *             ]
 *         },
 *         timeline: {...},
 *         options: [
 *             {title: {...}, series: {data: [...]}},
 *             {title: {...}, series: {data: [...]}},
 *             ...
 *         ],
 *         media: [
 *             {
 *                 query: {maxWidth: 320},
 *                 option: {series: {x: 20}, visualMap: {show: false}}
 *             },
 *             {
 *                 query: {minWidth: 320, maxWidth: 720},
 *                 option: {series: {x: 500}, visualMap: {show: true}}
 *             },
 *             {
 *                 option: {series: {x: 1200}, visualMap: {show: true}}
 *             }
 *         ]
 *     };
 *
 * @alias module:echarts/model/OptionManager
 * @param {module:echarts/ExtensionAPI} api
 */
function OptionManager(api) {

    /**
     * @private
     * @type {module:echarts/ExtensionAPI}
     */
    this._api = api;

    /**
     * @private
     * @type {Array.<number>}
     */
    this._timelineOptions = [];

    /**
     * @private
     * @type {Array.<Object>}
     */
    this._mediaList = [];

    /**
     * @private
     * @type {Object}
     */
    this._mediaDefault;

    /**
     * -1, means default.
     * empty means no media.
     * @private
     * @type {Array.<number>}
     */
    this._currentMediaIndices = [];

    /**
     * @private
     * @type {Object}
     */
    this._optionBackup;

    /**
     * @private
     * @type {Object}
     */
    this._newBaseOption;
}

// timeline.notMerge is not supported in ec3. Firstly there is rearly
// case that notMerge is needed. Secondly supporting 'notMerge' requires
// rawOption cloned and backuped when timeline changed, which does no
// good to performance. What's more, that both timeline and setOption
// method supply 'notMerge' brings complex and some problems.
// Consider this case:
// (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);
// (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);

OptionManager.prototype = {

    constructor: OptionManager,

    /**
     * @public
     * @param {Object} rawOption Raw option.
     * @param {module:echarts/model/Global} ecModel
     * @param {Array.<Function>} optionPreprocessorFuncs
     * @return {Object} Init option
     */
    setOption: function (rawOption, optionPreprocessorFuncs) {
        if (rawOption) {
            // That set dat primitive is dangerous if user reuse the data when setOption again.
            each$1(normalizeToArray(rawOption.series), function (series) {
                series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data);
            });
        }

        // Caution: some series modify option data, if do not clone,
        // it should ensure that the repeat modify correctly
        // (create a new object when modify itself).
        rawOption = clone$3(rawOption);

        // FIXME
        // 如果 timeline options 或者 media 中设置了某个属性，而baseOption中没有设置，则进行警告。

        var oldOptionBackup = this._optionBackup;
        var newParsedOption = parseRawOption.call(
            this, rawOption, optionPreprocessorFuncs, !oldOptionBackup
        );
        this._newBaseOption = newParsedOption.baseOption;

        // For setOption at second time (using merge mode);
        if (oldOptionBackup) {
            // Only baseOption can be merged.
            mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption);

            // For simplicity, timeline options and media options do not support merge,
            // that is, if you `setOption` twice and both has timeline options, the latter
            // timeline opitons will not be merged to the formers, but just substitude them.
            if (newParsedOption.timelineOptions.length) {
                oldOptionBackup.timelineOptions = newParsedOption.timelineOptions;
            }
            if (newParsedOption.mediaList.length) {
                oldOptionBackup.mediaList = newParsedOption.mediaList;
            }
            if (newParsedOption.mediaDefault) {
                oldOptionBackup.mediaDefault = newParsedOption.mediaDefault;
            }
        }
        else {
            this._optionBackup = newParsedOption;
        }
    },

    /**
     * @param {boolean} isRecreate
     * @return {Object}
     */
    mountOption: function (isRecreate) {
        var optionBackup = this._optionBackup;

        // TODO
        // 如果没有reset功能则不clone。

        this._timelineOptions = map$1(optionBackup.timelineOptions, clone$3);
        this._mediaList = map$1(optionBackup.mediaList, clone$3);
        this._mediaDefault = clone$3(optionBackup.mediaDefault);
        this._currentMediaIndices = [];

        return clone$3(isRecreate
            // this._optionBackup.baseOption, which is created at the first `setOption`
            // called, and is merged into every new option by inner method `mergeOption`
            // each time `setOption` called, can be only used in `isRecreate`, because
            // its reliability is under suspicion. In other cases option merge is
            // performed by `model.mergeOption`.
            ? optionBackup.baseOption : this._newBaseOption
        );
    },

    /**
     * @param {module:echarts/model/Global} ecModel
     * @return {Object}
     */
    getTimelineOption: function (ecModel) {
        var option;
        var timelineOptions = this._timelineOptions;

        if (timelineOptions.length) {
            // getTimelineOption can only be called after ecModel inited,
            // so we can get currentIndex from timelineModel.
            var timelineModel = ecModel.getComponent('timeline');
            if (timelineModel) {
                option = clone$3(
                    timelineOptions[timelineModel.getCurrentIndex()],
                    true
                );
            }
        }

        return option;
    },

    /**
     * @param {module:echarts/model/Global} ecModel
     * @return {Array.<Object>}
     */
    getMediaOption: function (ecModel) {
        var ecWidth = this._api.getWidth();
        var ecHeight = this._api.getHeight();
        var mediaList = this._mediaList;
        var mediaDefault = this._mediaDefault;
        var indices = [];
        var result = [];

        // No media defined.
        if (!mediaList.length && !mediaDefault) {
            return result;
        }

        // Multi media may be applied, the latter defined media has higher priority.
        for (var i = 0, len = mediaList.length; i < len; i++) {
            if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) {
                indices.push(i);
            }
        }

        // FIXME
        // 是否mediaDefault应该强制用户设置，否则可能修改不能回归。
        if (!indices.length && mediaDefault) {
            indices = [-1];
        }

        if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) {
            result = map$1(indices, function (index) {
                return clone$3(
                    index === -1 ? mediaDefault.option : mediaList[index].option
                );
            });
        }
        // Otherwise return nothing.

        this._currentMediaIndices = indices;

        return result;
    }
};

function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) {
    var timelineOptions = [];
    var mediaList = [];
    var mediaDefault;
    var baseOption;

    // Compatible with ec2.
    var timelineOpt = rawOption.timeline;

    if (rawOption.baseOption) {
        baseOption = rawOption.baseOption;
    }

    // For timeline
    if (timelineOpt || rawOption.options) {
        baseOption = baseOption || {};
        timelineOptions = (rawOption.options || []).slice();
    }

    // For media query
    if (rawOption.media) {
        baseOption = baseOption || {};
        var media = rawOption.media;
        each$4(media, function (singleMedia) {
            if (singleMedia && singleMedia.option) {
                if (singleMedia.query) {
                    mediaList.push(singleMedia);
                }
                else if (!mediaDefault) {
                    // Use the first media default.
                    mediaDefault = singleMedia;
                }
            }
        });
    }

    // For normal option
    if (!baseOption) {
        baseOption = rawOption;
    }

    // Set timelineOpt to baseOption in ec3,
    // which is convenient for merge option.
    if (!baseOption.timeline) {
        baseOption.timeline = timelineOpt;
    }

    // Preprocess.
    each$4([baseOption].concat(timelineOptions)
        .concat(map(mediaList, function (media) {
            return media.option;
        })),
        function (option) {
            each$4(optionPreprocessorFuncs, function (preProcess) {
                preProcess(option, isNew);
            });
        }
    );

    return {
        baseOption: baseOption,
        timelineOptions: timelineOptions,
        mediaDefault: mediaDefault,
        mediaList: mediaList
    };
}

/**
 * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>
 * Support: width, height, aspectRatio
 * Can use max or min as prefix.
 */
function applyMediaQuery(query, ecWidth, ecHeight) {
    var realMap = {
        width: ecWidth,
        height: ecHeight,
        aspectratio: ecWidth / ecHeight // lowser case for convenientce.
    };

    var applicatable = true;

    each$1(query, function (value, attr) {
        var matched = attr.match(QUERY_REG);

        if (!matched || !matched[1] || !matched[2]) {
            return;
        }

        var operator = matched[1];
        var realAttr = matched[2].toLowerCase();

        if (!compare(realMap[realAttr], value, operator)) {
            applicatable = false;
        }
    });

    return applicatable;
}

function compare(real, expect, operator) {
    if (operator === 'min') {
        return real >= expect;
    }
    else if (operator === 'max') {
        return real <= expect;
    }
    else { // Equals
        return real === expect;
    }
}

function indicesEquals(indices1, indices2) {
    // indices is always order by asc and has only finite number.
    return indices1.join(',') === indices2.join(',');
}

/**
 * Consider case:
 * `chart.setOption(opt1);`
 * Then user do some interaction like dataZoom, dataView changing.
 * `chart.setOption(opt2);`
 * Then user press 'reset button' in toolbox.
 *
 * After doing that all of the interaction effects should be reset, the
 * chart should be the same as the result of invoke
 * `chart.setOption(opt1); chart.setOption(opt2);`.
 *
 * Although it is not able ensure that
 * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
 * `chart.setOption(merge(opt1, opt2));` exactly,
 * this might be the only simple way to implement that feature.
 *
 * MEMO: We've considered some other approaches:
 * 1. Each model handle its self restoration but not uniform treatment.
 *     (Too complex in logic and error-prone)
 * 2. Use a shadow ecModel. (Performace expensive)
 */
function mergeOption(oldOption, newOption) {
    newOption = newOption || {};

    each$4(newOption, function (newCptOpt, mainType) {
        if (newCptOpt == null) {
            return;
        }

        var oldCptOpt = oldOption[mainType];

        if (!ComponentModel.hasClass(mainType)) {
            oldOption[mainType] = merge$1(oldCptOpt, newCptOpt, true);
        }
        else {
            newCptOpt = normalizeToArray(newCptOpt);
            oldCptOpt = normalizeToArray(oldCptOpt);

            var mapResult = mappingToExists(oldCptOpt, newCptOpt);

            oldOption[mainType] = map$1(mapResult, function (item) {
                return (item.option && item.exist)
                    ? merge$1(item.exist, item.option, true)
                    : (item.exist || item.option);
            });
        }
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$5 = each$1;
var isObject$3 = isObject$1;

var POSSIBLE_STYLES = [
    'areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle',
    'chordStyle', 'label', 'labelLine'
];

function compatEC2ItemStyle(opt) {
    var itemStyleOpt = opt && opt.itemStyle;
    if (!itemStyleOpt) {
        return;
    }
    for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) {
        var styleName = POSSIBLE_STYLES[i];
        var normalItemStyleOpt = itemStyleOpt.normal;
        var emphasisItemStyleOpt = itemStyleOpt.emphasis;
        if (normalItemStyleOpt && normalItemStyleOpt[styleName]) {
            opt[styleName] = opt[styleName] || {};
            if (!opt[styleName].normal) {
                opt[styleName].normal = normalItemStyleOpt[styleName];
            }
            else {
                merge(opt[styleName].normal, normalItemStyleOpt[styleName]);
            }
            normalItemStyleOpt[styleName] = null;
        }
        if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) {
            opt[styleName] = opt[styleName] || {};
            if (!opt[styleName].emphasis) {
                opt[styleName].emphasis = emphasisItemStyleOpt[styleName];
            }
            else {
                merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]);
            }
            emphasisItemStyleOpt[styleName] = null;
        }
    }
}

function convertNormalEmphasis(opt, optType, useExtend) {
    if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) {
        var normalOpt = opt[optType].normal;
        var emphasisOpt = opt[optType].emphasis;

        if (normalOpt) {
            // Timeline controlStyle has other properties besides normal and emphasis
            if (useExtend) {
                opt[optType].normal = opt[optType].emphasis = null;
                defaults(opt[optType], normalOpt);
            }
            else {
                opt[optType] = normalOpt;
            }
        }
        if (emphasisOpt) {
            opt.emphasis = opt.emphasis || {};
            opt.emphasis[optType] = emphasisOpt;
        }
    }
}

function removeEC3NormalStatus(opt) {
    convertNormalEmphasis(opt, 'itemStyle');
    convertNormalEmphasis(opt, 'lineStyle');
    convertNormalEmphasis(opt, 'areaStyle');
    convertNormalEmphasis(opt, 'label');
    convertNormalEmphasis(opt, 'labelLine');
    // treemap
    convertNormalEmphasis(opt, 'upperLabel');
    // graph
    convertNormalEmphasis(opt, 'edgeLabel');
}

function compatTextStyle(opt, propName) {
    // Check whether is not object (string\null\undefined ...)
    var labelOptSingle = isObject$3(opt) && opt[propName];
    var textStyle = isObject$3(labelOptSingle) && labelOptSingle.textStyle;
    if (textStyle) {
        for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) {
            var propName = TEXT_STYLE_OPTIONS[i];
            if (textStyle.hasOwnProperty(propName)) {
                labelOptSingle[propName] = textStyle[propName];
            }
        }
    }
}

function compatEC3CommonStyles(opt) {
    if (opt) {
        removeEC3NormalStatus(opt);
        compatTextStyle(opt, 'label');
        opt.emphasis && compatTextStyle(opt.emphasis, 'label');
    }
}

function processSeries(seriesOpt) {
    if (!isObject$3(seriesOpt)) {
        return;
    }

    compatEC2ItemStyle(seriesOpt);
    removeEC3NormalStatus(seriesOpt);

    compatTextStyle(seriesOpt, 'label');
    // treemap
    compatTextStyle(seriesOpt, 'upperLabel');
    // graph
    compatTextStyle(seriesOpt, 'edgeLabel');
    if (seriesOpt.emphasis) {
        compatTextStyle(seriesOpt.emphasis, 'label');
        // treemap
        compatTextStyle(seriesOpt.emphasis, 'upperLabel');
        // graph
        compatTextStyle(seriesOpt.emphasis, 'edgeLabel');
    }

    var markPoint = seriesOpt.markPoint;
    if (markPoint) {
        compatEC2ItemStyle(markPoint);
        compatEC3CommonStyles(markPoint);
    }

    var markLine = seriesOpt.markLine;
    if (markLine) {
        compatEC2ItemStyle(markLine);
        compatEC3CommonStyles(markLine);
    }

    var markArea = seriesOpt.markArea;
    if (markArea) {
        compatEC3CommonStyles(markArea);
    }

    var data = seriesOpt.data;

    // Break with ec3: if `setOption` again, there may be no `type` in option,
    // then the backward compat based on option type will not be performed.

    if (seriesOpt.type === 'graph') {
        data = data || seriesOpt.nodes;
        var edgeData = seriesOpt.links || seriesOpt.edges;
        if (edgeData && !isTypedArray(edgeData)) {
            for (var i = 0; i < edgeData.length; i++) {
                compatEC3CommonStyles(edgeData[i]);
            }
        }
        each$1(seriesOpt.categories, function (opt) {
            removeEC3NormalStatus(opt);
        });
    }

    if (data && !isTypedArray(data)) {
        for (var i = 0; i < data.length; i++) {
            compatEC3CommonStyles(data[i]);
        }
    }

    // mark point data
    var markPoint = seriesOpt.markPoint;
    if (markPoint && markPoint.data) {
        var mpData = markPoint.data;
        for (var i = 0; i < mpData.length; i++) {
            compatEC3CommonStyles(mpData[i]);
        }
    }
    // mark line data
    var markLine = seriesOpt.markLine;
    if (markLine && markLine.data) {
        var mlData = markLine.data;
        for (var i = 0; i < mlData.length; i++) {
            if (isArray(mlData[i])) {
                compatEC3CommonStyles(mlData[i][0]);
                compatEC3CommonStyles(mlData[i][1]);
            }
            else {
                compatEC3CommonStyles(mlData[i]);
            }
        }
    }

    // Series
    if (seriesOpt.type === 'gauge') {
        compatTextStyle(seriesOpt, 'axisLabel');
        compatTextStyle(seriesOpt, 'title');
        compatTextStyle(seriesOpt, 'detail');
    }
    else if (seriesOpt.type === 'treemap') {
        convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle');
        each$1(seriesOpt.levels, function (opt) {
            removeEC3NormalStatus(opt);
        });
    }
    else if (seriesOpt.type === 'tree') {
        removeEC3NormalStatus(seriesOpt.leaves);
    }
    // sunburst starts from ec4, so it does not need to compat levels.
}

function toArr(o) {
    return isArray(o) ? o : o ? [o] : [];
}

function toObj(o) {
    return (isArray(o) ? o[0] : o) || {};
}

var compatStyle = function (option, isTheme) {
    each$5(toArr(option.series), function (seriesOpt) {
        isObject$3(seriesOpt) && processSeries(seriesOpt);
    });

    var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar'];
    isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis');

    each$5(
        axes,
        function (axisName) {
            each$5(toArr(option[axisName]), function (axisOpt) {
                if (axisOpt) {
                    compatTextStyle(axisOpt, 'axisLabel');
                    compatTextStyle(axisOpt.axisPointer, 'label');
                }
            });
        }
    );

    each$5(toArr(option.parallel), function (parallelOpt) {
        var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault;
        compatTextStyle(parallelAxisDefault, 'axisLabel');
        compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label');
    });

    each$5(toArr(option.calendar), function (calendarOpt) {
        convertNormalEmphasis(calendarOpt, 'itemStyle');
        compatTextStyle(calendarOpt, 'dayLabel');
        compatTextStyle(calendarOpt, 'monthLabel');
        compatTextStyle(calendarOpt, 'yearLabel');
    });

    // radar.name.textStyle
    each$5(toArr(option.radar), function (radarOpt) {
        compatTextStyle(radarOpt, 'name');
    });

    each$5(toArr(option.geo), function (geoOpt) {
        if (isObject$3(geoOpt)) {
            compatEC3CommonStyles(geoOpt);
            each$5(toArr(geoOpt.regions), function (regionObj) {
                compatEC3CommonStyles(regionObj);
            });
        }
    });

    each$5(toArr(option.timeline), function (timelineOpt) {
        compatEC3CommonStyles(timelineOpt);
        convertNormalEmphasis(timelineOpt, 'label');
        convertNormalEmphasis(timelineOpt, 'itemStyle');
        convertNormalEmphasis(timelineOpt, 'controlStyle', true);

        var data = timelineOpt.data;
        isArray(data) && each$1(data, function (item) {
            if (isObject$1(item)) {
                convertNormalEmphasis(item, 'label');
                convertNormalEmphasis(item, 'itemStyle');
            }
        });
    });

    each$5(toArr(option.toolbox), function (toolboxOpt) {
        convertNormalEmphasis(toolboxOpt, 'iconStyle');
        each$5(toolboxOpt.feature, function (featureOpt) {
            convertNormalEmphasis(featureOpt, 'iconStyle');
        });
    });

    compatTextStyle(toObj(option.axisPointer), 'label');
    compatTextStyle(toObj(option.tooltip).axisPointer, 'label');
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Compatitable with 2.0

function get(opt, path) {
    path = path.split(',');
    var obj = opt;
    for (var i = 0; i < path.length; i++) {
        obj = obj && obj[path[i]];
        if (obj == null) {
            break;
        }
    }
    return obj;
}

function set$1(opt, path, val, overwrite) {
    path = path.split(',');
    var obj = opt;
    var key;
    for (var i = 0; i < path.length - 1; i++) {
        key = path[i];
        if (obj[key] == null) {
            obj[key] = {};
        }
        obj = obj[key];
    }
    if (overwrite || obj[path[i]] == null) {
        obj[path[i]] = val;
    }
}

function compatLayoutProperties(option) {
    each$1(LAYOUT_PROPERTIES, function (prop) {
        if (prop[0] in option && !(prop[1] in option)) {
            option[prop[1]] = option[prop[0]];
        }
    });
}

var LAYOUT_PROPERTIES = [
    ['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']
];

var COMPATITABLE_COMPONENTS = [
    'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline'
];

var backwardCompat = function (option, isTheme) {
    compatStyle(option, isTheme);

    // Make sure series array for model initialization.
    option.series = normalizeToArray(option.series);

    each$1(option.series, function (seriesOpt) {
        if (!isObject$1(seriesOpt)) {
            return;
        }

        var seriesType = seriesOpt.type;

        if (seriesType === 'line') {
            if (seriesOpt.clipOverflow != null) {
                seriesOpt.clip = seriesOpt.clipOverflow;
            }
        }
        else if (seriesType === 'pie' || seriesType === 'gauge') {
            if (seriesOpt.clockWise != null) {
                seriesOpt.clockwise = seriesOpt.clockWise;
            }
        }
        else if (seriesType === 'gauge') {
            var pointerColor = get(seriesOpt, 'pointer.color');
            pointerColor != null
                && set$1(seriesOpt, 'itemStyle.color', pointerColor);
        }

        compatLayoutProperties(seriesOpt);
    });

    // dataRange has changed to visualMap
    if (option.dataRange) {
        option.visualMap = option.dataRange;
    }

    each$1(COMPATITABLE_COMPONENTS, function (componentName) {
        var options = option[componentName];
        if (options) {
            if (!isArray(options)) {
                options = [options];
            }
            each$1(options, function (option) {
                compatLayoutProperties(option);
            });
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// (1) [Caution]: the logic is correct based on the premises:
//     data processing stage is blocked in stream.
//     See <module:echarts/stream/Scheduler#performDataProcessorTasks>
// (2) Only register once when import repeatly.
//     Should be executed after series filtered and before stack calculation.
var dataStack = function (ecModel) {
    var stackInfoMap = createHashMap();
    ecModel.eachSeries(function (seriesModel) {
        var stack = seriesModel.get('stack');
        // Compatibal: when `stack` is set as '', do not stack.
        if (stack) {
            var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []);
            var data = seriesModel.getData();

            var stackInfo = {
                // Used for calculate axis extent automatically.
                stackResultDimension: data.getCalculationInfo('stackResultDimension'),
                stackedOverDimension: data.getCalculationInfo('stackedOverDimension'),
                stackedDimension: data.getCalculationInfo('stackedDimension'),
                stackedByDimension: data.getCalculationInfo('stackedByDimension'),
                isStackedByIndex: data.getCalculationInfo('isStackedByIndex'),
                data: data,
                seriesModel: seriesModel
            };

            // If stacked on axis that do not support data stack.
            if (!stackInfo.stackedDimension
                || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)
            ) {
                return;
            }

            stackInfoList.length && data.setCalculationInfo(
                'stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel
            );

            stackInfoList.push(stackInfo);
        }
    });

    stackInfoMap.each(calculateStack);
};

function calculateStack(stackInfoList) {
    each$1(stackInfoList, function (targetStackInfo, idxInStack) {
        var resultVal = [];
        var resultNaN = [NaN, NaN];
        var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension];
        var targetData = targetStackInfo.data;
        var isStackedByIndex = targetStackInfo.isStackedByIndex;

        // Should not write on raw data, because stack series model list changes
        // depending on legend selection.
        var newData = targetData.map(dims, function (v0, v1, dataIndex) {
            var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex);

            // Consider `connectNulls` of line area, if value is NaN, stackedOver
            // should also be NaN, to draw a appropriate belt area.
            if (isNaN(sum)) {
                return resultNaN;
            }

            var byValue;
            var stackedDataRawIndex;

            if (isStackedByIndex) {
                stackedDataRawIndex = targetData.getRawIndex(dataIndex);
            }
            else {
                byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex);
            }

            // If stackOver is NaN, chart view will render point on value start.
            var stackedOver = NaN;

            for (var j = idxInStack - 1; j >= 0; j--) {
                var stackInfo = stackInfoList[j];

                // Has been optimized by inverted indices on `stackedByDimension`.
                if (!isStackedByIndex) {
                    stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue);
                }

                if (stackedDataRawIndex >= 0) {
                    var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex);

                    // Considering positive stack, negative stack and empty data
                    if ((sum >= 0 && val > 0) // Positive stack
                        || (sum <= 0 && val < 0) // Negative stack
                    ) {
                        sum += val;
                        stackedOver = val;
                        break;
                    }
                }
            }

            resultVal[0] = sum;
            resultVal[1] = stackedOver;

            return resultVal;
        });

        targetData.hostModel.setData(newData);
        // Update for consequent calculation
        targetStackInfo.data = newData;
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO
// ??? refactor? check the outer usage of data provider.
// merge with defaultDimValueGetter?

/**
 * If normal array used, mutable chunk size is supported.
 * If typed array used, chunk size must be fixed.
 */
function DefaultDataProvider(source, dimSize) {
    if (!Source.isInstance(source)) {
        source = Source.seriesDataToSource(source);
    }
    this._source = source;

    var data = this._data = source.data;
    var sourceFormat = source.sourceFormat;

    // Typed array. TODO IE10+?
    if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
        if (__DEV__) {
            if (dimSize == null) {
                throw new Error('Typed array data must specify dimension size');
            }
        }
        this._offset = 0;
        this._dimSize = dimSize;
        this._data = data;
    }

    var methods = providerMethods[
        sourceFormat === SOURCE_FORMAT_ARRAY_ROWS
        ? sourceFormat + '_' + source.seriesLayoutBy
        : sourceFormat
    ];

    if (__DEV__) {
        assert$1(methods, 'Invalide sourceFormat: ' + sourceFormat);
    }

    extend(this, methods);
}

var providerProto = DefaultDataProvider.prototype;
// If data is pure without style configuration
providerProto.pure = false;
// If data is persistent and will not be released after use.
providerProto.persistent = true;

// ???! FIXME legacy data provider do not has method getSource
providerProto.getSource = function () {
    return this._source;
};

var providerMethods = {

    'arrayRows_column': {
        pure: true,
        count: function () {
            return Math.max(0, this._data.length - this._source.startIndex);
        },
        getItem: function (idx) {
            return this._data[idx + this._source.startIndex];
        },
        appendData: appendDataSimply
    },

    'arrayRows_row': {
        pure: true,
        count: function () {
            var row = this._data[0];
            return row ? Math.max(0, row.length - this._source.startIndex) : 0;
        },
        getItem: function (idx) {
            idx += this._source.startIndex;
            var item = [];
            var data = this._data;
            for (var i = 0; i < data.length; i++) {
                var row = data[i];
                item.push(row ? row[idx] : null);
            }
            return item;
        },
        appendData: function () {
            throw new Error('Do not support appendData when set seriesLayoutBy: "row".');
        }
    },

    'objectRows': {
        pure: true,
        count: countSimply,
        getItem: getItemSimply,
        appendData: appendDataSimply
    },

    'keyedColumns': {
        pure: true,
        count: function () {
            var dimName = this._source.dimensionsDefine[0].name;
            var col = this._data[dimName];
            return col ? col.length : 0;
        },
        getItem: function (idx) {
            var item = [];
            var dims = this._source.dimensionsDefine;
            for (var i = 0; i < dims.length; i++) {
                var col = this._data[dims[i].name];
                item.push(col ? col[idx] : null);
            }
            return item;
        },
        appendData: function (newData) {
            var data = this._data;
            each$1(newData, function (newCol, key) {
                var oldCol = data[key] || (data[key] = []);
                for (var i = 0; i < (newCol || []).length; i++) {
                    oldCol.push(newCol[i]);
                }
            });
        }
    },

    'original': {
        count: countSimply,
        getItem: getItemSimply,
        appendData: appendDataSimply
    },

    'typedArray': {
        persistent: false,
        pure: true,
        count: function () {
            return this._data ? (this._data.length / this._dimSize) : 0;
        },
        getItem: function (idx, out) {
            idx = idx - this._offset;
            out = out || [];
            var offset = this._dimSize * idx;
            for (var i = 0; i < this._dimSize; i++) {
                out[i] = this._data[offset + i];
            }
            return out;
        },
        appendData: function (newData) {
            if (__DEV__) {
                assert$1(
                    isTypedArray(newData),
                    'Added data must be TypedArray if data in initialization is TypedArray'
                );
            }

            this._data = newData;
        },

        // Clean self if data is already used.
        clean: function () {
            // PENDING
            this._offset += this.count();
            this._data = null;
        }
    }
};

function countSimply() {
    return this._data.length;
}
function getItemSimply(idx) {
    return this._data[idx];
}
function appendDataSimply(newData) {
    for (var i = 0; i < newData.length; i++) {
        this._data.push(newData[i]);
    }
}



var rawValueGetters = {

    arrayRows: getRawValueSimply,

    objectRows: function (dataItem, dataIndex, dimIndex, dimName) {
        return dimIndex != null ? dataItem[dimName] : dataItem;
    },

    keyedColumns: getRawValueSimply,

    original: function (dataItem, dataIndex, dimIndex, dimName) {
        // FIXME
        // In some case (markpoint in geo (geo-map.html)), dataItem
        // is {coord: [...]}
        var value = getDataItemValue(dataItem);
        return (dimIndex == null || !(value instanceof Array))
            ? value
            : value[dimIndex];
    },

    typedArray: getRawValueSimply
};

function getRawValueSimply(dataItem, dataIndex, dimIndex, dimName) {
    return dimIndex != null ? dataItem[dimIndex] : dataItem;
}


var defaultDimValueGetters = {

    arrayRows: getDimValueSimply,

    objectRows: function (dataItem, dimName, dataIndex, dimIndex) {
        return converDataValue(dataItem[dimName], this._dimensionInfos[dimName]);
    },

    keyedColumns: getDimValueSimply,

    original: function (dataItem, dimName, dataIndex, dimIndex) {
        // Performance sensitive, do not use modelUtil.getDataItemValue.
        // If dataItem is an plain object with no value field, the var `value`
        // will be assigned with the object, but it will be tread correctly
        // in the `convertDataValue`.
        var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value);

        // If any dataItem is like { value: 10 }
        if (!this._rawData.pure && isDataItemOption(dataItem)) {
            this.hasItemOption = true;
        }
        return converDataValue(
            (value instanceof Array)
                ? value[dimIndex]
                // If value is a single number or something else not array.
                : value,
            this._dimensionInfos[dimName]
        );
    },

    typedArray: function (dataItem, dimName, dataIndex, dimIndex) {
        return dataItem[dimIndex];
    }

};

function getDimValueSimply(dataItem, dimName, dataIndex, dimIndex) {
    return converDataValue(dataItem[dimIndex], this._dimensionInfos[dimName]);
}

/**
 * This helper method convert value in data.
 * @param {string|number|Date} value
 * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'.
 *        If "dimInfo.ordinalParseAndSave", ordinal value can be parsed.
 */
function converDataValue(value, dimInfo) {
    // Performance sensitive.
    var dimType = dimInfo && dimInfo.type;
    if (dimType === 'ordinal') {
        // If given value is a category string
        var ordinalMeta = dimInfo && dimInfo.ordinalMeta;
        return ordinalMeta
            ? ordinalMeta.parseAndCollect(value)
            : value;
    }

    if (dimType === 'time'
        // spead up when using timestamp
        && typeof value !== 'number'
        && value != null
        && value !== '-'
    ) {
        value = +parseDate(value);
    }

    // dimType defaults 'number'.
    // If dimType is not ordinal and value is null or undefined or NaN or '-',
    // parse to NaN.
    return (value == null || value === '')
        ? NaN
        // If string (like '-'), using '+' parse to NaN
        // If object, also parse to NaN
        : +value;
}

// ??? FIXME can these logic be more neat: getRawValue, getRawDataItem,
// Consider persistent.
// Caution: why use raw value to display on label or tooltip?
// A reason is to avoid format. For example time value we do not know
// how to format is expected. More over, if stack is used, calculated
// value may be 0.91000000001, which have brings trouble to display.
// TODO: consider how to treat null/undefined/NaN when display?
/**
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @param {string|number} [dim] dimName or dimIndex
 * @return {Array.<number>|string|number} can be null/undefined.
 */
function retrieveRawValue(data, dataIndex, dim) {
    if (!data) {
        return;
    }

    // Consider data may be not persistent.
    var dataItem = data.getRawDataItem(dataIndex);

    if (dataItem == null) {
        return;
    }

    var sourceFormat = data.getProvider().getSource().sourceFormat;
    var dimName;
    var dimIndex;

    var dimInfo = data.getDimensionInfo(dim);
    if (dimInfo) {
        dimName = dimInfo.name;
        dimIndex = dimInfo.index;
    }

    return rawValueGetters[sourceFormat](dataItem, dataIndex, dimIndex, dimName);
}

/**
 * Compatible with some cases (in pie, map) like:
 * data: [{name: 'xx', value: 5, selected: true}, ...]
 * where only sourceFormat is 'original' and 'objectRows' supported.
 *
 * ??? TODO
 * Supported detail options in data item when using 'arrayRows'.
 *
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @param {string} attr like 'selected'
 */
function retrieveRawAttr(data, dataIndex, attr) {
    if (!data) {
        return;
    }

    var sourceFormat = data.getProvider().getSource().sourceFormat;

    if (sourceFormat !== SOURCE_FORMAT_ORIGINAL
        && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS
    ) {
        return;
    }

    var dataItem = data.getRawDataItem(dataIndex);
    if (sourceFormat === SOURCE_FORMAT_ORIGINAL && !isObject$1(dataItem)) {
        dataItem = null;
    }
    if (dataItem) {
        return dataItem[attr];
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DIMENSION_LABEL_REG = /\{@(.+?)\}/g;

// PENDING A little ugly
var dataFormatMixin = {
    /**
     * Get params for formatter
     * @param {number} dataIndex
     * @param {string} [dataType]
     * @return {Object}
     */
    getDataParams: function (dataIndex, dataType) {
        var data = this.getData(dataType);
        var rawValue = this.getRawValue(dataIndex, dataType);
        var rawDataIndex = data.getRawIndex(dataIndex);
        var name = data.getName(dataIndex);
        var itemOpt = data.getRawDataItem(dataIndex);
        var color = data.getItemVisual(dataIndex, 'color');
        var borderColor = data.getItemVisual(dataIndex, 'borderColor');
        var tooltipModel = this.ecModel.getComponent('tooltip');
        var renderModeOption = tooltipModel && tooltipModel.get('renderMode');
        var renderMode = getTooltipRenderMode(renderModeOption);
        var mainType = this.mainType;
        var isSeries = mainType === 'series';
        var userOutput = data.userOutput;

        return {
            componentType: mainType,
            componentSubType: this.subType,
            componentIndex: this.componentIndex,
            seriesType: isSeries ? this.subType : null,
            seriesIndex: this.seriesIndex,
            seriesId: isSeries ? this.id : null,
            seriesName: isSeries ? this.name : null,
            name: name,
            dataIndex: rawDataIndex,
            data: itemOpt,
            dataType: dataType,
            value: rawValue,
            color: color,
            borderColor: borderColor,
            dimensionNames: userOutput ? userOutput.dimensionNames : null,
            encode: userOutput ? userOutput.encode : null,
            marker: getTooltipMarker({
                color: color,
                renderMode: renderMode
            }),

            // Param name list for mapping `a`, `b`, `c`, `d`, `e`
            $vars: ['seriesName', 'name', 'value']
        };
    },

    /**
     * Format label
     * @param {number} dataIndex
     * @param {string} [status='normal'] 'normal' or 'emphasis'
     * @param {string} [dataType]
     * @param {number} [dimIndex] Only used in some chart that
     *        use formatter in different dimensions, like radar.
     * @param {string} [labelProp='label']
     * @return {string} If not formatter, return null/undefined
     */
    getFormattedLabel: function (dataIndex, status, dataType, dimIndex, labelProp) {
        status = status || 'normal';
        var data = this.getData(dataType);
        var itemModel = data.getItemModel(dataIndex);

        var params = this.getDataParams(dataIndex, dataType);
        if (dimIndex != null && (params.value instanceof Array)) {
            params.value = params.value[dimIndex];
        }

        var formatter = itemModel.get(
            status === 'normal'
            ? [labelProp || 'label', 'formatter']
            : [status, labelProp || 'label', 'formatter']
        );

        if (typeof formatter === 'function') {
            params.status = status;
            params.dimensionIndex = dimIndex;
            return formatter(params);
        }
        else if (typeof formatter === 'string') {
            var str = formatTpl(formatter, params);

            // Support 'aaa{@[3]}bbb{@product}ccc'.
            // Do not support '}' in dim name util have to.
            return str.replace(DIMENSION_LABEL_REG, function (origin, dim) {
                var len = dim.length;
                if (dim.charAt(0) === '[' && dim.charAt(len - 1) === ']') {
                    dim = +dim.slice(1, len - 1); // Also: '[]' => 0
                }
                return retrieveRawValue(data, dataIndex, dim);
            });
        }
    },

    /**
     * Get raw value in option
     * @param {number} idx
     * @param {string} [dataType]
     * @return {Array|number|string}
     */
    getRawValue: function (idx, dataType) {
        return retrieveRawValue(this.getData(dataType), idx);
    },

    /**
     * Should be implemented.
     * @param {number} dataIndex
     * @param {boolean} [multipleSeries=false]
     * @param {number} [dataType]
     * @return {string} tooltip string
     */
    formatTooltip: function () {
        // Empty function
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {Object} define
 * @return See the return of `createTask`.
 */
function createTask(define) {
    return new Task(define);
}

/**
 * @constructor
 * @param {Object} define
 * @param {Function} define.reset Custom reset
 * @param {Function} [define.plan] Returns 'reset' indicate reset immediately.
 * @param {Function} [define.count] count is used to determin data task.
 * @param {Function} [define.onDirty] count is used to determin data task.
 */
function Task(define) {
    define = define || {};

    this._reset = define.reset;
    this._plan = define.plan;
    this._count = define.count;
    this._onDirty = define.onDirty;

    this._dirty = true;

    // Context must be specified implicitly, to
    // avoid miss update context when model changed.
    this.context;
}

var taskProto = Task.prototype;

/**
 * @param {Object} performArgs
 * @param {number} [performArgs.step] Specified step.
 * @param {number} [performArgs.skip] Skip customer perform call.
 * @param {number} [performArgs.modBy] Sampling window size.
 * @param {number} [performArgs.modDataCount] Sampling count.
 */
taskProto.perform = function (performArgs) {
    var upTask = this._upstream;
    var skip = performArgs && performArgs.skip;

    // TODO some refactor.
    // Pull data. Must pull data each time, because context.data
    // may be updated by Series.setData.
    if (this._dirty && upTask) {
        var context = this.context;
        context.data = context.outputData = upTask.context.outputData;
    }

    if (this.__pipeline) {
        this.__pipeline.currentTask = this;
    }

    var planResult;
    if (this._plan && !skip) {
        planResult = this._plan(this.context);
    }

    // Support sharding by mod, which changes the render sequence and makes the rendered graphic
    // elements uniformed distributed when progress, especially when moving or zooming.
    var lastModBy = normalizeModBy(this._modBy);
    var lastModDataCount = this._modDataCount || 0;
    var modBy = normalizeModBy(performArgs && performArgs.modBy);
    var modDataCount = performArgs && performArgs.modDataCount || 0;
    if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
        planResult = 'reset';
    }

    function normalizeModBy(val) {
        !(val >= 1) && (val = 1); // jshint ignore:line
        return val;
    }

    var forceFirstProgress;
    if (this._dirty || planResult === 'reset') {
        this._dirty = false;
        forceFirstProgress = reset(this, skip);
    }

    this._modBy = modBy;
    this._modDataCount = modDataCount;

    var step = performArgs && performArgs.step;

    if (upTask) {

        if (__DEV__) {
            assert$1(upTask._outputDueEnd != null);
        }
        this._dueEnd = upTask._outputDueEnd;
    }
    // DataTask or overallTask
    else {
        if (__DEV__) {
            assert$1(!this._progress || this._count);
        }
        this._dueEnd = this._count ? this._count(this.context) : Infinity;
    }

    // Note: Stubs, that its host overall task let it has progress, has progress.
    // If no progress, pass index from upstream to downstream each time plan called.
    if (this._progress) {
        var start = this._dueIndex;
        var end = Math.min(
            step != null ? this._dueIndex + step : Infinity,
            this._dueEnd
        );

        if (!skip && (forceFirstProgress || start < end)) {
            var progress = this._progress;
            if (isArray(progress)) {
                for (var i = 0; i < progress.length; i++) {
                    doProgress(this, progress[i], start, end, modBy, modDataCount);
                }
            }
            else {
                doProgress(this, progress, start, end, modBy, modDataCount);
            }
        }

        this._dueIndex = end;
        // If no `outputDueEnd`, assume that output data and
        // input data is the same, so use `dueIndex` as `outputDueEnd`.
        var outputDueEnd = this._settedOutputEnd != null
            ? this._settedOutputEnd : end;

        if (__DEV__) {
            // ??? Can not rollback.
            assert$1(outputDueEnd >= this._outputDueEnd);
        }

        this._outputDueEnd = outputDueEnd;
    }
    else {
        // (1) Some overall task has no progress.
        // (2) Stubs, that its host overall task do not let it has progress, has no progress.
        // This should always be performed so it can be passed to downstream.
        this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null
            ? this._settedOutputEnd : this._dueEnd;
    }

    return this.unfinished();
};

var iterator = (function () {

    var end;
    var current;
    var modBy;
    var modDataCount;
    var winCount;

    var it = {
        reset: function (s, e, sStep, sCount) {
            current = s;
            end = e;

            modBy = sStep;
            modDataCount = sCount;
            winCount = Math.ceil(modDataCount / modBy);

            it.next = (modBy > 1 && modDataCount > 0) ? modNext : sequentialNext;
        }
    };

    return it;

    function sequentialNext() {
        return current < end ? current++ : null;
    }

    function modNext() {
        var dataIndex = (current % winCount) * modBy + Math.ceil(current / winCount);
        var result = current >= end
            ? null
            : dataIndex < modDataCount
            ? dataIndex
            // If modDataCount is smaller than data.count() (consider `appendData` case),
            // Use normal linear rendering mode.
            : current;
        current++;
        return result;
    }
})();

taskProto.dirty = function () {
    this._dirty = true;
    this._onDirty && this._onDirty(this.context);
};

function doProgress(taskIns, progress, start, end, modBy, modDataCount) {
    iterator.reset(start, end, modBy, modDataCount);
    taskIns._callingProgress = progress;
    taskIns._callingProgress({
        start: start, end: end, count: end - start, next: iterator.next
    }, taskIns.context);
}

function reset(taskIns, skip) {
    taskIns._dueIndex = taskIns._outputDueEnd = taskIns._dueEnd = 0;
    taskIns._settedOutputEnd = null;

    var progress;
    var forceFirstProgress;

    if (!skip && taskIns._reset) {
        progress = taskIns._reset(taskIns.context);
        if (progress && progress.progress) {
            forceFirstProgress = progress.forceFirstProgress;
            progress = progress.progress;
        }
        // To simplify no progress checking, array must has item.
        if (isArray(progress) && !progress.length) {
            progress = null;
        }
    }

    taskIns._progress = progress;
    taskIns._modBy = taskIns._modDataCount = null;

    var downstream = taskIns._downstream;
    downstream && downstream.dirty();

    return forceFirstProgress;
}

/**
 * @return {boolean}
 */
taskProto.unfinished = function () {
    return this._progress && this._dueIndex < this._dueEnd;
};

/**
 * @param {Object} downTask The downstream task.
 * @return {Object} The downstream task.
 */
taskProto.pipe = function (downTask) {
    if (__DEV__) {
        assert$1(downTask && !downTask._disposed && downTask !== this);
    }

    // If already downstream, do not dirty downTask.
    if (this._downstream !== downTask || this._dirty) {
        this._downstream = downTask;
        downTask._upstream = this;
        downTask.dirty();
    }
};

taskProto.dispose = function () {
    if (this._disposed) {
        return;
    }

    this._upstream && (this._upstream._downstream = null);
    this._downstream && (this._downstream._upstream = null);

    this._dirty = false;
    this._disposed = true;
};

taskProto.getUpstream = function () {
    return this._upstream;
};

taskProto.getDownstream = function () {
    return this._downstream;
};

taskProto.setOutputEnd = function (end) {
    // This only happend in dataTask, dataZoom, map, currently.
    // where dataZoom do not set end each time, but only set
    // when reset. So we should record the setted end, in case
    // that the stub of dataZoom perform again and earse the
    // setted end by upstream.
    this._outputDueEnd = this._settedOutputEnd = end;
};


///////////////////////////////////////////////////////////
// For stream debug (Should be commented out after used!)
// Usage: printTask(this, 'begin');
// Usage: printTask(this, null, {someExtraProp});
// function printTask(task, prefix, extra) {
//     window.ecTaskUID == null && (window.ecTaskUID = 0);
//     task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);
//     task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);
//     var props = [];
//     if (task.__pipeline) {
//         var val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;
//         props.push({text: 'idx', value: val});
//     } else {
//         var stubCount = 0;
//         task.agentStubMap.each(() => stubCount++);
//         props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});
//     }
//     props.push({text: 'uid', value: task.uidDebug});
//     if (task.__pipeline) {
//         props.push({text: 'pid', value: task.__pipeline.id});
//         task.agent && props.push(
//             {text: 'stubFor', value: task.agent.uidDebug}
//         );
//     }
//     props.push(
//         {text: 'dirty', value: task._dirty},
//         {text: 'dueIndex', value: task._dueIndex},
//         {text: 'dueEnd', value: task._dueEnd},
//         {text: 'outputDueEnd', value: task._outputDueEnd}
//     );
//     if (extra) {
//         Object.keys(extra).forEach(key => {
//             props.push({text: key, value: extra[key]});
//         });
//     }
//     var args = ['color: blue'];
//     var msg = `%c[${prefix || 'T'}] %c` + props.map(item => (
//         args.push('color: black', 'color: red'),
//         `${item.text}: %c${item.value}`
//     )).join('%c, ');
//     console.log.apply(console, [msg].concat(args));
//     // console.log(this);
// }

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$4 = makeInner();

var SeriesModel = ComponentModel.extend({

    type: 'series.__base__',

    /**
     * @readOnly
     */
    seriesIndex: 0,

    // coodinateSystem will be injected in the echarts/CoordinateSystem
    coordinateSystem: null,

    /**
     * @type {Object}
     * @protected
     */
    defaultOption: null,

    /**
     * Data provided for legend
     * @type {Function}
     */
    // PENDING
    legendDataProvider: null,

    /**
     * Access path of color for visual
     */
    visualColorAccessPath: 'itemStyle.color',

    /**
     * Access path of borderColor for visual
     */
    visualBorderColorAccessPath: 'itemStyle.borderColor',

    /**
     * Support merge layout params.
     * Only support 'box' now (left/right/top/bottom/width/height).
     * @type {string|Object} Object can be {ignoreSize: true}
     * @readOnly
     */
    layoutMode: null,

    init: function (option, parentModel, ecModel, extraOpt) {

        /**
         * @type {number}
         * @readOnly
         */
        this.seriesIndex = this.componentIndex;

        this.dataTask = createTask({
            count: dataTaskCount,
            reset: dataTaskReset
        });
        this.dataTask.context = {model: this};

        this.mergeDefaultAndTheme(option, ecModel);

        prepareSource(this);


        var data = this.getInitialData(option, ecModel);
        wrapData(data, this);
        this.dataTask.context.data = data;

        if (__DEV__) {
            assert$1(data, 'getInitialData returned invalid data.');
        }

        /**
         * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
         * @private
         */
        inner$4(this).dataBeforeProcessed = data;

        // If we reverse the order (make data firstly, and then make
        // dataBeforeProcessed by cloneShallow), cloneShallow will
        // cause data.graph.data !== data when using
        // module:echarts/data/Graph or module:echarts/data/Tree.
        // See module:echarts/data/helper/linkList

        // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model
        // init or merge stage, because the data can be restored. So we do not `restoreData`
        // and `setData` here, which forbids calling `seriesModel.getData()` in this stage.
        // Call `seriesModel.getRawData()` instead.
        // this.restoreData();

        autoSeriesName(this);
    },

    /**
     * Util for merge default and theme to option
     * @param  {Object} option
     * @param  {module:echarts/model/Global} ecModel
     */
    mergeDefaultAndTheme: function (option, ecModel) {
        var layoutMode = this.layoutMode;
        var inputPositionParams = layoutMode
            ? getLayoutParams(option) : {};

        // Backward compat: using subType on theme.
        // But if name duplicate between series subType
        // (for example: parallel) add component mainType,
        // add suffix 'Series'.
        var themeSubType = this.subType;
        if (ComponentModel.hasClass(themeSubType)) {
            themeSubType += 'Series';
        }
        merge(
            option,
            ecModel.getTheme().get(this.subType)
        );
        merge(option, this.getDefaultOption());

        // Default label emphasis `show`
        defaultEmphasis(option, 'label', ['show']);

        this.fillDataTextStyle(option.data);

        if (layoutMode) {
            mergeLayoutParam(option, inputPositionParams, layoutMode);
        }
    },

    mergeOption: function (newSeriesOption, ecModel) {
        // this.settingTask.dirty();

        newSeriesOption = merge(this.option, newSeriesOption, true);
        this.fillDataTextStyle(newSeriesOption.data);

        var layoutMode = this.layoutMode;
        if (layoutMode) {
            mergeLayoutParam(this.option, newSeriesOption, layoutMode);
        }

        prepareSource(this);

        var data = this.getInitialData(newSeriesOption, ecModel);
        wrapData(data, this);
        this.dataTask.dirty();
        this.dataTask.context.data = data;

        inner$4(this).dataBeforeProcessed = data;

        autoSeriesName(this);
    },

    fillDataTextStyle: function (data) {
        // Default data label emphasis `show`
        // FIXME Tree structure data ?
        // FIXME Performance ?
        if (data && !isTypedArray(data)) {
            var props = ['show'];
            for (var i = 0; i < data.length; i++) {
                if (data[i] && data[i].label) {
                    defaultEmphasis(data[i], 'label', props);
                }
            }
        }
    },

    /**
     * Init a data structure from data related option in series
     * Must be overwritten
     */
    getInitialData: function () {},

    /**
     * Append data to list
     * @param {Object} params
     * @param {Array|TypedArray} params.data
     */
    appendData: function (params) {
        // FIXME ???
        // (1) If data from dataset, forbidden append.
        // (2) support append data of dataset.
        var data = this.getRawData();
        data.appendData(params.data);
    },

    /**
     * Consider some method like `filter`, `map` need make new data,
     * We should make sure that `seriesModel.getData()` get correct
     * data in the stream procedure. So we fetch data from upstream
     * each time `task.perform` called.
     * @param {string} [dataType]
     * @return {module:echarts/data/List}
     */
    getData: function (dataType) {
        var task = getCurrentTask(this);
        if (task) {
            var data = task.context.data;
            return dataType == null ? data : data.getLinkedData(dataType);
        }
        else {
            // When series is not alive (that may happen when click toolbox
            // restore or setOption with not merge mode), series data may
            // be still need to judge animation or something when graphic
            // elements want to know whether fade out.
            return inner$4(this).data;
        }
    },

    /**
     * @param {module:echarts/data/List} data
     */
    setData: function (data) {
        var task = getCurrentTask(this);
        if (task) {
            var context = task.context;
            // Consider case: filter, data sample.
            if (context.data !== data && task.modifyOutputEnd) {
                task.setOutputEnd(data.count());
            }
            context.outputData = data;
            // Caution: setData should update context.data,
            // Because getData may be called multiply in a
            // single stage and expect to get the data just
            // set. (For example, AxisProxy, x y both call
            // getData and setDate sequentially).
            // So the context.data should be fetched from
            // upstream each time when a stage starts to be
            // performed.
            if (task !== this.dataTask) {
                context.data = data;
            }
        }
        inner$4(this).data = data;
    },

    /**
     * @see {module:echarts/data/helper/sourceHelper#getSource}
     * @return {module:echarts/data/Source} source
     */
    getSource: function () {
        return getSource(this);
    },

    /**
     * Get data before processed
     * @return {module:echarts/data/List}
     */
    getRawData: function () {
        return inner$4(this).dataBeforeProcessed;
    },

    /**
     * Get base axis if has coordinate system and has axis.
     * By default use coordSys.getBaseAxis();
     * Can be overrided for some chart.
     * @return {type} description
     */
    getBaseAxis: function () {
        var coordSys = this.coordinateSystem;
        return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
    },

    // FIXME
    /**
     * Default tooltip formatter
     *
     * @param {number} dataIndex
     * @param {boolean} [multipleSeries=false]
     * @param {number} [dataType]
     * @param {string} [renderMode='html'] valid values: 'html' and 'richText'.
     *                                     'html' is used for rendering tooltip in extra DOM form, and the result
     *                                     string is used as DOM HTML content.
     *                                     'richText' is used for rendering tooltip in rich text form, for those where
     *                                     DOM operation is not supported.
     * @return {Object} formatted tooltip with `html` and `markers`
     */
    formatTooltip: function (dataIndex, multipleSeries, dataType, renderMode) {

        var series = this;
        renderMode = renderMode || 'html';
        var newLine = renderMode === 'html' ? '<br/>' : '\n';
        var isRichText = renderMode === 'richText';
        var markers = {};
        var markerId = 0;

        function formatArrayValue(value) {
            // ??? TODO refactor these logic.
            // check: category-no-encode-has-axis-data in dataset.html
            var vertially = reduce(value, function (vertially, val, idx) {
                var dimItem = data.getDimensionInfo(idx);
                return vertially |= dimItem && dimItem.tooltip !== false && dimItem.displayName != null;
            }, 0);

            var result = [];

            tooltipDims.length
                ? each$1(tooltipDims, function (dim) {
                    setEachItem(retrieveRawValue(data, dataIndex, dim), dim);
                })
                // By default, all dims is used on tooltip.
                : each$1(value, setEachItem);

            function setEachItem(val, dim) {
                var dimInfo = data.getDimensionInfo(dim);
                // If `dimInfo.tooltip` is not set, show tooltip.
                if (!dimInfo || dimInfo.otherDims.tooltip === false) {
                    return;
                }
                var dimType = dimInfo.type;
                var markName = 'sub' + series.seriesIndex + 'at' + markerId;
                var dimHead = getTooltipMarker({
                    color: color,
                    type: 'subItem',
                    renderMode: renderMode,
                    markerId: markName
                });

                var dimHeadStr = typeof dimHead === 'string' ? dimHead : dimHead.content;
                var valStr = (vertially
                        ? dimHeadStr + encodeHTML(dimInfo.displayName || '-') + ': '
                        : ''
                    )
                    // FIXME should not format time for raw data?
                    + encodeHTML(dimType === 'ordinal'
                        ? val + ''
                        : dimType === 'time'
                        ? (multipleSeries ? '' : formatTime('yyyy/MM/dd hh:mm:ss', val))
                        : addCommas(val)
                    );
                valStr && result.push(valStr);

                if (isRichText) {
                    markers[markName] = color;
                    ++markerId;
                }
            }

            var newLine = vertially ? (isRichText ? '\n' : '<br/>') : '';
            var content = newLine + result.join(newLine || ', ');
            return {
                renderMode: renderMode,
                content: content,
                style: markers
            };
        }

        function formatSingleValue(val) {
            // return encodeHTML(addCommas(val));
            return {
                renderMode: renderMode,
                content: encodeHTML(addCommas(val)),
                style: markers
            };
        }

        var data = this.getData();
        var tooltipDims = data.mapDimension('defaultedTooltip', true);
        var tooltipDimLen = tooltipDims.length;
        var value = this.getRawValue(dataIndex);
        var isValueArr = isArray(value);

        var color = data.getItemVisual(dataIndex, 'color');
        if (isObject$1(color) && color.colorStops) {
            color = (color.colorStops[0] || {}).color;
        }
        color = color || 'transparent';

        // Complicated rule for pretty tooltip.
        var formattedValue = (tooltipDimLen > 1 || (isValueArr && !tooltipDimLen))
            ? formatArrayValue(value)
            : tooltipDimLen
            ? formatSingleValue(retrieveRawValue(data, dataIndex, tooltipDims[0]))
            : formatSingleValue(isValueArr ? value[0] : value);
        var content = formattedValue.content;

        var markName = series.seriesIndex + 'at' + markerId;
        var colorEl = getTooltipMarker({
            color: color,
            type: 'item',
            renderMode: renderMode,
            markerId: markName
        });
        markers[markName] = color;
        ++markerId;

        var name = data.getName(dataIndex);

        var seriesName = this.name;
        if (!isNameSpecified(this)) {
            seriesName = '';
        }
        seriesName = seriesName
            ? encodeHTML(seriesName) + (!multipleSeries ? newLine : ': ')
            : '';

        var colorStr = typeof colorEl === 'string' ? colorEl : colorEl.content;
        var html = !multipleSeries
            ? seriesName + colorStr
                + (name
                    ? encodeHTML(name) + ': ' + content
                    : content
                )
            : colorStr + seriesName + content;

        return {
            html: html,
            markers: markers
        };
    },

    /**
     * @return {boolean}
     */
    isAnimationEnabled: function () {
        if (env$1.node) {
            return false;
        }

        var animationEnabled = this.getShallow('animation');
        if (animationEnabled) {
            if (this.getData().count() > this.getShallow('animationThreshold')) {
                animationEnabled = false;
            }
        }
        return animationEnabled;
    },

    restoreData: function () {
        this.dataTask.dirty();
    },

    getColorFromPalette: function (name, scope, requestColorNum) {
        var ecModel = this.ecModel;
        // PENDING
        var color = colorPaletteMixin.getColorFromPalette.call(this, name, scope, requestColorNum);
        if (!color) {
            color = ecModel.getColorFromPalette(name, scope, requestColorNum);
        }
        return color;
    },

    /**
     * Use `data.mapDimension(coordDim, true)` instead.
     * @deprecated
     */
    coordDimToDataDim: function (coordDim) {
        return this.getRawData().mapDimension(coordDim, true);
    },

    /**
     * Get progressive rendering count each step
     * @return {number}
     */
    getProgressive: function () {
        return this.get('progressive');
    },

    /**
     * Get progressive rendering count each step
     * @return {number}
     */
    getProgressiveThreshold: function () {
        return this.get('progressiveThreshold');
    },

    /**
     * Get data indices for show tooltip content. See tooltip.
     * @abstract
     * @param {Array.<string>|string} dim
     * @param {Array.<number>} value
     * @param {module:echarts/coord/single/SingleAxis} baseAxis
     * @return {Object} {dataIndices, nestestValue}.
     */
    getAxisTooltipData: null,

    /**
     * See tooltip.
     * @abstract
     * @param {number} dataIndex
     * @return {Array.<number>} Point of tooltip. null/undefined can be returned.
     */
    getTooltipPosition: null,

    /**
     * @see {module:echarts/stream/Scheduler}
     */
    pipeTask: null,

    /**
     * Convinient for override in extended class.
     * @protected
     * @type {Function}
     */
    preventIncremental: null,

    /**
     * @public
     * @readOnly
     * @type {Object}
     */
    pipelineContext: null

});


mixin(SeriesModel, dataFormatMixin);
mixin(SeriesModel, colorPaletteMixin);

/**
 * MUST be called after `prepareSource` called
 * Here we need to make auto series, especially for auto legend. But we
 * do not modify series.name in option to avoid side effects.
 */
function autoSeriesName(seriesModel) {
    // User specified name has higher priority, otherwise it may cause
    // series can not be queried unexpectedly.
    var name = seriesModel.name;
    if (!isNameSpecified(seriesModel)) {
        seriesModel.name = getSeriesAutoName(seriesModel) || name;
    }
}

function getSeriesAutoName(seriesModel) {
    var data = seriesModel.getRawData();
    var dataDims = data.mapDimension('seriesName', true);
    var nameArr = [];
    each$1(dataDims, function (dataDim) {
        var dimInfo = data.getDimensionInfo(dataDim);
        dimInfo.displayName && nameArr.push(dimInfo.displayName);
    });
    return nameArr.join(' ');
}

function dataTaskCount(context) {
    return context.model.getRawData().count();
}

function dataTaskReset(context) {
    var seriesModel = context.model;
    seriesModel.setData(seriesModel.getRawData().cloneShallow());
    return dataTaskProgress;
}

function dataTaskProgress(param, context) {
    // Avoid repead cloneShallow when data just created in reset.
    if (param.end > context.outputData.count()) {
        context.model.getRawData().cloneShallow(context.outputData);
    }
}

// TODO refactor
function wrapData(data, seriesModel) {
    each$1(data.CHANGABLE_METHODS, function (methodName) {
        data.wrapMethod(methodName, curry(onDataSelfChange, seriesModel));
    });
}

function onDataSelfChange(seriesModel) {
    var task = getCurrentTask(seriesModel);
    if (task) {
        // Consider case: filter, selectRange
        task.setOutputEnd(this.count());
    }
}

function getCurrentTask(seriesModel) {
    var scheduler = (seriesModel.ecModel || {}).scheduler;
    var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid);

    if (pipeline) {
        // When pipline finished, the currrentTask keep the last
        // task (renderTask).
        var task = pipeline.currentTask;
        if (task) {
            var agentStubMap = task.agentStubMap;
            if (agentStubMap) {
                task = agentStubMap.get(seriesModel.uid);
            }
        }
        return task;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var Component$1 = function () {
    /**
     * @type {module:zrender/container/Group}
     * @readOnly
     */
    this.group = new Group();

    /**
     * @type {string}
     * @readOnly
     */
    this.uid = getUID('viewComponent');
};

Component$1.prototype = {

    constructor: Component$1,

    init: function (ecModel, api) {},

    render: function (componentModel, ecModel, api, payload) {},

    dispose: function () {},

    /**
     * @param {string} eventType
     * @param {Object} query
     * @param {module:zrender/Element} targetEl
     * @param {Object} packedEvent
     * @return {boolen} Pass only when return `true`.
     */
    filterForExposedEvent: null

};

var componentProto = Component$1.prototype;
componentProto.updateView =
    componentProto.updateLayout =
    componentProto.updateVisual =
    function (seriesModel, ecModel, api, payload) {
        // Do nothing;
    };
// Enable Component.extend.
enableClassExtend(Component$1);

// Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
enableClassManagement(Component$1, {registerWhenExtend: true});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @return {string} If large mode changed, return string 'reset';
 */
var createRenderPlanner = function () {
    var inner = makeInner();

    return function (seriesModel) {
        var fields = inner(seriesModel);
        var pipelineContext = seriesModel.pipelineContext;

        var originalLarge = fields.large;
        var originalProgressive = fields.progressiveRender;

        var large = fields.large = pipelineContext.large;
        var progressive = fields.progressiveRender = pipelineContext.progressiveRender;

        return !!((originalLarge ^ large) || (originalProgressive ^ progressive)) && 'reset';
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$5 = makeInner();
var renderPlanner = createRenderPlanner();

function Chart() {

    /**
     * @type {module:zrender/container/Group}
     * @readOnly
     */
    this.group = new Group();

    /**
     * @type {string}
     * @readOnly
     */
    this.uid = getUID('viewChart');

    this.renderTask = createTask({
        plan: renderTaskPlan,
        reset: renderTaskReset
    });
    this.renderTask.context = {view: this};
}

Chart.prototype = {

    type: 'chart',

    /**
     * Init the chart.
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    init: function (ecModel, api) {},

    /**
     * Render the chart.
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     */
    render: function (seriesModel, ecModel, api, payload) {},

    /**
     * Highlight series or specified data item.
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     */
    highlight: function (seriesModel, ecModel, api, payload) {
        toggleHighlight(seriesModel.getData(), payload, 'emphasis');
    },

    /**
     * Downplay series or specified data item.
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     */
    downplay: function (seriesModel, ecModel, api, payload) {
        toggleHighlight(seriesModel.getData(), payload, 'normal');
    },

    /**
     * Remove self.
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    remove: function (ecModel, api) {
        this.group.removeAll();
    },

    /**
     * Dispose self.
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    dispose: function () {},

    /**
     * Rendering preparation in progressive mode.
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     */
    incrementalPrepareRender: null,

    /**
     * Render in progressive mode.
     * @param  {Object} params See taskParams in `stream/task.js`
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     */
    incrementalRender: null,

    /**
     * Update transform directly.
     * @param  {module:echarts/model/Series} seriesModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @param  {Object} payload
     * @return {Object} {update: true}
     */
    updateTransform: null,

    /**
     * The view contains the given point.
     * @interface
     * @param {Array.<number>} point
     * @return {boolean}
     */
    // containPoint: function () {}

    /**
     * @param {string} eventType
     * @param {Object} query
     * @param {module:zrender/Element} targetEl
     * @param {Object} packedEvent
     * @return {boolen} Pass only when return `true`.
     */
    filterForExposedEvent: null

};

var chartProto = Chart.prototype;
chartProto.updateView =
chartProto.updateLayout =
chartProto.updateVisual =
    function (seriesModel, ecModel, api, payload) {
        this.render(seriesModel, ecModel, api, payload);
    };

/**
 * Set state of single element
 * @param {module:zrender/Element} el
 * @param {string} state 'normal'|'emphasis'
 * @param {number} highlightDigit
 */
function elSetState(el, state, highlightDigit) {
    if (el) {
        el.trigger(state, highlightDigit);
        if (el.isGroup
            // Simple optimize.
            && !isHighDownDispatcher(el)
        ) {
            for (var i = 0, len = el.childCount(); i < len; i++) {
                elSetState(el.childAt(i), state, highlightDigit);
            }
        }
    }
}

/**
 * @param {module:echarts/data/List} data
 * @param {Object} payload
 * @param {string} state 'normal'|'emphasis'
 */
function toggleHighlight(data, payload, state) {
    var dataIndex = queryDataIndex(data, payload);

    var highlightDigit = (payload && payload.highlightKey != null)
        ? getHighlightDigit(payload.highlightKey)
        : null;

    if (dataIndex != null) {
        each$1(normalizeToArray(dataIndex), function (dataIdx) {
            elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit);
        });
    }
    else {
        data.eachItemGraphicEl(function (el) {
            elSetState(el, state, highlightDigit);
        });
    }
}

// Enable Chart.extend.
enableClassExtend(Chart, ['dispose']);

// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
enableClassManagement(Chart, {registerWhenExtend: true});

Chart.markUpdateMethod = function (payload, methodName) {
    inner$5(payload).updateMethod = methodName;
};

function renderTaskPlan(context) {
    return renderPlanner(context.model);
}

function renderTaskReset(context) {
    var seriesModel = context.model;
    var ecModel = context.ecModel;
    var api = context.api;
    var payload = context.payload;
    // ???! remove updateView updateVisual
    var progressiveRender = seriesModel.pipelineContext.progressiveRender;
    var view = context.view;

    var updateMethod = payload && inner$5(payload).updateMethod;
    var methodName = progressiveRender
        ? 'incrementalPrepareRender'
        : (updateMethod && view[updateMethod])
        ? updateMethod
        // `appendData` is also supported when data amount
        // is less than progressive threshold.
        : 'render';

    if (methodName !== 'render') {
        view[methodName](seriesModel, ecModel, api, payload);
    }

    return progressMethodMap[methodName];
}

var progressMethodMap = {
    incrementalPrepareRender: {
        progress: function (params, context) {
            context.view.incrementalRender(
                params, context.model, context.ecModel, context.api, context.payload
            );
        }
    },
    render: {
        // Put view.render in `progress` to support appendData. But in this case
        // view.render should not be called in reset, otherwise it will be called
        // twise. Use `forceFirstProgress` to make sure that view.render is called
        // in any cases.
        forceFirstProgress: true,
        progress: function (params, context) {
            context.view.render(
                context.model, context.ecModel, context.api, context.payload
            );
        }
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var ORIGIN_METHOD = '\0__throttleOriginMethod';
var RATE = '\0__throttleRate';
var THROTTLE_TYPE = '\0__throttleType';

/**
 * @public
 * @param {(Function)} fn
 * @param {number} [delay=0] Unit: ms.
 * @param {boolean} [debounce=false]
 *        true: If call interval less than `delay`, only the last call works.
 *        false: If call interval less than `delay, call works on fixed rate.
 * @return {(Function)} throttled fn.
 */
function throttle(fn, delay, debounce) {

    var currCall;
    var lastCall = 0;
    var lastExec = 0;
    var timer = null;
    var diff;
    var scope;
    var args;
    var debounceNextCall;

    delay = delay || 0;

    function exec() {
        lastExec = (new Date()).getTime();
        timer = null;
        fn.apply(scope, args || []);
    }

    var cb = function () {
        currCall = (new Date()).getTime();
        scope = this;
        args = arguments;
        var thisDelay = debounceNextCall || delay;
        var thisDebounce = debounceNextCall || debounce;
        debounceNextCall = null;
        diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;

        clearTimeout(timer);

        // Here we should make sure that: the `exec` SHOULD NOT be called later
        // than a new call of `cb`, that is, preserving the command order. Consider
        // calculating "scale rate" when roaming as an example. When a call of `cb`
        // happens, either the `exec` is called dierectly, or the call is delayed.
        // But the delayed call should never be later than next call of `cb`. Under
        // this assurance, we can simply update view state each time `dispatchAction`
        // triggered by user roaming, but not need to add extra code to avoid the
        // state being "rolled-back".
        if (thisDebounce) {
            timer = setTimeout(exec, thisDelay);
        }
        else {
            if (diff >= 0) {
                exec();
            }
            else {
                timer = setTimeout(exec, -diff);
            }
        }

        lastCall = currCall;
    };

    /**
     * Clear throttle.
     * @public
     */
    cb.clear = function () {
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
    };

    /**
     * Enable debounce once.
     */
    cb.debounceNextCall = function (debounceDelay) {
        debounceNextCall = debounceDelay;
    };

    return cb;
}

/**
 * Create throttle method or update throttle rate.
 *
 * @example
 * ComponentView.prototype.render = function () {
 *     ...
 *     throttle.createOrUpdate(
 *         this,
 *         '_dispatchAction',
 *         this.model.get('throttle'),
 *         'fixRate'
 *     );
 * };
 * ComponentView.prototype.remove = function () {
 *     throttle.clear(this, '_dispatchAction');
 * };
 * ComponentView.prototype.dispose = function () {
 *     throttle.clear(this, '_dispatchAction');
 * };
 *
 * @public
 * @param {Object} obj
 * @param {string} fnAttr
 * @param {number} [rate]
 * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce'
 * @return {Function} throttled function.
 */
function createOrUpdate(obj, fnAttr, rate, throttleType) {
    var fn = obj[fnAttr];

    if (!fn) {
        return;
    }

    var originFn = fn[ORIGIN_METHOD] || fn;
    var lastThrottleType = fn[THROTTLE_TYPE];
    var lastRate = fn[RATE];

    if (lastRate !== rate || lastThrottleType !== throttleType) {
        if (rate == null || !throttleType) {
            return (obj[fnAttr] = originFn);
        }

        fn = obj[fnAttr] = throttle(
            originFn, rate, throttleType === 'debounce'
        );
        fn[ORIGIN_METHOD] = originFn;
        fn[THROTTLE_TYPE] = throttleType;
        fn[RATE] = rate;
    }

    return fn;
}

/**
 * Clear throttle. Example see throttle.createOrUpdate.
 *
 * @public
 * @param {Object} obj
 * @param {string} fnAttr
 */
function clear(obj, fnAttr) {
    var fn = obj[fnAttr];
    if (fn && fn[ORIGIN_METHOD]) {
        obj[fnAttr] = fn[ORIGIN_METHOD];
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var seriesColor = {
    createOnAllSeries: true,
    performRawSeries: true,
    reset: function (seriesModel, ecModel) {
        var data = seriesModel.getData();
        var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.color').split('.');
        var color = seriesModel.get(colorAccessPath) // Set in itemStyle
            || seriesModel.getColorFromPalette(
                // TODO series count changed.
                seriesModel.name, null, ecModel.getSeriesCount()
            );  // Default color

        // FIXME Set color function or use the platte color
        data.setVisual('color', color);
        
        var borderColorAccessPath = (seriesModel.visualBorderColorAccessPath || 'itemStyle.borderColor').split('.');
        var borderColor = seriesModel.get(borderColorAccessPath);
        data.setVisual('borderColor', borderColor);

        // Only visible series has each data be visual encoded
        if (!ecModel.isSeriesFiltered(seriesModel)) {
            if (typeof color === 'function' && !(color instanceof Gradient)) {
                data.each(function (idx) {
                    data.setItemVisual(
                        idx, 'color', color(seriesModel.getDataParams(idx))
                    );
                });
            }

            // itemStyle in each data item
            var dataEach = function (data, idx) {
                var itemModel = data.getItemModel(idx);
                var color = itemModel.get(colorAccessPath, true);
                var borderColor = itemModel.get(borderColorAccessPath, true);
                if (color != null) {
                    data.setItemVisual(idx, 'color', color);
                }
                if (borderColor != null) {
                    data.setItemVisual(idx, 'borderColor', borderColor);
                }
            };

            return { dataEach: data.hasItemOption ? dataEach : null };
        }
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Language: English.
 */

var lang = {
    legend: {
        selector: {
            all: 'All',
            inverse: 'Inv'
        }
    },
    toolbox: {
        brush: {
            title: {
                rect: 'Box Select',
                polygon: 'Lasso Select',
                lineX: 'Horizontally Select',
                lineY: 'Vertically Select',
                keep: 'Keep Selections',
                clear: 'Clear Selections'
            }
        },
        dataView: {
            title: 'Data View',
            lang: ['Data View', 'Close', 'Refresh']
        },
        dataZoom: {
            title: {
                zoom: 'Zoom',
                back: 'Zoom Reset'
            }
        },
        magicType: {
            title: {
                line: 'Switch to Line Chart',
                bar: 'Switch to Bar Chart',
                stack: 'Stack',
                tiled: 'Tile'
            }
        },
        restore: {
            title: 'Restore'
        },
        saveAsImage: {
            title: 'Save as Image',
            lang: ['Right Click to Save Image']
        }
    },
    aria: {
        general: {
            withTitle: 'This is a chart about "{title}"',
            withoutTitle: 'This is a chart'
        },
        series: {
            single: {
                prefix: '',
                withName: ' with type {seriesType} named {seriesName}.',
                withoutName: ' with type {seriesType}.'
            },
            multiple: {
                prefix: '. It consists of {seriesCount} series count.',
                withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.',
                withoutName: ' The {seriesId} series is a {seriesType}.',
                separator: {
                    middle: '',
                    end: ''
                }
            }
        },
        data: {
            allData: 'The data is as follows: ',
            partialData: 'The first {displayCnt} items are: ',
            withName: 'the data for {name} is {value}',
            withoutName: '{value}',
            separator: {
                middle: ',',
                end: '.'
            }
        }
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var aria = function (dom, ecModel) {
    var ariaModel = ecModel.getModel('aria');
    if (!ariaModel.get('show')) {
        return;
    }
    else if (ariaModel.get('description')) {
        dom.setAttribute('aria-label', ariaModel.get('description'));
        return;
    }

    var seriesCnt = 0;
    ecModel.eachSeries(function (seriesModel, idx) {
        ++seriesCnt;
    }, this);

    var maxDataCnt = ariaModel.get('data.maxCount') || 10;
    var maxSeriesCnt = ariaModel.get('series.maxCount') || 10;
    var displaySeriesCnt = Math.min(seriesCnt, maxSeriesCnt);

    var ariaLabel;
    if (seriesCnt < 1) {
        // No series, no aria label
        return;
    }
    else {
        var title = getTitle();
        if (title) {
            ariaLabel = replace(getConfig('general.withTitle'), {
                title: title
            });
        }
        else {
            ariaLabel = getConfig('general.withoutTitle');
        }

        var seriesLabels = [];
        var prefix = seriesCnt > 1
            ? 'series.multiple.prefix'
            : 'series.single.prefix';
        ariaLabel += replace(getConfig(prefix), { seriesCount: seriesCnt });

        ecModel.eachSeries(function (seriesModel, idx) {
            if (idx < displaySeriesCnt) {
                var seriesLabel;

                var seriesName = seriesModel.get('name');
                var seriesTpl = 'series.'
                    + (seriesCnt > 1 ? 'multiple' : 'single') + '.';
                seriesLabel = getConfig(seriesName
                    ? seriesTpl + 'withName'
                    : seriesTpl + 'withoutName');

                seriesLabel = replace(seriesLabel, {
                    seriesId: seriesModel.seriesIndex,
                    seriesName: seriesModel.get('name'),
                    seriesType: getSeriesTypeName(seriesModel.subType)
                });

                var data = seriesModel.getData();
                window.data = data;
                if (data.count() > maxDataCnt) {
                    // Show part of data
                    seriesLabel += replace(getConfig('data.partialData'), {
                        displayCnt: maxDataCnt
                    });
                }
                else {
                    seriesLabel += getConfig('data.allData');
                }

                var dataLabels = [];
                for (var i = 0; i < data.count(); i++) {
                    if (i < maxDataCnt) {
                        var name = data.getName(i);
                        var value = retrieveRawValue(data, i);
                        dataLabels.push(
                            replace(
                                name
                                    ? getConfig('data.withName')
                                    : getConfig('data.withoutName'),
                                {
                                    name: name,
                                    value: value
                                }
                            )
                        );
                    }
                }
                seriesLabel += dataLabels
                    .join(getConfig('data.separator.middle'))
                    + getConfig('data.separator.end');

                seriesLabels.push(seriesLabel);
            }
        });

        ariaLabel += seriesLabels
            .join(getConfig('series.multiple.separator.middle'))
            + getConfig('series.multiple.separator.end');

        dom.setAttribute('aria-label', ariaLabel);
    }

    function replace(str, keyValues) {
        if (typeof str !== 'string') {
            return str;
        }

        var result = str;
        each$1(keyValues, function (value, key) {
            result = result.replace(
                new RegExp('\\{\\s*' + key + '\\s*\\}', 'g'),
                value
            );
        });
        return result;
    }

    function getConfig(path) {
        var userConfig = ariaModel.get(path);
        if (userConfig == null) {
            var pathArr = path.split('.');
            var result = lang.aria;
            for (var i = 0; i < pathArr.length; ++i) {
                result = result[pathArr[i]];
            }
            return result;
        }
        else {
            return userConfig;
        }
    }

    function getTitle() {
        var title = ecModel.getModel('title').option;
        if (title && title.length) {
            title = title[0];
        }
        return title && title.text;
    }

    function getSeriesTypeName(type) {
        return lang.series.typeNames[type] || '自定义图';
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PI$1 = Math.PI;

/**
 * @param {module:echarts/ExtensionAPI} api
 * @param {Object} [opts]
 * @param {string} [opts.text]
 * @param {string} [opts.color]
 * @param {string} [opts.textColor]
 * @return {module:zrender/Element}
 */
var loadingDefault = function (api, opts) {
    opts = opts || {};
    defaults(opts, {
        text: 'loading',
        color: '#c23531',
        textColor: '#000',
        maskColor: 'rgba(255, 255, 255, 0.8)',
        zlevel: 0
    });
    var mask = new Rect({
        style: {
            fill: opts.maskColor
        },
        zlevel: opts.zlevel,
        z: 10000
    });
    var arc = new Arc({
        shape: {
            startAngle: -PI$1 / 2,
            endAngle: -PI$1 / 2 + 0.1,
            r: 10
        },
        style: {
            stroke: opts.color,
            lineCap: 'round',
            lineWidth: 5
        },
        zlevel: opts.zlevel,
        z: 10001
    });
    var labelRect = new Rect({
        style: {
            fill: 'none',
            text: opts.text,
            textPosition: 'right',
            textDistance: 10,
            textFill: opts.textColor
        },
        zlevel: opts.zlevel,
        z: 10001
    });

    arc.animateShape(true)
        .when(1000, {
            endAngle: PI$1 * 3 / 2
        })
        .start('circularInOut');
    arc.animateShape(true)
        .when(1000, {
            startAngle: PI$1 * 3 / 2
        })
        .delay(300)
        .start('circularInOut');

    var group = new Group();
    group.add(arc);
    group.add(labelRect);
    group.add(mask);
    // Inject resize
    group.resize = function () {
        var cx = api.getWidth() / 2;
        var cy = api.getHeight() / 2;
        arc.setShape({
            cx: cx,
            cy: cy
        });
        var r = arc.shape.r;
        labelRect.setShape({
            x: cx - r,
            y: cy - r,
            width: r * 2,
            height: r * 2
        });

        mask.setShape({
            x: 0,
            y: 0,
            width: api.getWidth(),
            height: api.getHeight()
        });
    };
    group.resize();
    return group;
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/stream/Scheduler
 */

/**
 * @constructor
 */
function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) {
    this.ecInstance = ecInstance;
    this.api = api;
    this.unfinished;

    // Fix current processors in case that in some rear cases that
    // processors might be registered after echarts instance created.
    // Register processors incrementally for a echarts instance is
    // not supported by this stream architecture.
    var dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice();
    var visualHandlers = this._visualHandlers = visualHandlers.slice();
    this._allHandlers = dataProcessorHandlers.concat(visualHandlers);

    /**
     * @private
     * @type {
     *     [handlerUID: string]: {
     *         seriesTaskMap?: {
     *             [seriesUID: string]: Task
     *         },
     *         overallTask?: Task
     *     }
     * }
     */
    this._stageTaskMap = createHashMap();
}

var proto = Scheduler.prototype;

/**
 * @param {module:echarts/model/Global} ecModel
 * @param {Object} payload
 */
proto.restoreData = function (ecModel, payload) {
    // TODO: Only restroe needed series and components, but not all components.
    // Currently `restoreData` of all of the series and component will be called.
    // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
    // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
    // and some components like coordinate system, axes, dataZoom, visualMap only
    // need their target series refresh.
    // (1) If we are implementing this feature some day, we should consider these cases:
    // if a data processor depends on a component (e.g., dataZoomProcessor depends
    // on the settings of `dataZoom`), it should be re-performed if the component
    // is modified by `setOption`.
    // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,
    // it should be re-performed when the result array of `getTargetSeries` changed.
    // We use `dependencies` to cover these issues.
    // (3) How to update target series when coordinate system related components modified.

    // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,
    // and this case all of the tasks will be set as dirty.

    ecModel.restoreData(payload);

    // Theoretically an overall task not only depends on each of its target series, but also
    // depends on all of the series.
    // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks
    // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure
    // that the overall task is set as dirty and to be performed, otherwise it probably cause
    // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it
    // probably cause state chaos (consider `dataZoomProcessor`).
    this._stageTaskMap.each(function (taskRecord) {
        var overallTask = taskRecord.overallTask;
        overallTask && overallTask.dirty();
    });
};

// If seriesModel provided, incremental threshold is check by series data.
proto.getPerformArgs = function (task, isBlock) {
    // For overall task
    if (!task.__pipeline) {
        return;
    }

    var pipeline = this._pipelineMap.get(task.__pipeline.id);
    var pCtx = pipeline.context;
    var incremental = !isBlock
        && pipeline.progressiveEnabled
        && (!pCtx || pCtx.progressiveRender)
        && task.__idxInPipeline > pipeline.blockIndex;

    var step = incremental ? pipeline.step : null;
    var modDataCount = pCtx && pCtx.modDataCount;
    var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null;

    return {step: step, modBy: modBy, modDataCount: modDataCount};
};

proto.getPipeline = function (pipelineId) {
    return this._pipelineMap.get(pipelineId);
};

/**
 * Current, progressive rendering starts from visual and layout.
 * Always detect render mode in the same stage, avoiding that incorrect
 * detection caused by data filtering.
 * Caution:
 * `updateStreamModes` use `seriesModel.getData()`.
 */
proto.updateStreamModes = function (seriesModel, view) {
    var pipeline = this._pipelineMap.get(seriesModel.uid);
    var data = seriesModel.getData();
    var dataLen = data.count();

    // `progressiveRender` means that can render progressively in each
    // animation frame. Note that some types of series do not provide
    // `view.incrementalPrepareRender` but support `chart.appendData`. We
    // use the term `incremental` but not `progressive` to describe the
    // case that `chart.appendData`.
    var progressiveRender = pipeline.progressiveEnabled
        && view.incrementalPrepareRender
        && dataLen >= pipeline.threshold;

    var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold');

    // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.
    // see `test/candlestick-large3.html`
    var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null;

    seriesModel.pipelineContext = pipeline.context = {
        progressiveRender: progressiveRender,
        modDataCount: modDataCount,
        large: large
    };
};

proto.restorePipelines = function (ecModel) {
    var scheduler = this;
    var pipelineMap = scheduler._pipelineMap = createHashMap();

    ecModel.eachSeries(function (seriesModel) {
        var progressive = seriesModel.getProgressive();
        var pipelineId = seriesModel.uid;

        pipelineMap.set(pipelineId, {
            id: pipelineId,
            head: null,
            tail: null,
            threshold: seriesModel.getProgressiveThreshold(),
            progressiveEnabled: progressive
                && !(seriesModel.preventIncremental && seriesModel.preventIncremental()),
            blockIndex: -1,
            step: Math.round(progressive || 700),
            count: 0
        });

        pipe(scheduler, seriesModel, seriesModel.dataTask);
    });
};

proto.prepareStageTasks = function () {
    var stageTaskMap = this._stageTaskMap;
    var ecModel = this.ecInstance.getModel();
    var api = this.api;

    each$1(this._allHandlers, function (handler) {
        var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, []);

        handler.reset && createSeriesStageTask(this, handler, record, ecModel, api);
        handler.overallReset && createOverallStageTask(this, handler, record, ecModel, api);
    }, this);
};

proto.prepareView = function (view, model, ecModel, api) {
    var renderTask = view.renderTask;
    var context = renderTask.context;

    context.model = model;
    context.ecModel = ecModel;
    context.api = api;

    renderTask.__block = !view.incrementalPrepareRender;

    pipe(this, model, renderTask);
};


proto.performDataProcessorTasks = function (ecModel, payload) {
    // If we do not use `block` here, it should be considered when to update modes.
    performStageTasks(this, this._dataProcessorHandlers, ecModel, payload, {block: true});
};

// opt
// opt.visualType: 'visual' or 'layout'
// opt.setDirty
proto.performVisualTasks = function (ecModel, payload, opt) {
    performStageTasks(this, this._visualHandlers, ecModel, payload, opt);
};

function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
    opt = opt || {};
    var unfinished;

    each$1(stageHandlers, function (stageHandler, idx) {
        if (opt.visualType && opt.visualType !== stageHandler.visualType) {
            return;
        }

        var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid);
        var seriesTaskMap = stageHandlerRecord.seriesTaskMap;
        var overallTask = stageHandlerRecord.overallTask;

        if (overallTask) {
            var overallNeedDirty;
            var agentStubMap = overallTask.agentStubMap;
            agentStubMap.each(function (stub) {
                if (needSetDirty(opt, stub)) {
                    stub.dirty();
                    overallNeedDirty = true;
                }
            });
            overallNeedDirty && overallTask.dirty();
            updatePayload(overallTask, payload);
            var performArgs = scheduler.getPerformArgs(overallTask, opt.block);
            // Execute stubs firstly, which may set the overall task dirty,
            // then execute the overall task. And stub will call seriesModel.setData,
            // which ensures that in the overallTask seriesModel.getData() will not
            // return incorrect data.
            agentStubMap.each(function (stub) {
                stub.perform(performArgs);
            });
            unfinished |= overallTask.perform(performArgs);
        }
        else if (seriesTaskMap) {
            seriesTaskMap.each(function (task, pipelineId) {
                if (needSetDirty(opt, task)) {
                    task.dirty();
                }
                var performArgs = scheduler.getPerformArgs(task, opt.block);
                performArgs.skip = !stageHandler.performRawSeries
                    && ecModel.isSeriesFiltered(task.context.model);
                updatePayload(task, payload);
                unfinished |= task.perform(performArgs);
            });
        }
    });

    function needSetDirty(opt, task) {
        return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id));
    }

    scheduler.unfinished |= unfinished;
}

proto.performSeriesTasks = function (ecModel) {
    var unfinished;

    ecModel.eachSeries(function (seriesModel) {
        // Progress to the end for dataInit and dataRestore.
        unfinished |= seriesModel.dataTask.perform();
    });

    this.unfinished |= unfinished;
};

proto.plan = function () {
    // Travel pipelines, check block.
    this._pipelineMap.each(function (pipeline) {
        var task = pipeline.tail;
        do {
            if (task.__block) {
                pipeline.blockIndex = task.__idxInPipeline;
                break;
            }
            task = task.getUpstream();
        }
        while (task);
    });
};

var updatePayload = proto.updatePayload = function (task, payload) {
    payload !== 'remain' && (task.context.payload = payload);
};

function createSeriesStageTask(scheduler, stageHandler, stageHandlerRecord, ecModel, api) {
    var seriesTaskMap = stageHandlerRecord.seriesTaskMap
        || (stageHandlerRecord.seriesTaskMap = createHashMap());
    var seriesType = stageHandler.seriesType;
    var getTargetSeries = stageHandler.getTargetSeries;

    // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,
    // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,
    // it works but it may cause other irrelevant charts blocked.
    if (stageHandler.createOnAllSeries) {
        ecModel.eachRawSeries(create);
    }
    else if (seriesType) {
        ecModel.eachRawSeriesByType(seriesType, create);
    }
    else if (getTargetSeries) {
        getTargetSeries(ecModel, api).each(create);
    }

    function create(seriesModel) {
        var pipelineId = seriesModel.uid;

        // Init tasks for each seriesModel only once.
        // Reuse original task instance.
        var task = seriesTaskMap.get(pipelineId)
            || seriesTaskMap.set(pipelineId, createTask({
                plan: seriesTaskPlan,
                reset: seriesTaskReset,
                count: seriesTaskCount
            }));
        task.context = {
            model: seriesModel,
            ecModel: ecModel,
            api: api,
            useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
            plan: stageHandler.plan,
            reset: stageHandler.reset,
            scheduler: scheduler
        };
        pipe(scheduler, seriesModel, task);
    }

    // Clear unused series tasks.
    var pipelineMap = scheduler._pipelineMap;
    seriesTaskMap.each(function (task, pipelineId) {
        if (!pipelineMap.get(pipelineId)) {
            task.dispose();
            seriesTaskMap.removeKey(pipelineId);
        }
    });
}

function createOverallStageTask(scheduler, stageHandler, stageHandlerRecord, ecModel, api) {
    var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask
        // For overall task, the function only be called on reset stage.
        || createTask({reset: overallTaskReset});

    overallTask.context = {
        ecModel: ecModel,
        api: api,
        overallReset: stageHandler.overallReset,
        scheduler: scheduler
    };

    // Reuse orignal stubs.
    var agentStubMap = overallTask.agentStubMap = overallTask.agentStubMap || createHashMap();

    var seriesType = stageHandler.seriesType;
    var getTargetSeries = stageHandler.getTargetSeries;
    var overallProgress = true;
    var modifyOutputEnd = stageHandler.modifyOutputEnd;

    // An overall task with seriesType detected or has `getTargetSeries`, we add
    // stub in each pipelines, it will set the overall task dirty when the pipeline
    // progress. Moreover, to avoid call the overall task each frame (too frequent),
    // we set the pipeline block.
    if (seriesType) {
        ecModel.eachRawSeriesByType(seriesType, createStub);
    }
    else if (getTargetSeries) {
        getTargetSeries(ecModel, api).each(createStub);
    }
    // Otherwise, (usually it is legancy case), the overall task will only be
    // executed when upstream dirty. Otherwise the progressive rendering of all
    // pipelines will be disabled unexpectedly. But it still needs stubs to receive
    // dirty info from upsteam.
    else {
        overallProgress = false;
        each$1(ecModel.getSeries(), createStub);
    }

    function createStub(seriesModel) {
        var pipelineId = seriesModel.uid;
        var stub = agentStubMap.get(pipelineId);
        if (!stub) {
            stub = agentStubMap.set(pipelineId, createTask(
                {reset: stubReset, onDirty: stubOnDirty}
            ));
            // When the result of `getTargetSeries` changed, the overallTask
            // should be set as dirty and re-performed.
            overallTask.dirty();
        }
        stub.context = {
            model: seriesModel,
            overallProgress: overallProgress,
            modifyOutputEnd: modifyOutputEnd
        };
        stub.agent = overallTask;
        stub.__block = overallProgress;

        pipe(scheduler, seriesModel, stub);
    }

    // Clear unused stubs.
    var pipelineMap = scheduler._pipelineMap;
    agentStubMap.each(function (stub, pipelineId) {
        if (!pipelineMap.get(pipelineId)) {
            stub.dispose();
            // When the result of `getTargetSeries` changed, the overallTask
            // should be set as dirty and re-performed.
            overallTask.dirty();
            agentStubMap.removeKey(pipelineId);
        }
    });
}

function overallTaskReset(context) {
    context.overallReset(
        context.ecModel, context.api, context.payload
    );
}

function stubReset(context, upstreamContext) {
    return context.overallProgress && stubProgress;
}

function stubProgress() {
    this.agent.dirty();
    this.getDownstream().dirty();
}

function stubOnDirty() {
    this.agent && this.agent.dirty();
}

function seriesTaskPlan(context) {
    return context.plan && context.plan(
        context.model, context.ecModel, context.api, context.payload
    );
}

function seriesTaskReset(context) {
    if (context.useClearVisual) {
        context.data.clearAllVisual();
    }
    var resetDefines = context.resetDefines = normalizeToArray(context.reset(
        context.model, context.ecModel, context.api, context.payload
    ));
    return resetDefines.length > 1
        ? map(resetDefines, function (v, idx) {
            return makeSeriesTaskProgress(idx);
        })
        : singleSeriesTaskProgress;
}

var singleSeriesTaskProgress = makeSeriesTaskProgress(0);

function makeSeriesTaskProgress(resetDefineIdx) {
    return function (params, context) {
        var data = context.data;
        var resetDefine = context.resetDefines[resetDefineIdx];

        if (resetDefine && resetDefine.dataEach) {
            for (var i = params.start; i < params.end; i++) {
                resetDefine.dataEach(data, i);
            }
        }
        else if (resetDefine && resetDefine.progress) {
            resetDefine.progress(params, data);
        }
    };
}

function seriesTaskCount(context) {
    return context.data.count();
}

function pipe(scheduler, seriesModel, task) {
    var pipelineId = seriesModel.uid;
    var pipeline = scheduler._pipelineMap.get(pipelineId);
    !pipeline.head && (pipeline.head = task);
    pipeline.tail && pipeline.tail.pipe(task);
    pipeline.tail = task;
    task.__idxInPipeline = pipeline.count++;
    task.__pipeline = pipeline;
}

Scheduler.wrapStageHandler = function (stageHandler, visualType) {
    if (isFunction$1(stageHandler)) {
        stageHandler = {
            overallReset: stageHandler,
            seriesType: detectSeriseType(stageHandler)
        };
    }

    stageHandler.uid = getUID('stageHandler');
    visualType && (stageHandler.visualType = visualType);

    return stageHandler;
};



/**
 * Only some legacy stage handlers (usually in echarts extensions) are pure function.
 * To ensure that they can work normally, they should work in block mode, that is,
 * they should not be started util the previous tasks finished. So they cause the
 * progressive rendering disabled. We try to detect the series type, to narrow down
 * the block range to only the series type they concern, but not all series.
 */
function detectSeriseType(legacyFunc) {
    seriesType = null;
    try {
        // Assume there is no async when calling `eachSeriesByType`.
        legacyFunc(ecModelMock, apiMock);
    }
    catch (e) {
    }
    return seriesType;
}

var ecModelMock = {};
var apiMock = {};
var seriesType;

mockMethods(ecModelMock, GlobalModel);
mockMethods(apiMock, ExtensionAPI);
ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) {
    seriesType = type;
};
ecModelMock.eachComponent = function (cond) {
    if (cond.mainType === 'series' && cond.subType) {
        seriesType = cond.subType;
    }
};

function mockMethods(target, Clz) {
    /* eslint-disable */
    for (var name in Clz.prototype) {
        // Do not use hasOwnProperty
        target[name] = noop;
    }
    /* eslint-enable */
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var colorAll = [
    '#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f',
    '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'
];

var lightTheme = {

    color: colorAll,

    colorLayer: [
        ['#37A2DA', '#ffd85c', '#fd7b5f'],
        ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'],
        ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'],
        colorAll
    ]
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var contrastColor = '#eee';
var axisCommon = function () {
    return {
        axisLine: {
            lineStyle: {
                color: contrastColor
            }
        },
        axisTick: {
            lineStyle: {
                color: contrastColor
            }
        },
        axisLabel: {
            textStyle: {
                color: contrastColor
            }
        },
        splitLine: {
            lineStyle: {
                type: 'dashed',
                color: '#aaa'
            }
        },
        splitArea: {
            areaStyle: {
                color: contrastColor
            }
        }
    };
};

var colorPalette = [
    '#dd6b66', '#759aa0', '#e69d87', '#8dc1a9', '#ea7e53',
    '#eedd78', '#73a373', '#73b9bc', '#7289ab', '#91ca8c', '#f49f42'
];
var theme = {
    color: colorPalette,
    backgroundColor: '#333',
    tooltip: {
        axisPointer: {
            lineStyle: {
                color: contrastColor
            },
            crossStyle: {
                color: contrastColor
            }
        }
    },
    legend: {
        textStyle: {
            color: contrastColor
        }
    },
    textStyle: {
        color: contrastColor
    },
    title: {
        textStyle: {
            color: contrastColor
        }
    },
    toolbox: {
        iconStyle: {
            normal: {
                borderColor: contrastColor
            }
        }
    },
    dataZoom: {
        textStyle: {
            color: contrastColor
        }
    },
    visualMap: {
        textStyle: {
            color: contrastColor
        }
    },
    timeline: {
        lineStyle: {
            color: contrastColor
        },
        itemStyle: {
            normal: {
                color: colorPalette[1]
            }
        },
        label: {
            normal: {
                textStyle: {
                    color: contrastColor
                }
            }
        },
        controlStyle: {
            normal: {
                color: contrastColor,
                borderColor: contrastColor
            }
        }
    },
    timeAxis: axisCommon(),
    logAxis: axisCommon(),
    valueAxis: axisCommon(),
    categoryAxis: axisCommon(),

    line: {
        symbol: 'circle'
    },
    graph: {
        color: colorPalette
    },
    gauge: {
        title: {
            textStyle: {
                color: contrastColor
            }
        }
    },
    candlestick: {
        itemStyle: {
            normal: {
                color: '#FD1050',
                color0: '#0CF49B',
                borderColor: '#FD1050',
                borderColor0: '#0CF49B'
            }
        }
    }
};
theme.categoryAxis.splitLine.show = false;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * This module is imported by echarts directly.
 *
 * Notice:
 * Always keep this file exists for backward compatibility.
 * Because before 4.1.0, dataset is an optional component,
 * some users may import this module manually.
 */

ComponentModel.extend({

    type: 'dataset',

    /**
     * @protected
     */
    defaultOption: {

        // 'row', 'column'
        seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,

        // null/'auto': auto detect header, see "module:echarts/data/helper/sourceHelper"
        sourceHeader: null,

        dimensions: null,

        source: null
    },

    optionUpdated: function () {
        detectSourceFormat(this);
    }

});

Component$1.extend({

    type: 'dataset'

});

/**
 * 椭圆形状
 * @module zrender/graphic/shape/Ellipse
 */

var Ellipse = Path.extend({

    type: 'ellipse',

    shape: {
        cx: 0, cy: 0,
        rx: 0, ry: 0
    },

    buildPath: function (ctx, shape) {
        var k = 0.5522848;
        var x = shape.cx;
        var y = shape.cy;
        var a = shape.rx;
        var b = shape.ry;
        var ox = a * k; // 水平控制点偏移量
        var oy = b * k; // 垂直控制点偏移量
        // 从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线
        ctx.moveTo(x - a, y);
        ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
        ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
        ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
        ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
        ctx.closePath();
    }
});

// import RadialGradient from '../graphic/RadialGradient';
// import Pattern from '../graphic/Pattern';
// import * as vector from '../core/vector';
// Most of the values can be separated by comma and/or white space.
var DILIMITER_REG = /[\s,]+/;

/**
 * For big svg string, this method might be time consuming.
 *
 * @param {string} svg xml string
 * @return {Object} xml root.
 */
function parseXML(svg) {
    if (isString(svg)) {
        var parser = new DOMParser();
        svg = parser.parseFromString(svg, 'text/xml');
    }

    // Document node. If using $.get, doc node may be input.
    if (svg.nodeType === 9) {
        svg = svg.firstChild;
    }
    // nodeName of <!DOCTYPE svg> is also 'svg'.
    while (svg.nodeName.toLowerCase() !== 'svg' || svg.nodeType !== 1) {
        svg = svg.nextSibling;
    }

    return svg;
}

function SVGParser() {
    this._defs = {};
    this._root = null;

    this._isDefine = false;
    this._isText = false;
}

SVGParser.prototype.parse = function (xml, opt) {
    opt = opt || {};

    var svg = parseXML(xml);

    if (!svg) {
        throw new Error('Illegal svg');
    }

    var root = new Group();
    this._root = root;
    // parse view port
    var viewBox = svg.getAttribute('viewBox') || '';

    // If width/height not specified, means "100%" of `opt.width/height`.
    // TODO: Other percent value not supported yet.
    var width = parseFloat(svg.getAttribute('width') || opt.width);
    var height = parseFloat(svg.getAttribute('height') || opt.height);
    // If width/height not specified, set as null for output.
    isNaN(width) && (width = null);
    isNaN(height) && (height = null);

    // Apply inline style on svg element.
    parseAttributes(svg, root, null, true);

    var child = svg.firstChild;
    while (child) {
        this._parseNode(child, root);
        child = child.nextSibling;
    }

    var viewBoxRect;
    var viewBoxTransform;

    if (viewBox) {
        var viewBoxArr = trim(viewBox).split(DILIMITER_REG);
        // Some invalid case like viewBox: 'none'.
        if (viewBoxArr.length >= 4) {
            viewBoxRect = {
                x: parseFloat(viewBoxArr[0] || 0),
                y: parseFloat(viewBoxArr[1] || 0),
                width: parseFloat(viewBoxArr[2]),
                height: parseFloat(viewBoxArr[3])
            };
        }
    }

    if (viewBoxRect && width != null && height != null) {
        viewBoxTransform = makeViewBoxTransform(viewBoxRect, width, height);

        if (!opt.ignoreViewBox) {
            // If set transform on the output group, it probably bring trouble when
            // some users only intend to show the clipped content inside the viewBox,
            // but not intend to transform the output group. So we keep the output
            // group no transform. If the user intend to use the viewBox as a
            // camera, just set `opt.ignoreViewBox` as `true` and set transfrom
            // manually according to the viewBox info in the output of this method.
            var elRoot = root;
            root = new Group();
            root.add(elRoot);
            elRoot.scale = viewBoxTransform.scale.slice();
            elRoot.position = viewBoxTransform.position.slice();
        }
    }

    // Some shapes might be overflow the viewport, which should be
    // clipped despite whether the viewBox is used, as the SVG does.
    if (!opt.ignoreRootClip && width != null && height != null) {
        root.setClipPath(new Rect({
            shape: {x: 0, y: 0, width: width, height: height}
        }));
    }

    // Set width/height on group just for output the viewport size.
    return {
        root: root,
        width: width,
        height: height,
        viewBoxRect: viewBoxRect,
        viewBoxTransform: viewBoxTransform
    };
};

SVGParser.prototype._parseNode = function (xmlNode, parentGroup) {

    var nodeName = xmlNode.nodeName.toLowerCase();

    // TODO
    // support <style>...</style> in svg, where nodeName is 'style',
    // CSS classes is defined globally wherever the style tags are declared.

    if (nodeName === 'defs') {
        // define flag
        this._isDefine = true;
    }
    else if (nodeName === 'text') {
        this._isText = true;
    }

    var el;
    if (this._isDefine) {
        var parser = defineParsers[nodeName];
        if (parser) {
            var def = parser.call(this, xmlNode);
            var id = xmlNode.getAttribute('id');
            if (id) {
                this._defs[id] = def;
            }
        }
    }
    else {
        var parser = nodeParsers[nodeName];
        if (parser) {
            el = parser.call(this, xmlNode, parentGroup);
            parentGroup.add(el);
        }
    }

    var child = xmlNode.firstChild;
    while (child) {
        if (child.nodeType === 1) {
            this._parseNode(child, el);
        }
        // Is text
        if (child.nodeType === 3 && this._isText) {
            this._parseText(child, el);
        }
        child = child.nextSibling;
    }

    // Quit define
    if (nodeName === 'defs') {
        this._isDefine = false;
    }
    else if (nodeName === 'text') {
        this._isText = false;
    }
};

SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
    if (xmlNode.nodeType === 1) {
        var dx = xmlNode.getAttribute('dx') || 0;
        var dy = xmlNode.getAttribute('dy') || 0;
        this._textX += parseFloat(dx);
        this._textY += parseFloat(dy);
    }

    var text = new Text({
        style: {
            text: xmlNode.textContent,
            transformText: true
        },
        position: [this._textX || 0, this._textY || 0]
    });

    inheritStyle(parentGroup, text);
    parseAttributes(xmlNode, text, this._defs);

    var fontSize = text.style.fontSize;
    if (fontSize && fontSize < 9) {
        // PENDING
        text.style.fontSize = 9;
        text.scale = text.scale || [1, 1];
        text.scale[0] *= fontSize / 9;
        text.scale[1] *= fontSize / 9;
    }

    var rect = text.getBoundingRect();
    this._textX += rect.width;

    parentGroup.add(text);

    return text;
};

var nodeParsers = {
    'g': function (xmlNode, parentGroup) {
        var g = new Group();
        inheritStyle(parentGroup, g);
        parseAttributes(xmlNode, g, this._defs);

        return g;
    },
    'rect': function (xmlNode, parentGroup) {
        var rect = new Rect();
        inheritStyle(parentGroup, rect);
        parseAttributes(xmlNode, rect, this._defs);

        rect.setShape({
            x: parseFloat(xmlNode.getAttribute('x') || 0),
            y: parseFloat(xmlNode.getAttribute('y') || 0),
            width: parseFloat(xmlNode.getAttribute('width') || 0),
            height: parseFloat(xmlNode.getAttribute('height') || 0)
        });

        // console.log(xmlNode.getAttribute('transform'));
        // console.log(rect.transform);

        return rect;
    },
    'circle': function (xmlNode, parentGroup) {
        var circle = new Circle();
        inheritStyle(parentGroup, circle);
        parseAttributes(xmlNode, circle, this._defs);

        circle.setShape({
            cx: parseFloat(xmlNode.getAttribute('cx') || 0),
            cy: parseFloat(xmlNode.getAttribute('cy') || 0),
            r: parseFloat(xmlNode.getAttribute('r') || 0)
        });

        return circle;
    },
    'line': function (xmlNode, parentGroup) {
        var line = new Line();
        inheritStyle(parentGroup, line);
        parseAttributes(xmlNode, line, this._defs);

        line.setShape({
            x1: parseFloat(xmlNode.getAttribute('x1') || 0),
            y1: parseFloat(xmlNode.getAttribute('y1') || 0),
            x2: parseFloat(xmlNode.getAttribute('x2') || 0),
            y2: parseFloat(xmlNode.getAttribute('y2') || 0)
        });

        return line;
    },
    'ellipse': function (xmlNode, parentGroup) {
        var ellipse = new Ellipse();
        inheritStyle(parentGroup, ellipse);
        parseAttributes(xmlNode, ellipse, this._defs);

        ellipse.setShape({
            cx: parseFloat(xmlNode.getAttribute('cx') || 0),
            cy: parseFloat(xmlNode.getAttribute('cy') || 0),
            rx: parseFloat(xmlNode.getAttribute('rx') || 0),
            ry: parseFloat(xmlNode.getAttribute('ry') || 0)
        });
        return ellipse;
    },
    'polygon': function (xmlNode, parentGroup) {
        var points = xmlNode.getAttribute('points');
        if (points) {
            points = parsePoints(points);
        }
        var polygon = new Polygon({
            shape: {
                points: points || []
            }
        });

        inheritStyle(parentGroup, polygon);
        parseAttributes(xmlNode, polygon, this._defs);

        return polygon;
    },
    'polyline': function (xmlNode, parentGroup) {
        var path = new Path();
        inheritStyle(parentGroup, path);
        parseAttributes(xmlNode, path, this._defs);

        var points = xmlNode.getAttribute('points');
        if (points) {
            points = parsePoints(points);
        }
        var polyline = new Polyline({
            shape: {
                points: points || []
            }
        });

        return polyline;
    },
    'image': function (xmlNode, parentGroup) {
        var img = new ZImage();
        inheritStyle(parentGroup, img);
        parseAttributes(xmlNode, img, this._defs);

        img.setStyle({
            image: xmlNode.getAttribute('xlink:href'),
            x: xmlNode.getAttribute('x'),
            y: xmlNode.getAttribute('y'),
            width: xmlNode.getAttribute('width'),
            height: xmlNode.getAttribute('height')
        });

        return img;
    },
    'text': function (xmlNode, parentGroup) {
        var x = xmlNode.getAttribute('x') || 0;
        var y = xmlNode.getAttribute('y') || 0;
        var dx = xmlNode.getAttribute('dx') || 0;
        var dy = xmlNode.getAttribute('dy') || 0;

        this._textX = parseFloat(x) + parseFloat(dx);
        this._textY = parseFloat(y) + parseFloat(dy);

        var g = new Group();
        inheritStyle(parentGroup, g);
        parseAttributes(xmlNode, g, this._defs);

        return g;
    },
    'tspan': function (xmlNode, parentGroup) {
        var x = xmlNode.getAttribute('x');
        var y = xmlNode.getAttribute('y');
        if (x != null) {
            // new offset x
            this._textX = parseFloat(x);
        }
        if (y != null) {
            // new offset y
            this._textY = parseFloat(y);
        }
        var dx = xmlNode.getAttribute('dx') || 0;
        var dy = xmlNode.getAttribute('dy') || 0;

        var g = new Group();

        inheritStyle(parentGroup, g);
        parseAttributes(xmlNode, g, this._defs);


        this._textX += dx;
        this._textY += dy;

        return g;
    },
    'path': function (xmlNode, parentGroup) {
        // TODO svg fill rule
        // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule
        // path.style.globalCompositeOperation = 'xor';
        var d = xmlNode.getAttribute('d') || '';

        // Performance sensitive.

        var path = createFromString(d);

        inheritStyle(parentGroup, path);
        parseAttributes(xmlNode, path, this._defs);

        return path;
    }
};

var defineParsers = {

    'lineargradient': function (xmlNode) {
        var x1 = parseInt(xmlNode.getAttribute('x1') || 0, 10);
        var y1 = parseInt(xmlNode.getAttribute('y1') || 0, 10);
        var x2 = parseInt(xmlNode.getAttribute('x2') || 10, 10);
        var y2 = parseInt(xmlNode.getAttribute('y2') || 0, 10);

        var gradient = new LinearGradient(x1, y1, x2, y2);

        _parseGradientColorStops(xmlNode, gradient);

        return gradient;
    },

    'radialgradient': function (xmlNode) {

    }
};

function _parseGradientColorStops(xmlNode, gradient) {

    var stop = xmlNode.firstChild;

    while (stop) {
        if (stop.nodeType === 1) {
            var offset = stop.getAttribute('offset');
            if (offset.indexOf('%') > 0) {  // percentage
                offset = parseInt(offset, 10) / 100;
            }
            else if (offset) {    // number from 0 to 1
                offset = parseFloat(offset);
            }
            else {
                offset = 0;
            }

            var stopColor = stop.getAttribute('stop-color') || '#000000';

            gradient.addColorStop(offset, stopColor);
        }
        stop = stop.nextSibling;
    }
}

function inheritStyle(parent, child) {
    if (parent && parent.__inheritedStyle) {
        if (!child.__inheritedStyle) {
            child.__inheritedStyle = {};
        }
        defaults(child.__inheritedStyle, parent.__inheritedStyle);
    }
}

function parsePoints(pointsString) {
    var list = trim(pointsString).split(DILIMITER_REG);
    var points = [];

    for (var i = 0; i < list.length; i += 2) {
        var x = parseFloat(list[i]);
        var y = parseFloat(list[i + 1]);
        points.push([x, y]);
    }
    return points;
}

var attributesMap = {
    'fill': 'fill',
    'stroke': 'stroke',
    'stroke-width': 'lineWidth',
    'opacity': 'opacity',
    'fill-opacity': 'fillOpacity',
    'stroke-opacity': 'strokeOpacity',
    'stroke-dasharray': 'lineDash',
    'stroke-dashoffset': 'lineDashOffset',
    'stroke-linecap': 'lineCap',
    'stroke-linejoin': 'lineJoin',
    'stroke-miterlimit': 'miterLimit',
    'font-family': 'fontFamily',
    'font-size': 'fontSize',
    'font-style': 'fontStyle',
    'font-weight': 'fontWeight',

    'text-align': 'textAlign',
    'alignment-baseline': 'textBaseline'
};

function parseAttributes(xmlNode, el, defs, onlyInlineStyle) {
    var zrStyle = el.__inheritedStyle || {};
    var isTextEl = el.type === 'text';

    // TODO Shadow
    if (xmlNode.nodeType === 1) {
        parseTransformAttribute(xmlNode, el);

        extend(zrStyle, parseStyleAttribute(xmlNode));

        if (!onlyInlineStyle) {
            for (var svgAttrName in attributesMap) {
                if (attributesMap.hasOwnProperty(svgAttrName)) {
                    var attrValue = xmlNode.getAttribute(svgAttrName);
                    if (attrValue != null) {
                        zrStyle[attributesMap[svgAttrName]] = attrValue;
                    }
                }
            }
        }
    }

    var elFillProp = isTextEl ? 'textFill' : 'fill';
    var elStrokeProp = isTextEl ? 'textStroke' : 'stroke';

    el.style = el.style || new Style();
    var elStyle = el.style;

    zrStyle.fill != null && elStyle.set(elFillProp, getPaint(zrStyle.fill, defs));
    zrStyle.stroke != null && elStyle.set(elStrokeProp, getPaint(zrStyle.stroke, defs));

    each$1([
        'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'
    ], function (propName) {
        var elPropName = (propName === 'lineWidth' && isTextEl) ? 'textStrokeWidth' : propName;
        zrStyle[propName] != null && elStyle.set(elPropName, parseFloat(zrStyle[propName]));
    });

    if (!zrStyle.textBaseline || zrStyle.textBaseline === 'auto') {
        zrStyle.textBaseline = 'alphabetic';
    }
    if (zrStyle.textBaseline === 'alphabetic') {
        zrStyle.textBaseline = 'bottom';
    }
    if (zrStyle.textAlign === 'start') {
        zrStyle.textAlign = 'left';
    }
    if (zrStyle.textAlign === 'end') {
        zrStyle.textAlign = 'right';
    }

    each$1(['lineDashOffset', 'lineCap', 'lineJoin',
        'fontWeight', 'fontFamily', 'fontStyle', 'textAlign', 'textBaseline'
    ], function (propName) {
        zrStyle[propName] != null && elStyle.set(propName, zrStyle[propName]);
    });

    if (zrStyle.lineDash) {
        el.style.lineDash = trim(zrStyle.lineDash).split(DILIMITER_REG);
    }

    if (elStyle[elStrokeProp] && elStyle[elStrokeProp] !== 'none') {
        // enable stroke
        el[elStrokeProp] = true;
    }

    el.__inheritedStyle = zrStyle;
}


var urlRegex = /url\(\s*#(.*?)\)/;
function getPaint(str, defs) {
    // if (str === 'none') {
    //     return;
    // }
    var urlMatch = defs && str && str.match(urlRegex);
    if (urlMatch) {
        var url = trim(urlMatch[1]);
        var def = defs[url];
        return def;
    }
    return str;
}

var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g;

function parseTransformAttribute(xmlNode, node) {
    var transform = xmlNode.getAttribute('transform');
    if (transform) {
        transform = transform.replace(/,/g, ' ');
        var m = null;
        var transformOps = [];
        transform.replace(transformRegex, function (str, type, value) {
            transformOps.push(type, value);
        });
        for (var i = transformOps.length - 1; i > 0; i -= 2) {
            var value = transformOps[i];
            var type = transformOps[i - 1];
            m = m || create$1();
            switch (type) {
                case 'translate':
                    value = trim(value).split(DILIMITER_REG);
                    translate(m, m, [parseFloat(value[0]), parseFloat(value[1] || 0)]);
                    break;
                case 'scale':
                    value = trim(value).split(DILIMITER_REG);
                    scale$1(m, m, [parseFloat(value[0]), parseFloat(value[1] || value[0])]);
                    break;
                case 'rotate':
                    value = trim(value).split(DILIMITER_REG);
                    rotate(m, m, parseFloat(value[0]));
                    break;
                case 'skew':
                    value = trim(value).split(DILIMITER_REG);
                    console.warn('Skew transform is not supported yet');
                    break;
                case 'matrix':
                    var value = trim(value).split(DILIMITER_REG);
                    m[0] = parseFloat(value[0]);
                    m[1] = parseFloat(value[1]);
                    m[2] = parseFloat(value[2]);
                    m[3] = parseFloat(value[3]);
                    m[4] = parseFloat(value[4]);
                    m[5] = parseFloat(value[5]);
                    break;
            }
        }
        node.setLocalTransform(m);
    }
}

// Value may contain space.
var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;
function parseStyleAttribute(xmlNode) {
    var style = xmlNode.getAttribute('style');
    var result = {};

    if (!style) {
        return result;
    }

    var styleList = {};
    styleRegex.lastIndex = 0;
    var styleRegResult;
    while ((styleRegResult = styleRegex.exec(style)) != null) {
        styleList[styleRegResult[1]] = styleRegResult[2];
    }

    for (var svgAttrName in attributesMap) {
        if (attributesMap.hasOwnProperty(svgAttrName) && styleList[svgAttrName] != null) {
            result[attributesMap[svgAttrName]] = styleList[svgAttrName];
        }
    }

    return result;
}

/**
 * @param {Array.<number>} viewBoxRect
 * @param {number} width
 * @param {number} height
 * @return {Object} {scale, position}
 */
function makeViewBoxTransform(viewBoxRect, width, height) {
    var scaleX = width / viewBoxRect.width;
    var scaleY = height / viewBoxRect.height;
    var scale = Math.min(scaleX, scaleY);
    // preserveAspectRatio 'xMidYMid'
    var viewBoxScale = [scale, scale];
    var viewBoxPosition = [
        -(viewBoxRect.x + viewBoxRect.width / 2) * scale + width / 2,
        -(viewBoxRect.y + viewBoxRect.height / 2) * scale + height / 2
    ];

    return {
        scale: viewBoxScale,
        position: viewBoxPosition
    };
}

/**
 * @param {string|XMLElement} xml
 * @param {Object} [opt]
 * @param {number} [opt.width] Default width if svg width not specified or is a percent value.
 * @param {number} [opt.height] Default height if svg height not specified or is a percent value.
 * @param {boolean} [opt.ignoreViewBox]
 * @param {boolean} [opt.ignoreRootClip]
 * @return {Object} result:
 * {
 *     root: Group, The root of the the result tree of zrender shapes,
 *     width: number, the viewport width of the SVG,
 *     height: number, the viewport height of the SVG,
 *     viewBoxRect: {x, y, width, height}, the declared viewBox rect of the SVG, if exists,
 *     viewBoxTransform: the {scale, position} calculated by viewBox and viewport, is exists.
 * }
 */
function parseSVG(xml, opt) {
    var parser = new SVGParser();
    return parser.parse(xml, opt);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var storage = createHashMap();

// For minimize the code size of common echarts package,
// do not put too much logic in this module.

var mapDataStorage = {

    // The format of record: see `echarts.registerMap`.
    // Compatible with previous `echarts.registerMap`.
    registerMap: function (mapName, rawGeoJson, rawSpecialAreas) {

        var records;

        if (isArray(rawGeoJson)) {
            records = rawGeoJson;
        }
        else if (rawGeoJson.svg) {
            records = [{
                type: 'svg',
                source: rawGeoJson.svg,
                specialAreas: rawGeoJson.specialAreas
            }];
        }
        else {
            // Backward compatibility.
            if (rawGeoJson.geoJson && !rawGeoJson.features) {
                rawSpecialAreas = rawGeoJson.specialAreas;
                rawGeoJson = rawGeoJson.geoJson;
            }
            records = [{
                type: 'geoJSON',
                source: rawGeoJson,
                specialAreas: rawSpecialAreas
            }];
        }

        each$1(records, function (record) {
            var type = record.type;
            type === 'geoJson' && (type = record.type = 'geoJSON');

            var parse = parsers[type];

            if (__DEV__) {
                assert$1(parse, 'Illegal map type: ' + type);
            }

            parse(record);
        });

        return storage.set(mapName, records);
    },

    retrieveMap: function (mapName) {
        return storage.get(mapName);
    }

};

var parsers = {

    geoJSON: function (record) {
        var source = record.source;
        record.geoJSON = !isString(source)
            ? source
            : (typeof JSON !== 'undefined' && JSON.parse)
            ? JSON.parse(source)
            : (new Function('return (' + source + ');'))();
    },

    // Only perform parse to XML object here, which might be time
    // consiming for large SVG.
    // Although convert XML to zrender element is also time consiming,
    // if we do it here, the clone of zrender elements has to be
    // required. So we do it once for each geo instance, util real
    // performance issues call for optimizing it.
    svg: function (record) {
        record.svgXML = parseXML(record.source);
    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var assert = assert$1;
var each = each$1;
var isFunction = isFunction$1;
var isObject = isObject$1;
var parseClassType = ComponentModel.parseClassType;

var version = '4.5.0';

var dependencies = {
    zrender: '4.1.2'
};

var TEST_FRAME_REMAIN_TIME = 1;

var PRIORITY_PROCESSOR_FILTER = 1000;
var PRIORITY_PROCESSOR_SERIES_FILTER = 800;
var PRIORITY_PROCESSOR_DATASTACK = 900;
var PRIORITY_PROCESSOR_STATISTIC = 5000;

var PRIORITY_VISUAL_LAYOUT = 1000;
var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
var PRIORITY_VISUAL_GLOBAL = 2000;
var PRIORITY_VISUAL_CHART = 3000;
var PRIORITY_VISUAL_POST_CHART_LAYOUT = 3500;
var PRIORITY_VISUAL_COMPONENT = 4000;
// FIXME
// necessary?
var PRIORITY_VISUAL_BRUSH = 5000;

var PRIORITY = {
    PROCESSOR: {
        FILTER: PRIORITY_PROCESSOR_FILTER,
        SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
        STATISTIC: PRIORITY_PROCESSOR_STATISTIC
    },
    VISUAL: {
        LAYOUT: PRIORITY_VISUAL_LAYOUT,
        PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
        GLOBAL: PRIORITY_VISUAL_GLOBAL,
        CHART: PRIORITY_VISUAL_CHART,
        POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
        COMPONENT: PRIORITY_VISUAL_COMPONENT,
        BRUSH: PRIORITY_VISUAL_BRUSH
    }
};

// Main process have three entries: `setOption`, `dispatchAction` and `resize`,
// where they must not be invoked nestedly, except the only case: invoke
// dispatchAction with updateMethod "none" in main process.
// This flag is used to carry out this rule.
// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
var IN_MAIN_PROCESS = '__flagInMainProcess';
var OPTION_UPDATED = '__optionUpdated';
var ACTION_REG = /^[a-zA-Z0-9_]+$/;


function createRegisterEventWithLowercaseName(method, ignoreDisposed) {
    return function (eventName, handler, context) {
        if (!ignoreDisposed && this._disposed) {
            disposedWarning(this.id);
            return;
        }

        // Event name is all lowercase
        eventName = eventName && eventName.toLowerCase();
        Eventful.prototype[method].call(this, eventName, handler, context);
    };
}

/**
 * @module echarts~MessageCenter
 */
function MessageCenter() {
    Eventful.call(this);
}
MessageCenter.prototype.on = createRegisterEventWithLowercaseName('on', true);
MessageCenter.prototype.off = createRegisterEventWithLowercaseName('off', true);
MessageCenter.prototype.one = createRegisterEventWithLowercaseName('one', true);
mixin(MessageCenter, Eventful);

/**
 * @module echarts~ECharts
 */
function ECharts(dom, theme$$1, opts) {
    opts = opts || {};

    // Get theme by name
    if (typeof theme$$1 === 'string') {
        theme$$1 = themeStorage[theme$$1];
    }

    /**
     * @type {string}
     */
    this.id;

    /**
     * Group id
     * @type {string}
     */
    this.group;

    /**
     * @type {HTMLElement}
     * @private
     */
    this._dom = dom;

    var defaultRenderer = 'canvas';
    if (__DEV__) {
        defaultRenderer = (
            typeof window === 'undefined' ? global : window
        ).__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;
    }

    /**
     * @type {module:zrender/ZRender}
     * @private
     */
    var zr = this._zr = init$1(dom, {
        renderer: opts.renderer || defaultRenderer,
        devicePixelRatio: opts.devicePixelRatio,
        width: opts.width,
        height: opts.height
    });

    /**
     * Expect 60 fps.
     * @type {Function}
     * @private
     */
    this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);

    var theme$$1 = clone(theme$$1);
    theme$$1 && backwardCompat(theme$$1, true);
    /**
     * @type {Object}
     * @private
     */
    this._theme = theme$$1;

    /**
     * @type {Array.<module:echarts/view/Chart>}
     * @private
     */
    this._chartsViews = [];

    /**
     * @type {Object.<string, module:echarts/view/Chart>}
     * @private
     */
    this._chartsMap = {};

    /**
     * @type {Array.<module:echarts/view/Component>}
     * @private
     */
    this._componentsViews = [];

    /**
     * @type {Object.<string, module:echarts/view/Component>}
     * @private
     */
    this._componentsMap = {};

    /**
     * @type {module:echarts/CoordinateSystem}
     * @private
     */
    this._coordSysMgr = new CoordinateSystemManager();

    /**
     * @type {module:echarts/ExtensionAPI}
     * @private
     */
    var api = this._api = createExtensionAPI(this);

    // Sort on demand
    function prioritySortFunc(a, b) {
        return a.__prio - b.__prio;
    }
    sort(visualFuncs, prioritySortFunc);
    sort(dataProcessorFuncs, prioritySortFunc);

    /**
     * @type {module:echarts/stream/Scheduler}
     */
    this._scheduler = new Scheduler(this, api, dataProcessorFuncs, visualFuncs);

    Eventful.call(this, this._ecEventProcessor = new EventProcessor());

    /**
     * @type {module:echarts~MessageCenter}
     * @private
     */
    this._messageCenter = new MessageCenter();

    // Init mouse events
    this._initEvents();

    // In case some people write `window.onresize = chart.resize`
    this.resize = bind(this.resize, this);

    // Can't dispatch action during rendering procedure
    this._pendingActions = [];

    zr.animation.on('frame', this._onframe, this);

    bindRenderedEvent(zr, this);

    // ECharts instance can be used as value.
    setAsPrimitive(this);
}

var echartsProto = ECharts.prototype;

echartsProto._onframe = function () {
    if (this._disposed) {
        return;
    }

    var scheduler = this._scheduler;

    // Lazy update
    if (this[OPTION_UPDATED]) {
        var silent = this[OPTION_UPDATED].silent;

        this[IN_MAIN_PROCESS] = true;

        prepare(this);
        updateMethods.update.call(this);

        this[IN_MAIN_PROCESS] = false;

        this[OPTION_UPDATED] = false;

        flushPendingActions.call(this, silent);

        triggerUpdatedEvent.call(this, silent);
    }
    // Avoid do both lazy update and progress in one frame.
    else if (scheduler.unfinished) {
        // Stream progress.
        var remainTime = TEST_FRAME_REMAIN_TIME;
        var ecModel = this._model;
        var api = this._api;
        scheduler.unfinished = false;
        do {
            var startTime = +new Date();

            scheduler.performSeriesTasks(ecModel);

            // Currently dataProcessorFuncs do not check threshold.
            scheduler.performDataProcessorTasks(ecModel);

            updateStreamModes(this, ecModel);

            // Do not update coordinate system here. Because that coord system update in
            // each frame is not a good user experience. So we follow the rule that
            // the extent of the coordinate system is determin in the first frame (the
            // frame is executed immedietely after task reset.
            // this._coordSysMgr.update(ecModel, api);

            // console.log('--- ec frame visual ---', remainTime);
            scheduler.performVisualTasks(ecModel);

            renderSeries(this, this._model, api, 'remain');

            remainTime -= (+new Date() - startTime);
        }
        while (remainTime > 0 && scheduler.unfinished);

        // Call flush explicitly for trigger finished event.
        if (!scheduler.unfinished) {
            this._zr.flush();
        }
        // Else, zr flushing be ensue within the same frame,
        // because zr flushing is after onframe event.
    }
};

/**
 * @return {HTMLElement}
 */
echartsProto.getDom = function () {
    return this._dom;
};

/**
 * @return {module:zrender~ZRender}
 */
echartsProto.getZr = function () {
    return this._zr;
};

/**
 * Usage:
 * chart.setOption(option, notMerge, lazyUpdate);
 * chart.setOption(option, {
 *     notMerge: ...,
 *     lazyUpdate: ...,
 *     silent: ...
 * });
 *
 * @param {Object} option
 * @param {Object|boolean} [opts] opts or notMerge.
 * @param {boolean} [opts.notMerge=false]
 * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently.
 */
echartsProto.setOption = function (option, notMerge, lazyUpdate) {
    if (__DEV__) {
        assert(!this[IN_MAIN_PROCESS], '`setOption` should not be called during main process.');
    }
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    var silent;
    if (isObject(notMerge)) {
        lazyUpdate = notMerge.lazyUpdate;
        silent = notMerge.silent;
        notMerge = notMerge.notMerge;
    }

    this[IN_MAIN_PROCESS] = true;

    if (!this._model || notMerge) {
        var optionManager = new OptionManager(this._api);
        var theme$$1 = this._theme;
        var ecModel = this._model = new GlobalModel();
        ecModel.scheduler = this._scheduler;
        ecModel.init(null, null, theme$$1, optionManager);
    }

    this._model.setOption(option, optionPreprocessorFuncs);

    if (lazyUpdate) {
        this[OPTION_UPDATED] = {silent: silent};
        this[IN_MAIN_PROCESS] = false;
    }
    else {
        prepare(this);

        updateMethods.update.call(this);

        // Ensure zr refresh sychronously, and then pixel in canvas can be
        // fetched after `setOption`.
        this._zr.flush();

        this[OPTION_UPDATED] = false;
        this[IN_MAIN_PROCESS] = false;

        flushPendingActions.call(this, silent);
        triggerUpdatedEvent.call(this, silent);
    }
};

/**
 * @DEPRECATED
 */
echartsProto.setTheme = function () {
    console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
};

/**
 * @return {module:echarts/model/Global}
 */
echartsProto.getModel = function () {
    return this._model;
};

/**
 * @return {Object}
 */
echartsProto.getOption = function () {
    return this._model && this._model.getOption();
};

/**
 * @return {number}
 */
echartsProto.getWidth = function () {
    return this._zr.getWidth();
};

/**
 * @return {number}
 */
echartsProto.getHeight = function () {
    return this._zr.getHeight();
};

/**
 * @return {number}
 */
echartsProto.getDevicePixelRatio = function () {
    return this._zr.painter.dpr || window.devicePixelRatio || 1;
};

/**
 * Get canvas which has all thing rendered
 * @param {Object} opts
 * @param {string} [opts.backgroundColor]
 * @return {string}
 */
echartsProto.getRenderedCanvas = function (opts) {
    if (!env$1.canvasSupported) {
        return;
    }
    opts = opts || {};
    opts.pixelRatio = opts.pixelRatio || 1;
    opts.backgroundColor = opts.backgroundColor
        || this._model.get('backgroundColor');
    var zr = this._zr;
    // var list = zr.storage.getDisplayList();
    // Stop animations
    // Never works before in init animation, so remove it.
    // zrUtil.each(list, function (el) {
    //     el.stopAnimation(true);
    // });
    return zr.painter.getRenderedCanvas(opts);
};

/**
 * Get svg data url
 * @return {string}
 */
echartsProto.getSvgDataUrl = function () {
    if (!env$1.svgSupported) {
        return;
    }

    var zr = this._zr;
    var list = zr.storage.getDisplayList();
    // Stop animations
    each$1(list, function (el) {
        el.stopAnimation(true);
    });

    return zr.painter.pathToDataUrl();
};

/**
 * @return {string}
 * @param {Object} opts
 * @param {string} [opts.type='png']
 * @param {string} [opts.pixelRatio=1]
 * @param {string} [opts.backgroundColor]
 * @param {string} [opts.excludeComponents]
 */
echartsProto.getDataURL = function (opts) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    opts = opts || {};
    var excludeComponents = opts.excludeComponents;
    var ecModel = this._model;
    var excludesComponentViews = [];
    var self = this;

    each(excludeComponents, function (componentType) {
        ecModel.eachComponent({
            mainType: componentType
        }, function (component) {
            var view = self._componentsMap[component.__viewId];
            if (!view.group.ignore) {
                excludesComponentViews.push(view);
                view.group.ignore = true;
            }
        });
    });

    var url = this._zr.painter.getType() === 'svg'
        ? this.getSvgDataUrl()
        : this.getRenderedCanvas(opts).toDataURL(
            'image/' + (opts && opts.type || 'png')
        );

    each(excludesComponentViews, function (view) {
        view.group.ignore = false;
    });

    return url;
};


/**
 * @return {string}
 * @param {Object} opts
 * @param {string} [opts.type='png']
 * @param {string} [opts.pixelRatio=1]
 * @param {string} [opts.backgroundColor]
 */
echartsProto.getConnectedDataURL = function (opts) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    if (!env$1.canvasSupported) {
        return;
    }
    var groupId = this.group;
    var mathMin = Math.min;
    var mathMax = Math.max;
    var MAX_NUMBER = Infinity;
    if (connectedGroups[groupId]) {
        var left = MAX_NUMBER;
        var top = MAX_NUMBER;
        var right = -MAX_NUMBER;
        var bottom = -MAX_NUMBER;
        var canvasList = [];
        var dpr = (opts && opts.pixelRatio) || 1;

        each$1(instances, function (chart, id) {
            if (chart.group === groupId) {
                var canvas = chart.getRenderedCanvas(
                    clone(opts)
                );
                var boundingRect = chart.getDom().getBoundingClientRect();
                left = mathMin(boundingRect.left, left);
                top = mathMin(boundingRect.top, top);
                right = mathMax(boundingRect.right, right);
                bottom = mathMax(boundingRect.bottom, bottom);
                canvasList.push({
                    dom: canvas,
                    left: boundingRect.left,
                    top: boundingRect.top
                });
            }
        });

        left *= dpr;
        top *= dpr;
        right *= dpr;
        bottom *= dpr;
        var width = right - left;
        var height = bottom - top;
        var targetCanvas = createCanvas();
        targetCanvas.width = width;
        targetCanvas.height = height;
        var zr = init$1(targetCanvas);

        // Background between the charts
        if (opts.connectedBackgroundColor) {
            zr.add(new Rect({
                shape: {
                    x: 0,
                    y: 0,
                    width: width,
                    height: height
                },
                style: {
                    fill: opts.connectedBackgroundColor
                }
            }));
        }

        each(canvasList, function (item) {
            var img = new ZImage({
                style: {
                    x: item.left * dpr - left,
                    y: item.top * dpr - top,
                    image: item.dom
                }
            });
            zr.add(img);
        });
        zr.refreshImmediately();

        return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
    }
    else {
        return this.getDataURL(opts);
    }
};

/**
 * Convert from logical coordinate system to pixel coordinate system.
 * See CoordinateSystem#convertToPixel.
 * @param {string|Object} finder
 *        If string, e.g., 'geo', means {geoIndex: 0}.
 *        If Object, could contain some of these properties below:
 *        {
 *            seriesIndex / seriesId / seriesName,
 *            geoIndex / geoId, geoName,
 *            bmapIndex / bmapId / bmapName,
 *            xAxisIndex / xAxisId / xAxisName,
 *            yAxisIndex / yAxisId / yAxisName,
 *            gridIndex / gridId / gridName,
 *            ... (can be extended)
 *        }
 * @param {Array|number} value
 * @return {Array|number} result
 */
echartsProto.convertToPixel = curry(doConvertPixel, 'convertToPixel');

/**
 * Convert from pixel coordinate system to logical coordinate system.
 * See CoordinateSystem#convertFromPixel.
 * @param {string|Object} finder
 *        If string, e.g., 'geo', means {geoIndex: 0}.
 *        If Object, could contain some of these properties below:
 *        {
 *            seriesIndex / seriesId / seriesName,
 *            geoIndex / geoId / geoName,
 *            bmapIndex / bmapId / bmapName,
 *            xAxisIndex / xAxisId / xAxisName,
 *            yAxisIndex / yAxisId / yAxisName
 *            gridIndex / gridId / gridName,
 *            ... (can be extended)
 *        }
 * @param {Array|number} value
 * @return {Array|number} result
 */
echartsProto.convertFromPixel = curry(doConvertPixel, 'convertFromPixel');

function doConvertPixel(methodName, finder, value) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    var ecModel = this._model;
    var coordSysList = this._coordSysMgr.getCoordinateSystems();
    var result;

    finder = parseFinder(ecModel, finder);

    for (var i = 0; i < coordSysList.length; i++) {
        var coordSys = coordSysList[i];
        if (coordSys[methodName]
            && (result = coordSys[methodName](ecModel, finder, value)) != null
        ) {
            return result;
        }
    }

    if (__DEV__) {
        console.warn(
            'No coordinate system that supports ' + methodName + ' found by the given finder.'
        );
    }
}

/**
 * Is the specified coordinate systems or components contain the given pixel point.
 * @param {string|Object} finder
 *        If string, e.g., 'geo', means {geoIndex: 0}.
 *        If Object, could contain some of these properties below:
 *        {
 *            seriesIndex / seriesId / seriesName,
 *            geoIndex / geoId / geoName,
 *            bmapIndex / bmapId / bmapName,
 *            xAxisIndex / xAxisId / xAxisName,
 *            yAxisIndex / yAxisId / yAxisName,
 *            gridIndex / gridId / gridName,
 *            ... (can be extended)
 *        }
 * @param {Array|number} value
 * @return {boolean} result
 */
echartsProto.containPixel = function (finder, value) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    var ecModel = this._model;
    var result;

    finder = parseFinder(ecModel, finder);

    each$1(finder, function (models, key) {
        key.indexOf('Models') >= 0 && each$1(models, function (model) {
            var coordSys = model.coordinateSystem;
            if (coordSys && coordSys.containPoint) {
                result |= !!coordSys.containPoint(value);
            }
            else if (key === 'seriesModels') {
                var view = this._chartsMap[model.__viewId];
                if (view && view.containPoint) {
                    result |= view.containPoint(value, model);
                }
                else {
                    if (__DEV__) {
                        console.warn(key + ': ' + (view
                            ? 'The found component do not support containPoint.'
                            : 'No view mapping to the found component.'
                        ));
                    }
                }
            }
            else {
                if (__DEV__) {
                    console.warn(key + ': containPoint is not supported');
                }
            }
        }, this);
    }, this);

    return !!result;
};

/**
 * Get visual from series or data.
 * @param {string|Object} finder
 *        If string, e.g., 'series', means {seriesIndex: 0}.
 *        If Object, could contain some of these properties below:
 *        {
 *            seriesIndex / seriesId / seriesName,
 *            dataIndex / dataIndexInside
 *        }
 *        If dataIndex is not specified, series visual will be fetched,
 *        but not data item visual.
 *        If all of seriesIndex, seriesId, seriesName are not specified,
 *        visual will be fetched from first series.
 * @param {string} visualType 'color', 'symbol', 'symbolSize'
 */
echartsProto.getVisual = function (finder, visualType) {
    var ecModel = this._model;

    finder = parseFinder(ecModel, finder, {defaultMainType: 'series'});

    var seriesModel = finder.seriesModel;

    if (__DEV__) {
        if (!seriesModel) {
            console.warn('There is no specified seires model');
        }
    }

    var data = seriesModel.getData();

    var dataIndexInside = finder.hasOwnProperty('dataIndexInside')
        ? finder.dataIndexInside
        : finder.hasOwnProperty('dataIndex')
        ? data.indexOfRawIndex(finder.dataIndex)
        : null;

    return dataIndexInside != null
        ? data.getItemVisual(dataIndexInside, visualType)
        : data.getVisual(visualType);
};

/**
 * Get view of corresponding component model
 * @param  {module:echarts/model/Component} componentModel
 * @return {module:echarts/view/Component}
 */
echartsProto.getViewOfComponentModel = function (componentModel) {
    return this._componentsMap[componentModel.__viewId];
};

/**
 * Get view of corresponding series model
 * @param  {module:echarts/model/Series} seriesModel
 * @return {module:echarts/view/Chart}
 */
echartsProto.getViewOfSeriesModel = function (seriesModel) {
    return this._chartsMap[seriesModel.__viewId];
};

var updateMethods = {

    prepareAndUpdate: function (payload) {
        prepare(this);
        updateMethods.update.call(this, payload);
    },

    /**
     * @param {Object} payload
     * @private
     */
    update: function (payload) {
        // console.profile && console.profile('update');

        var ecModel = this._model;
        var api = this._api;
        var zr = this._zr;
        var coordSysMgr = this._coordSysMgr;
        var scheduler = this._scheduler;

        // update before setOption
        if (!ecModel) {
            return;
        }

        scheduler.restoreData(ecModel, payload);

        scheduler.performSeriesTasks(ecModel);

        // TODO
        // Save total ecModel here for undo/redo (after restoring data and before processing data).
        // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.

        // Create new coordinate system each update
        // In LineView may save the old coordinate system and use it to get the orignal point
        coordSysMgr.create(ecModel, api);

        scheduler.performDataProcessorTasks(ecModel, payload);

        // Current stream render is not supported in data process. So we can update
        // stream modes after data processing, where the filtered data is used to
        // deteming whether use progressive rendering.
        updateStreamModes(this, ecModel);

        // We update stream modes before coordinate system updated, then the modes info
        // can be fetched when coord sys updating (consider the barGrid extent fix). But
        // the drawback is the full coord info can not be fetched. Fortunately this full
        // coord is not requied in stream mode updater currently.
        coordSysMgr.update(ecModel, api);

        clearColorPalette(ecModel);
        scheduler.performVisualTasks(ecModel, payload);

        render(this, ecModel, api, payload);

        // Set background
        var backgroundColor = ecModel.get('backgroundColor') || 'transparent';

        // In IE8
        if (!env$1.canvasSupported) {
            var colorArr = parse(backgroundColor);
            backgroundColor = stringify(colorArr, 'rgb');
            if (colorArr[3] === 0) {
                backgroundColor = 'transparent';
            }
        }
        else {
            zr.setBackgroundColor(backgroundColor);
        }

        performPostUpdateFuncs(ecModel, api);

        // console.profile && console.profileEnd('update');
    },

    /**
     * @param {Object} payload
     * @private
     */
    updateTransform: function (payload) {
        var ecModel = this._model;
        var ecIns = this;
        var api = this._api;

        // update before setOption
        if (!ecModel) {
            return;
        }

        // ChartView.markUpdateMethod(payload, 'updateTransform');

        var componentDirtyList = [];
        ecModel.eachComponent(function (componentType, componentModel) {
            var componentView = ecIns.getViewOfComponentModel(componentModel);
            if (componentView && componentView.__alive) {
                if (componentView.updateTransform) {
                    var result = componentView.updateTransform(componentModel, ecModel, api, payload);
                    result && result.update && componentDirtyList.push(componentView);
                }
                else {
                    componentDirtyList.push(componentView);
                }
            }
        });

        var seriesDirtyMap = createHashMap();
        ecModel.eachSeries(function (seriesModel) {
            var chartView = ecIns._chartsMap[seriesModel.__viewId];
            if (chartView.updateTransform) {
                var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
                result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
            }
            else {
                seriesDirtyMap.set(seriesModel.uid, 1);
            }
        });

        clearColorPalette(ecModel);
        // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
        // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
        this._scheduler.performVisualTasks(
            ecModel, payload, {setDirty: true, dirtyMap: seriesDirtyMap}
        );

        // Currently, not call render of components. Geo render cost a lot.
        // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);
        renderSeries(ecIns, ecModel, api, payload, seriesDirtyMap);

        performPostUpdateFuncs(ecModel, this._api);
    },

    /**
     * @param {Object} payload
     * @private
     */
    updateView: function (payload) {
        var ecModel = this._model;

        // update before setOption
        if (!ecModel) {
            return;
        }

        Chart.markUpdateMethod(payload, 'updateView');

        clearColorPalette(ecModel);

        // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
        this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true});

        render(this, this._model, this._api, payload);

        performPostUpdateFuncs(ecModel, this._api);
    },

    /**
     * @param {Object} payload
     * @private
     */
    updateVisual: function (payload) {
        updateMethods.update.call(this, payload);

        // var ecModel = this._model;

        // // update before setOption
        // if (!ecModel) {
        //     return;
        // }

        // ChartView.markUpdateMethod(payload, 'updateVisual');

        // clearColorPalette(ecModel);

        // // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
        // this._scheduler.performVisualTasks(ecModel, payload, {visualType: 'visual', setDirty: true});

        // render(this, this._model, this._api, payload);

        // performPostUpdateFuncs(ecModel, this._api);
    },

    /**
     * @param {Object} payload
     * @private
     */
    updateLayout: function (payload) {
        updateMethods.update.call(this, payload);

        // var ecModel = this._model;

        // // update before setOption
        // if (!ecModel) {
        //     return;
        // }

        // ChartView.markUpdateMethod(payload, 'updateLayout');

        // // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
        // // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
        // this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true});

        // render(this, this._model, this._api, payload);

        // performPostUpdateFuncs(ecModel, this._api);
    }
};

function prepare(ecIns) {
    var ecModel = ecIns._model;
    var scheduler = ecIns._scheduler;

    scheduler.restorePipelines(ecModel);

    scheduler.prepareStageTasks();

    prepareView(ecIns, 'component', ecModel, scheduler);

    prepareView(ecIns, 'chart', ecModel, scheduler);

    scheduler.plan();
}

/**
 * @private
 */
function updateDirectly(ecIns, method, payload, mainType, subType) {
    var ecModel = ecIns._model;

    // broadcast
    if (!mainType) {
        // FIXME
        // Chart will not be update directly here, except set dirty.
        // But there is no such scenario now.
        each(ecIns._componentsViews.concat(ecIns._chartsViews), callView);
        return;
    }

    var query = {};
    query[mainType + 'Id'] = payload[mainType + 'Id'];
    query[mainType + 'Index'] = payload[mainType + 'Index'];
    query[mainType + 'Name'] = payload[mainType + 'Name'];

    var condition = {mainType: mainType, query: query};
    subType && (condition.subType = subType); // subType may be '' by parseClassType;

    var excludeSeriesId = payload.excludeSeriesId;
    if (excludeSeriesId != null) {
        excludeSeriesId = createHashMap(normalizeToArray(excludeSeriesId));
    }

    // If dispatchAction before setOption, do nothing.
    ecModel && ecModel.eachComponent(condition, function (model) {
        if (!excludeSeriesId || excludeSeriesId.get(model.id) == null) {
            callView(ecIns[
                mainType === 'series' ? '_chartsMap' : '_componentsMap'
            ][model.__viewId]);
        }
    }, ecIns);

    function callView(view) {
        view && view.__alive && view[method] && view[method](
            view.__model, ecModel, ecIns._api, payload
        );
    }
}

/**
 * Resize the chart
 * @param {Object} opts
 * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
 * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
 * @param {boolean} [opts.silent=false]
 */
echartsProto.resize = function (opts) {
    if (__DEV__) {
        assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.');
    }
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    this._zr.resize(opts);

    var ecModel = this._model;

    // Resize loading effect
    this._loadingFX && this._loadingFX.resize();

    if (!ecModel) {
        return;
    }

    var optionChanged = ecModel.resetOption('media');

    var silent = opts && opts.silent;

    this[IN_MAIN_PROCESS] = true;

    optionChanged && prepare(this);
    updateMethods.update.call(this);

    this[IN_MAIN_PROCESS] = false;

    flushPendingActions.call(this, silent);

    triggerUpdatedEvent.call(this, silent);
};

function updateStreamModes(ecIns, ecModel) {
    var chartsMap = ecIns._chartsMap;
    var scheduler = ecIns._scheduler;
    ecModel.eachSeries(function (seriesModel) {
        scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
    });
}

/**
 * Show loading effect
 * @param  {string} [name='default']
 * @param  {Object} [cfg]
 */
echartsProto.showLoading = function (name, cfg) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    if (isObject(name)) {
        cfg = name;
        name = '';
    }
    name = name || 'default';

    this.hideLoading();
    if (!loadingEffects[name]) {
        if (__DEV__) {
            console.warn('Loading effects ' + name + ' not exists.');
        }
        return;
    }
    var el = loadingEffects[name](this._api, cfg);
    var zr = this._zr;
    this._loadingFX = el;

    zr.add(el);
};

/**
 * Hide loading effect
 */
echartsProto.hideLoading = function () {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    this._loadingFX && this._zr.remove(this._loadingFX);
    this._loadingFX = null;
};

/**
 * @param {Object} eventObj
 * @return {Object}
 */
echartsProto.makeActionFromEvent = function (eventObj) {
    var payload = extend({}, eventObj);
    payload.type = eventActionMap[eventObj.type];
    return payload;
};

/**
 * @pubilc
 * @param {Object} payload
 * @param {string} [payload.type] Action type
 * @param {Object|boolean} [opt] If pass boolean, means opt.silent
 * @param {boolean} [opt.silent=false] Whether trigger events.
 * @param {boolean} [opt.flush=undefined]
 *                  true: Flush immediately, and then pixel in canvas can be fetched
 *                      immediately. Caution: it might affect performance.
 *                  false: Not flush.
 *                  undefined: Auto decide whether perform flush.
 */
echartsProto.dispatchAction = function (payload, opt) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    if (!isObject(opt)) {
        opt = {silent: !!opt};
    }

    if (!actions[payload.type]) {
        return;
    }

    // Avoid dispatch action before setOption. Especially in `connect`.
    if (!this._model) {
        return;
    }

    // May dispatchAction in rendering procedure
    if (this[IN_MAIN_PROCESS]) {
        this._pendingActions.push(payload);
        return;
    }

    doDispatchAction.call(this, payload, opt.silent);

    if (opt.flush) {
        this._zr.flush(true);
    }
    else if (opt.flush !== false && env$1.browser.weChat) {
        // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
        // hang when sliding page (on touch event), which cause that zr does not
        // refresh util user interaction finished, which is not expected.
        // But `dispatchAction` may be called too frequently when pan on touch
        // screen, which impacts performance if do not throttle them.
        this._throttledZrFlush();
    }

    flushPendingActions.call(this, opt.silent);

    triggerUpdatedEvent.call(this, opt.silent);
};

function doDispatchAction(payload, silent) {
    var payloadType = payload.type;
    var escapeConnect = payload.escapeConnect;
    var actionWrap = actions[payloadType];
    var actionInfo = actionWrap.actionInfo;

    var cptType = (actionInfo.update || 'update').split(':');
    var updateMethod = cptType.pop();
    cptType = cptType[0] != null && parseClassType(cptType[0]);

    this[IN_MAIN_PROCESS] = true;

    var payloads = [payload];
    var batched = false;
    // Batch action
    if (payload.batch) {
        batched = true;
        payloads = map(payload.batch, function (item) {
            item = defaults(extend({}, item), payload);
            item.batch = null;
            return item;
        });
    }

    var eventObjBatch = [];
    var eventObj;
    var isHighDown = payloadType === 'highlight' || payloadType === 'downplay';

    each(payloads, function (batchItem) {
        // Action can specify the event by return it.
        eventObj = actionWrap.action(batchItem, this._model, this._api);
        // Emit event outside
        eventObj = eventObj || extend({}, batchItem);
        // Convert type to eventType
        eventObj.type = actionInfo.event || eventObj.type;
        eventObjBatch.push(eventObj);

        // light update does not perform data process, layout and visual.
        if (isHighDown) {
            // method, payload, mainType, subType
            updateDirectly(this, updateMethod, batchItem, 'series');
        }
        else if (cptType) {
            updateDirectly(this, updateMethod, batchItem, cptType.main, cptType.sub);
        }
    }, this);

    if (updateMethod !== 'none' && !isHighDown && !cptType) {
        // Still dirty
        if (this[OPTION_UPDATED]) {
            // FIXME Pass payload ?
            prepare(this);
            updateMethods.update.call(this, payload);
            this[OPTION_UPDATED] = false;
        }
        else {
            updateMethods[updateMethod].call(this, payload);
        }
    }

    // Follow the rule of action batch
    if (batched) {
        eventObj = {
            type: actionInfo.event || payloadType,
            escapeConnect: escapeConnect,
            batch: eventObjBatch
        };
    }
    else {
        eventObj = eventObjBatch[0];
    }

    this[IN_MAIN_PROCESS] = false;

    !silent && this._messageCenter.trigger(eventObj.type, eventObj);
}

function flushPendingActions(silent) {
    var pendingActions = this._pendingActions;
    while (pendingActions.length) {
        var payload = pendingActions.shift();
        doDispatchAction.call(this, payload, silent);
    }
}

function triggerUpdatedEvent(silent) {
    !silent && this.trigger('updated');
}

/**
 * Event `rendered` is triggered when zr
 * rendered. It is useful for realtime
 * snapshot (reflect animation).
 *
 * Event `finished` is triggered when:
 * (1) zrender rendering finished.
 * (2) initial animation finished.
 * (3) progressive rendering finished.
 * (4) no pending action.
 * (5) no delayed setOption needs to be processed.
 */
function bindRenderedEvent(zr, ecIns) {
    zr.on('rendered', function () {

        ecIns.trigger('rendered');

        // The `finished` event should not be triggered repeatly,
        // so it should only be triggered when rendering indeed happend
        // in zrender. (Consider the case that dipatchAction is keep
        // triggering when mouse move).
        if (
            // Although zr is dirty if initial animation is not finished
            // and this checking is called on frame, we also check
            // animation finished for robustness.
            zr.animation.isFinished()
            && !ecIns[OPTION_UPDATED]
            && !ecIns._scheduler.unfinished
            && !ecIns._pendingActions.length
        ) {
            ecIns.trigger('finished');
        }
    });
}

/**
 * @param {Object} params
 * @param {number} params.seriesIndex
 * @param {Array|TypedArray} params.data
 */
echartsProto.appendData = function (params) {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }

    var seriesIndex = params.seriesIndex;
    var ecModel = this.getModel();
    var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

    if (__DEV__) {
        assert(params.data && seriesModel);
    }

    seriesModel.appendData(params);

    // Note: `appendData` does not support that update extent of coordinate
    // system, util some scenario require that. In the expected usage of
    // `appendData`, the initial extent of coordinate system should better
    // be fixed by axis `min`/`max` setting or initial data, otherwise if
    // the extent changed while `appendData`, the location of the painted
    // graphic elements have to be changed, which make the usage of
    // `appendData` meaningless.

    this._scheduler.unfinished = true;
};

/**
 * Register event
 * @method
 */
echartsProto.on = createRegisterEventWithLowercaseName('on', false);
echartsProto.off = createRegisterEventWithLowercaseName('off', false);
echartsProto.one = createRegisterEventWithLowercaseName('one', false);

/**
 * Prepare view instances of charts and components
 * @param  {module:echarts/model/Global} ecModel
 * @private
 */
function prepareView(ecIns, type, ecModel, scheduler) {
    var isComponent = type === 'component';
    var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
    var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
    var zr = ecIns._zr;
    var api = ecIns._api;

    for (var i = 0; i < viewList.length; i++) {
        viewList[i].__alive = false;
    }

    isComponent
        ? ecModel.eachComponent(function (componentType, model) {
            componentType !== 'series' && doPrepare(model);
        })
        : ecModel.eachSeries(doPrepare);

    function doPrepare(model) {
        // Consider: id same and type changed.
        var viewId = '_ec_' + model.id + '_' + model.type;
        var view = viewMap[viewId];
        if (!view) {
            var classType = parseClassType(model.type);
            var Clazz = isComponent
                ? Component$1.getClass(classType.main, classType.sub)
                : Chart.getClass(classType.sub);

            if (__DEV__) {
                assert(Clazz, classType.sub + ' does not exist.');
            }

            view = new Clazz();
            view.init(ecModel, api);
            viewMap[viewId] = view;
            viewList.push(view);
            zr.add(view.group);
        }

        model.__viewId = view.__id = viewId;
        view.__alive = true;
        view.__model = model;
        view.group.__ecComponentInfo = {
            mainType: model.mainType,
            index: model.componentIndex
        };
        !isComponent && scheduler.prepareView(view, model, ecModel, api);
    }

    for (var i = 0; i < viewList.length;) {
        var view = viewList[i];
        if (!view.__alive) {
            !isComponent && view.renderTask.dispose();
            zr.remove(view.group);
            view.dispose(ecModel, api);
            viewList.splice(i, 1);
            delete viewMap[view.__id];
            view.__id = view.group.__ecComponentInfo = null;
        }
        else {
            i++;
        }
    }
}

// /**
//  * Encode visual infomation from data after data processing
//  *
//  * @param {module:echarts/model/Global} ecModel
//  * @param {object} layout
//  * @param {boolean} [layoutFilter] `true`: only layout,
//  *                                 `false`: only not layout,
//  *                                 `null`/`undefined`: all.
//  * @param {string} taskBaseTag
//  * @private
//  */
// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {
//     each(visualFuncs, function (visual, index) {
//         var isLayout = visual.isLayout;
//         if (layoutFilter == null
//             || (layoutFilter === false && !isLayout)
//             || (layoutFilter === true && isLayout)
//         ) {
//             visual.func(ecModel, api, payload);
//         }
//     });
// }

function clearColorPalette(ecModel) {
    ecModel.clearColorPalette();
    ecModel.eachSeries(function (seriesModel) {
        seriesModel.clearColorPalette();
    });
}

function render(ecIns, ecModel, api, payload) {

    renderComponents(ecIns, ecModel, api, payload);

    each(ecIns._chartsViews, function (chart) {
        chart.__alive = false;
    });

    renderSeries(ecIns, ecModel, api, payload);

    // Remove groups of unrendered charts
    each(ecIns._chartsViews, function (chart) {
        if (!chart.__alive) {
            chart.remove(ecModel, api);
        }
    });
}

function renderComponents(ecIns, ecModel, api, payload, dirtyList) {
    each(dirtyList || ecIns._componentsViews, function (componentView) {
        var componentModel = componentView.__model;
        componentView.render(componentModel, ecModel, api, payload);

        updateZ(componentModel, componentView);
    });
}

/**
 * Render each chart and component
 * @private
 */
function renderSeries(ecIns, ecModel, api, payload, dirtyMap) {
    // Render all charts
    var scheduler = ecIns._scheduler;
    var unfinished;
    ecModel.eachSeries(function (seriesModel) {
        var chartView = ecIns._chartsMap[seriesModel.__viewId];
        chartView.__alive = true;

        var renderTask = chartView.renderTask;
        scheduler.updatePayload(renderTask, payload);

        if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
            renderTask.dirty();
        }

        unfinished |= renderTask.perform(scheduler.getPerformArgs(renderTask));

        chartView.group.silent = !!seriesModel.get('silent');

        updateZ(seriesModel, chartView);

        updateBlend(seriesModel, chartView);
    });
    scheduler.unfinished |= unfinished;

    // If use hover layer
    updateHoverLayerStatus(ecIns, ecModel);

    // Add aria
    aria(ecIns._zr.dom, ecModel);
}

function performPostUpdateFuncs(ecModel, api) {
    each(postUpdateFuncs, function (func) {
        func(ecModel, api);
    });
}


var MOUSE_EVENT_NAMES = [
    'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove',
    'mousedown', 'mouseup', 'globalout', 'contextmenu'
];

/**
 * @private
 */
echartsProto._initEvents = function () {
    each(MOUSE_EVENT_NAMES, function (eveName) {
        var handler = function (e) {
            var ecModel = this.getModel();
            var el = e.target;
            var params;
            var isGlobalOut = eveName === 'globalout';

            // no e.target when 'globalout'.
            if (isGlobalOut) {
                params = {};
            }
            else if (el && el.dataIndex != null) {
                var dataModel = el.dataModel || ecModel.getSeriesByIndex(el.seriesIndex);
                params = dataModel && dataModel.getDataParams(el.dataIndex, el.dataType, el) || {};
            }
            // If element has custom eventData of components
            else if (el && el.eventData) {
                params = extend({}, el.eventData);
            }

            // Contract: if params prepared in mouse event,
            // these properties must be specified:
            // {
            //    componentType: string (component main type)
            //    componentIndex: number
            // }
            // Otherwise event query can not work.

            if (params) {
                var componentType = params.componentType;
                var componentIndex = params.componentIndex;
                // Special handling for historic reason: when trigger by
                // markLine/markPoint/markArea, the componentType is
                // 'markLine'/'markPoint'/'markArea', but we should better
                // enable them to be queried by seriesIndex, since their
                // option is set in each series.
                if (componentType === 'markLine'
                    || componentType === 'markPoint'
                    || componentType === 'markArea'
                ) {
                    componentType = 'series';
                    componentIndex = params.seriesIndex;
                }
                var model = componentType && componentIndex != null
                    && ecModel.getComponent(componentType, componentIndex);
                var view = model && this[
                    model.mainType === 'series' ? '_chartsMap' : '_componentsMap'
                ][model.__viewId];

                if (__DEV__) {
                    // `event.componentType` and `event[componentTpype + 'Index']` must not
                    // be missed, otherwise there is no way to distinguish source component.
                    // See `dataFormat.getDataParams`.
                    if (!isGlobalOut && !(model && view)) {
                        console.warn('model or view can not be found by params');
                    }
                }

                params.event = e;
                params.type = eveName;

                this._ecEventProcessor.eventInfo = {
                    targetEl: el,
                    packedEvent: params,
                    model: model,
                    view: view
                };

                this.trigger(eveName, params);
            }
        };
        // Consider that some component (like tooltip, brush, ...)
        // register zr event handler, but user event handler might
        // do anything, such as call `setOption` or `dispatchAction`,
        // which probably update any of the content and probably
        // cause problem if it is called previous other inner handlers.
        handler.zrEventfulCallAtLast = true;
        this._zr.on(eveName, handler, this);
    }, this);

    each(eventActionMap, function (actionType, eventType) {
        this._messageCenter.on(eventType, function (event) {
            this.trigger(eventType, event);
        }, this);
    }, this);
};

/**
 * @return {boolean}
 */
echartsProto.isDisposed = function () {
    return this._disposed;
};

/**
 * Clear
 */
echartsProto.clear = function () {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }
    this.setOption({ series: [] }, true);
};

/**
 * Dispose instance
 */
echartsProto.dispose = function () {
    if (this._disposed) {
        disposedWarning(this.id);
        return;
    }
    this._disposed = true;

    setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');

    var api = this._api;
    var ecModel = this._model;

    each(this._componentsViews, function (component) {
        component.dispose(ecModel, api);
    });
    each(this._chartsViews, function (chart) {
        chart.dispose(ecModel, api);
    });

    // Dispose after all views disposed
    this._zr.dispose();

    delete instances[this.id];
};

mixin(ECharts, Eventful);

function disposedWarning(id) {
    if (__DEV__) {
        console.warn('Instance ' + id + ' has been disposed');
    }
}

function updateHoverLayerStatus(ecIns, ecModel) {
    var zr = ecIns._zr;
    var storage = zr.storage;
    var elCount = 0;

    storage.traverse(function (el) {
        elCount++;
    });

    if (elCount > ecModel.get('hoverLayerThreshold') && !env$1.node) {
        ecModel.eachSeries(function (seriesModel) {
            if (seriesModel.preventUsingHoverLayer) {
                return;
            }
            var chartView = ecIns._chartsMap[seriesModel.__viewId];
            if (chartView.__alive) {
                chartView.group.traverse(function (el) {
                    // Don't switch back.
                    el.useHoverLayer = true;
                });
            }
        });
    }
}

/**
 * Update chart progressive and blend.
 * @param {module:echarts/model/Series|module:echarts/model/Component} model
 * @param {module:echarts/view/Component|module:echarts/view/Chart} view
 */
function updateBlend(seriesModel, chartView) {
    var blendMode = seriesModel.get('blendMode') || null;
    if (__DEV__) {
        if (!env$1.canvasSupported && blendMode && blendMode !== 'source-over') {
            console.warn('Only canvas support blendMode');
        }
    }
    chartView.group.traverse(function (el) {
        // FIXME marker and other components
        if (!el.isGroup) {
            // Only set if blendMode is changed. In case element is incremental and don't wan't to rerender.
            if (el.style.blend !== blendMode) {
                el.setStyle('blend', blendMode);
            }
        }
        if (el.eachPendingDisplayable) {
            el.eachPendingDisplayable(function (displayable) {
                displayable.setStyle('blend', blendMode);
            });
        }
    });
}

/**
 * @param {module:echarts/model/Series|module:echarts/model/Component} model
 * @param {module:echarts/view/Component|module:echarts/view/Chart} view
 */
function updateZ(model, view) {
    var z = model.get('z');
    var zlevel = model.get('zlevel');
    // Set z and zlevel
    view.group.traverse(function (el) {
        if (el.type !== 'group') {
            z != null && (el.z = z);
            zlevel != null && (el.zlevel = zlevel);
        }
    });
}

function createExtensionAPI(ecInstance) {
    var coordSysMgr = ecInstance._coordSysMgr;
    return extend(new ExtensionAPI(ecInstance), {
        // Inject methods
        getCoordinateSystems: bind(
            coordSysMgr.getCoordinateSystems, coordSysMgr
        ),
        getComponentByElement: function (el) {
            while (el) {
                var modelInfo = el.__ecComponentInfo;
                if (modelInfo != null) {
                    return ecInstance._model.getComponent(modelInfo.mainType, modelInfo.index);
                }
                el = el.parent;
            }
        }
    });
}


/**
 * @class
 * Usage of query:
 * `chart.on('click', query, handler);`
 * The `query` can be:
 * + The component type query string, only `mainType` or `mainType.subType`,
 *   like: 'xAxis', 'series', 'xAxis.category' or 'series.line'.
 * + The component query object, like:
 *   `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`,
 *   `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`.
 * + The data query object, like:
 *   `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`.
 * + The other query object (cmponent customized query), like:
 *   `{element: 'some'}` (only available in custom series).
 *
 * Caveat: If a prop in the `query` object is `null/undefined`, it is the
 * same as there is no such prop in the `query` object.
 */
function EventProcessor() {
    // These info required: targetEl, packedEvent, model, view
    this.eventInfo;
}
EventProcessor.prototype = {
    constructor: EventProcessor,

    normalizeQuery: function (query) {
        var cptQuery = {};
        var dataQuery = {};
        var otherQuery = {};

        // `query` is `mainType` or `mainType.subType` of component.
        if (isString(query)) {
            var condCptType = parseClassType(query);
            // `.main` and `.sub` may be ''.
            cptQuery.mainType = condCptType.main || null;
            cptQuery.subType = condCptType.sub || null;
        }
        // `query` is an object, convert to {mainType, index, name, id}.
        else {
            // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved,
            // can not be used in `compomentModel.filterForExposedEvent`.
            var suffixes = ['Index', 'Name', 'Id'];
            var dataKeys = {name: 1, dataIndex: 1, dataType: 1};
            each$1(query, function (val, key) {
                var reserved = false;
                for (var i = 0; i < suffixes.length; i++) {
                    var propSuffix = suffixes[i];
                    var suffixPos = key.lastIndexOf(propSuffix);
                    if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) {
                        var mainType = key.slice(0, suffixPos);
                        // Consider `dataIndex`.
                        if (mainType !== 'data') {
                            cptQuery.mainType = mainType;
                            cptQuery[propSuffix.toLowerCase()] = val;
                            reserved = true;
                        }
                    }
                }
                if (dataKeys.hasOwnProperty(key)) {
                    dataQuery[key] = val;
                    reserved = true;
                }
                if (!reserved) {
                    otherQuery[key] = val;
                }
            });
        }

        return {
            cptQuery: cptQuery,
            dataQuery: dataQuery,
            otherQuery: otherQuery
        };
    },

    filter: function (eventType, query, args) {
        // They should be assigned before each trigger call.
        var eventInfo = this.eventInfo;

        if (!eventInfo) {
            return true;
        }

        var targetEl = eventInfo.targetEl;
        var packedEvent = eventInfo.packedEvent;
        var model = eventInfo.model;
        var view = eventInfo.view;

        // For event like 'globalout'.
        if (!model || !view) {
            return true;
        }

        var cptQuery = query.cptQuery;
        var dataQuery = query.dataQuery;

        return check(cptQuery, model, 'mainType')
            && check(cptQuery, model, 'subType')
            && check(cptQuery, model, 'index', 'componentIndex')
            && check(cptQuery, model, 'name')
            && check(cptQuery, model, 'id')
            && check(dataQuery, packedEvent, 'name')
            && check(dataQuery, packedEvent, 'dataIndex')
            && check(dataQuery, packedEvent, 'dataType')
            && (!view.filterForExposedEvent || view.filterForExposedEvent(
                eventType, query.otherQuery, targetEl, packedEvent
            ));

        function check(query, host, prop, propOnHost) {
            return query[prop] == null || host[propOnHost || prop] === query[prop];
        }
    },

    afterTrigger: function () {
        // Make sure the eventInfo wont be used in next trigger.
        this.eventInfo = null;
    }
};


/**
 * @type {Object} key: actionType.
 * @inner
 */
var actions = {};

/**
 * Map eventType to actionType
 * @type {Object}
 */
var eventActionMap = {};

/**
 * Data processor functions of each stage
 * @type {Array.<Object.<string, Function>>}
 * @inner
 */
var dataProcessorFuncs = [];

/**
 * @type {Array.<Function>}
 * @inner
 */
var optionPreprocessorFuncs = [];

/**
 * @type {Array.<Function>}
 * @inner
 */
var postUpdateFuncs = [];

/**
 * Visual encoding functions of each stage
 * @type {Array.<Object.<string, Function>>}
 */
var visualFuncs = [];

/**
 * Theme storage
 * @type {Object.<key, Object>}
 */
var themeStorage = {};
/**
 * Loading effects
 */
var loadingEffects = {};

var instances = {};
var connectedGroups = {};

var idBase = new Date() - 0;
var groupIdBase = new Date() - 0;
var DOM_ATTRIBUTE_KEY = '_echarts_instance_';

function enableConnect(chart) {
    var STATUS_PENDING = 0;
    var STATUS_UPDATING = 1;
    var STATUS_UPDATED = 2;
    var STATUS_KEY = '__connectUpdateStatus';

    function updateConnectedChartsStatus(charts, status) {
        for (var i = 0; i < charts.length; i++) {
            var otherChart = charts[i];
            otherChart[STATUS_KEY] = status;
        }
    }

    each(eventActionMap, function (actionType, eventType) {
        chart._messageCenter.on(eventType, function (event) {
            if (connectedGroups[chart.group] && chart[STATUS_KEY] !== STATUS_PENDING) {
                if (event && event.escapeConnect) {
                    return;
                }

                var action = chart.makeActionFromEvent(event);
                var otherCharts = [];

                each(instances, function (otherChart) {
                    if (otherChart !== chart && otherChart.group === chart.group) {
                        otherCharts.push(otherChart);
                    }
                });

                updateConnectedChartsStatus(otherCharts, STATUS_PENDING);
                each(otherCharts, function (otherChart) {
                    if (otherChart[STATUS_KEY] !== STATUS_UPDATING) {
                        otherChart.dispatchAction(action);
                    }
                });
                updateConnectedChartsStatus(otherCharts, STATUS_UPDATED);
            }
        });
    });
}

/**
 * @param {HTMLElement} dom
 * @param {Object} [theme]
 * @param {Object} opts
 * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default
 * @param {string} [opts.renderer] Can choose 'canvas' or 'svg' to render the chart.
 * @param {number} [opts.width] Use clientWidth of the input `dom` by default.
 *                              Can be 'auto' (the same as null/undefined)
 * @param {number} [opts.height] Use clientHeight of the input `dom` by default.
 *                               Can be 'auto' (the same as null/undefined)
 */
function init(dom, theme$$1, opts) {
    if (__DEV__) {
        // Check version
        if ((version$1.replace('.', '') - 0) < (dependencies.zrender.replace('.', '') - 0)) {
            throw new Error(
                'zrender/src ' + version$1
                + ' is too old for ECharts ' + version
                + '. Current version need ZRender '
                + dependencies.zrender + '+'
            );
        }

        if (!dom) {
            throw new Error('Initialize failed: invalid dom.');
        }
    }

    var existInstance = getInstanceByDom(dom);
    if (existInstance) {
        if (__DEV__) {
            console.warn('There is a chart instance already initialized on the dom.');
        }
        return existInstance;
    }

    if (__DEV__) {
        if (isDom(dom)
            && dom.nodeName.toUpperCase() !== 'CANVAS'
            && (
                (!dom.clientWidth && (!opts || opts.width == null))
                || (!dom.clientHeight && (!opts || opts.height == null))
            )
        ) {
            console.warn('Can\'t get DOM width or height. Please check '
            + 'dom.clientWidth and dom.clientHeight. They should not be 0.'
            + 'For example, you may need to call this in the callback '
            + 'of window.onload.');
        }
    }

    var chart = new ECharts(dom, theme$$1, opts);
    chart.id = 'ec_' + idBase++;
    instances[chart.id] = chart;

    setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);

    enableConnect(chart);

    return chart;
}

/**
 * @return {string|Array.<module:echarts~ECharts>} groupId
 */
function connect(groupId) {
    // Is array of charts
    if (isArray(groupId)) {
        var charts = groupId;
        groupId = null;
        // If any chart has group
        each(charts, function (chart) {
            if (chart.group != null) {
                groupId = chart.group;
            }
        });
        groupId = groupId || ('g_' + groupIdBase++);
        each(charts, function (chart) {
            chart.group = groupId;
        });
    }
    connectedGroups[groupId] = true;
    return groupId;
}

/**
 * @DEPRECATED
 * @return {string} groupId
 */
function disConnect(groupId) {
    connectedGroups[groupId] = false;
}

/**
 * @return {string} groupId
 */
var disconnect = disConnect;

/**
 * Dispose a chart instance
 * @param  {module:echarts~ECharts|HTMLDomElement|string} chart
 */
function dispose(chart) {
    if (typeof chart === 'string') {
        chart = instances[chart];
    }
    else if (!(chart instanceof ECharts)) {
        // Try to treat as dom
        chart = getInstanceByDom(chart);
    }
    if ((chart instanceof ECharts) && !chart.isDisposed()) {
        chart.dispose();
    }
}

/**
 * @param  {HTMLElement} dom
 * @return {echarts~ECharts}
 */
function getInstanceByDom(dom) {
    return instances[getAttribute(dom, DOM_ATTRIBUTE_KEY)];
}

/**
 * @param {string} key
 * @return {echarts~ECharts}
 */
function getInstanceById(key) {
    return instances[key];
}

/**
 * Register theme
 */
function registerTheme(name, theme$$1) {
    themeStorage[name] = theme$$1;
}

/**
 * Register option preprocessor
 * @param {Function} preprocessorFunc
 */
function registerPreprocessor(preprocessorFunc) {
    optionPreprocessorFuncs.push(preprocessorFunc);
}

/**
 * @param {number} [priority=1000]
 * @param {Object|Function} processor
 */
function registerProcessor(priority, processor) {
    normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_FILTER);
}

/**
 * Register postUpdater
 * @param {Function} postUpdateFunc
 */
function registerPostUpdate(postUpdateFunc) {
    postUpdateFuncs.push(postUpdateFunc);
}

/**
 * Usage:
 * registerAction('someAction', 'someEvent', function () { ... });
 * registerAction('someAction', function () { ... });
 * registerAction(
 *     {type: 'someAction', event: 'someEvent', update: 'updateView'},
 *     function () { ... }
 * );
 *
 * @param {(string|Object)} actionInfo
 * @param {string} actionInfo.type
 * @param {string} [actionInfo.event]
 * @param {string} [actionInfo.update]
 * @param {string} [eventName]
 * @param {Function} action
 */
function registerAction(actionInfo, eventName, action) {
    if (typeof eventName === 'function') {
        action = eventName;
        eventName = '';
    }
    var actionType = isObject(actionInfo)
        ? actionInfo.type
        : ([actionInfo, actionInfo = {
            event: eventName
        }][0]);

    // Event name is all lowercase
    actionInfo.event = (actionInfo.event || actionType).toLowerCase();
    eventName = actionInfo.event;

    // Validate action type and event name.
    assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));

    if (!actions[actionType]) {
        actions[actionType] = {action: action, actionInfo: actionInfo};
    }
    eventActionMap[eventName] = actionType;
}

/**
 * @param {string} type
 * @param {*} CoordinateSystem
 */
function registerCoordinateSystem(type, CoordinateSystem$$1) {
    CoordinateSystemManager.register(type, CoordinateSystem$$1);
}

/**
 * Get dimensions of specified coordinate system.
 * @param {string} type
 * @return {Array.<string|Object>}
 */
function getCoordinateSystemDimensions(type) {
    var coordSysCreator = CoordinateSystemManager.get(type);
    if (coordSysCreator) {
        return coordSysCreator.getDimensionsInfo
                ? coordSysCreator.getDimensionsInfo()
                : coordSysCreator.dimensions.slice();
    }
}

/**
 * Layout is a special stage of visual encoding
 * Most visual encoding like color are common for different chart
 * But each chart has it's own layout algorithm
 *
 * @param {number} [priority=1000]
 * @param {Function} layoutTask
 */
function registerLayout(priority, layoutTask) {
    normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
}

/**
 * @param {number} [priority=3000]
 * @param {module:echarts/stream/Task} visualTask
 */
function registerVisual(priority, visualTask) {
    normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
}

/**
 * @param {Object|Function} fn: {seriesType, createOnAllSeries, performRawSeries, reset}
 */
function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
    if (isFunction(priority) || isObject(priority)) {
        fn = priority;
        priority = defaultPriority;
    }

    if (__DEV__) {
        if (isNaN(priority) || priority == null) {
            throw new Error('Illegal priority');
        }
        // Check duplicate
        each(targetList, function (wrap) {
            assert(wrap.__raw !== fn);
        });
    }

    var stageHandler = Scheduler.wrapStageHandler(fn, visualType);

    stageHandler.__prio = priority;
    stageHandler.__raw = fn;
    targetList.push(stageHandler);

    return stageHandler;
}

/**
 * @param {string} name
 */
function registerLoading(name, loadingFx) {
    loadingEffects[name] = loadingFx;
}

/**
 * @param {Object} opts
 * @param {string} [superClass]
 */
function extendComponentModel(opts/*, superClass*/) {
    // var Clazz = ComponentModel;
    // if (superClass) {
    //     var classType = parseClassType(superClass);
    //     Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
    // }
    return ComponentModel.extend(opts);
}

/**
 * @param {Object} opts
 * @param {string} [superClass]
 */
function extendComponentView(opts/*, superClass*/) {
    // var Clazz = ComponentView;
    // if (superClass) {
    //     var classType = parseClassType(superClass);
    //     Clazz = ComponentView.getClass(classType.main, classType.sub, true);
    // }
    return Component$1.extend(opts);
}

/**
 * @param {Object} opts
 * @param {string} [superClass]
 */
function extendSeriesModel(opts/*, superClass*/) {
    // var Clazz = SeriesModel;
    // if (superClass) {
    //     superClass = 'series.' + superClass.replace('series.', '');
    //     var classType = parseClassType(superClass);
    //     Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
    // }
    return SeriesModel.extend(opts);
}

/**
 * @param {Object} opts
 * @param {string} [superClass]
 */
function extendChartView(opts/*, superClass*/) {
    // var Clazz = ChartView;
    // if (superClass) {
    //     superClass = superClass.replace('series.', '');
    //     var classType = parseClassType(superClass);
    //     Clazz = ChartView.getClass(classType.main, true);
    // }
    return Chart.extend(opts);
}

/**
 * ZRender need a canvas context to do measureText.
 * But in node environment canvas may be created by node-canvas.
 * So we need to specify how to create a canvas instead of using document.createElement('canvas')
 *
 * Be careful of using it in the browser.
 *
 * @param {Function} creator
 * @example
 *     var Canvas = require('canvas');
 *     var echarts = require('echarts');
 *     echarts.setCanvasCreator(function () {
 *         // Small size is enough.
 *         return new Canvas(32, 32);
 *     });
 */
function setCanvasCreator(creator) {
    $override('createCanvas', creator);
}

/**
 * @param {string} mapName
 * @param {Array.<Object>|Object|string} geoJson
 * @param {Object} [specialAreas]
 *
 * @example GeoJSON
 *     $.get('USA.json', function (geoJson) {
 *         echarts.registerMap('USA', geoJson);
 *         // Or
 *         echarts.registerMap('USA', {
 *             geoJson: geoJson,
 *             specialAreas: {}
 *         })
 *     });
 *
 *     $.get('airport.svg', function (svg) {
 *         echarts.registerMap('airport', {
 *             svg: svg
 *         }
 *     });
 *
 *     echarts.registerMap('eu', [
 *         {svg: eu-topographic.svg},
 *         {geoJSON: eu.json}
 *     ])
 */
function registerMap(mapName, geoJson, specialAreas) {
    mapDataStorage.registerMap(mapName, geoJson, specialAreas);
}

/**
 * @param {string} mapName
 * @return {Object}
 */
function getMap(mapName) {
    // For backward compatibility, only return the first one.
    var records = mapDataStorage.retrieveMap(mapName);
    return records && records[0] && {
        geoJson: records[0].geoJSON,
        specialAreas: records[0].specialAreas
    };
}

registerVisual(PRIORITY_VISUAL_GLOBAL, seriesColor);
registerPreprocessor(backwardCompat);
registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
registerLoading('default', loadingDefault);

// Default actions

registerAction({
    type: 'highlight',
    event: 'highlight',
    update: 'highlight'
}, noop);

registerAction({
    type: 'downplay',
    event: 'downplay',
    update: 'downplay'
}, noop);

// Default theme
registerTheme('light', lightTheme);
registerTheme('dark', theme);

// For backward compatibility, where the namespace `dataTool` will
// be mounted on `echarts` is the extension `dataTool` is imported.
var dataTool = {};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


function defaultKeyGetter(item) {
    return item;
}

/**
 * @param {Array} oldArr
 * @param {Array} newArr
 * @param {Function} oldKeyGetter
 * @param {Function} newKeyGetter
 * @param {Object} [context] Can be visited by this.context in callback.
 */
function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context) {
    this._old = oldArr;
    this._new = newArr;

    this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;
    this._newKeyGetter = newKeyGetter || defaultKeyGetter;

    this.context = context;
}

DataDiffer.prototype = {

    constructor: DataDiffer,

    /**
     * Callback function when add a data
     */
    add: function (func) {
        this._add = func;
        return this;
    },

    /**
     * Callback function when update a data
     */
    update: function (func) {
        this._update = func;
        return this;
    },

    /**
     * Callback function when remove a data
     */
    remove: function (func) {
        this._remove = func;
        return this;
    },

    execute: function () {
        var oldArr = this._old;
        var newArr = this._new;

        var oldDataIndexMap = {};
        var newDataIndexMap = {};
        var oldDataKeyArr = [];
        var newDataKeyArr = [];
        var i;

        initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter', this);
        initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter', this);

        for (i = 0; i < oldArr.length; i++) {
            var key = oldDataKeyArr[i];
            var idx = newDataIndexMap[key];

            // idx can never be empty array here. see 'set null' logic below.
            if (idx != null) {
                // Consider there is duplicate key (for example, use dataItem.name as key).
                // We should make sure every item in newArr and oldArr can be visited.
                var len = idx.length;
                if (len) {
                    len === 1 && (newDataIndexMap[key] = null);
                    idx = idx.shift();
                }
                else {
                    newDataIndexMap[key] = null;
                }
                this._update && this._update(idx, i);
            }
            else {
                this._remove && this._remove(i);
            }
        }

        for (var i = 0; i < newDataKeyArr.length; i++) {
            var key = newDataKeyArr[i];
            if (newDataIndexMap.hasOwnProperty(key)) {
                var idx = newDataIndexMap[key];
                if (idx == null) {
                    continue;
                }
                // idx can never be empty array here. see 'set null' logic above.
                if (!idx.length) {
                    this._add && this._add(idx);
                }
                else {
                    for (var j = 0, len = idx.length; j < len; j++) {
                        this._add && this._add(idx[j]);
                    }
                }
            }
        }
    }
};

function initIndexMap(arr, map, keyArr, keyGetterName, dataDiffer) {
    for (var i = 0; i < arr.length; i++) {
        // Add prefix to avoid conflict with Object.prototype.
        var key = '_ec_' + dataDiffer[keyGetterName](arr[i], i);
        var existence = map[key];
        if (existence == null) {
            keyArr.push(key);
            map[key] = i;
        }
        else {
            if (!existence.length) {
                map[key] = existence = [existence];
            }
            existence.push(i);
        }
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var OTHER_DIMENSIONS = createHashMap([
    'tooltip', 'label', 'itemName', 'itemId', 'seriesName'
]);

function summarizeDimensions(data) {
    var summary = {};
    var encode = summary.encode = {};
    var notExtraCoordDimMap = createHashMap();
    var defaultedLabel = [];
    var defaultedTooltip = [];

    // See the comment of `List.js#userOutput`.
    var userOutput = summary.userOutput = {
        dimensionNames: data.dimensions.slice(),
        encode: {}
    };

    each$1(data.dimensions, function (dimName) {
        var dimItem = data.getDimensionInfo(dimName);

        var coordDim = dimItem.coordDim;
        if (coordDim) {
            if (__DEV__) {
                assert$1(OTHER_DIMENSIONS.get(coordDim) == null);
            }

            var coordDimIndex = dimItem.coordDimIndex;
            getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName;

            if (!dimItem.isExtraCoord) {
                notExtraCoordDimMap.set(coordDim, 1);

                // Use the last coord dim (and label friendly) as default label,
                // because when dataset is used, it is hard to guess which dimension
                // can be value dimension. If both show x, y on label is not look good,
                // and conventionally y axis is focused more.
                if (mayLabelDimType(dimItem.type)) {
                    defaultedLabel[0] = dimName;
                }

                // User output encode do not contain generated coords.
                // And it only has index. User can use index to retrieve value from the raw item array.
                getOrCreateEncodeArr(userOutput.encode, coordDim)[coordDimIndex] = dimItem.index;
            }
            if (dimItem.defaultTooltip) {
                defaultedTooltip.push(dimName);
            }
        }

        OTHER_DIMENSIONS.each(function (v, otherDim) {
            var encodeArr = getOrCreateEncodeArr(encode, otherDim);

            var dimIndex = dimItem.otherDims[otherDim];
            if (dimIndex != null && dimIndex !== false) {
                encodeArr[dimIndex] = dimItem.name;
            }
        });
    });

    var dataDimsOnCoord = [];
    var encodeFirstDimNotExtra = {};

    notExtraCoordDimMap.each(function (v, coordDim) {
        var dimArr = encode[coordDim];
        // ??? FIXME extra coord should not be set in dataDimsOnCoord.
        // But should fix the case that radar axes: simplify the logic
        // of `completeDimension`, remove `extraPrefix`.
        encodeFirstDimNotExtra[coordDim] = dimArr[0];
        // Not necessary to remove duplicate, because a data
        // dim canot on more than one coordDim.
        dataDimsOnCoord = dataDimsOnCoord.concat(dimArr);
    });

    summary.dataDimsOnCoord = dataDimsOnCoord;
    summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra;

    var encodeLabel = encode.label;
    // FIXME `encode.label` is not recommanded, because formatter can not be set
    // in this way. Use label.formatter instead. May be remove this approach someday.
    if (encodeLabel && encodeLabel.length) {
        defaultedLabel = encodeLabel.slice();
    }

    var encodeTooltip = encode.tooltip;
    if (encodeTooltip && encodeTooltip.length) {
        defaultedTooltip = encodeTooltip.slice();
    }
    else if (!defaultedTooltip.length) {
        defaultedTooltip = defaultedLabel.slice();
    }

    encode.defaultedLabel = defaultedLabel;
    encode.defaultedTooltip = defaultedTooltip;

    return summary;
}

function getOrCreateEncodeArr(encode, dim) {
    if (!encode.hasOwnProperty(dim)) {
        encode[dim] = [];
    }
    return encode[dim];
}

function getDimensionTypeByAxis(axisType) {
    return axisType === 'category'
        ? 'ordinal'
        : axisType === 'time'
        ? 'time'
        : 'float';
}

function mayLabelDimType(dimType) {
    // In most cases, ordinal and time do not suitable for label.
    // Ordinal info can be displayed on axis. Time is too long.
    return !(dimType === 'ordinal' || dimType === 'time');
}

// function findTheLastDimMayLabel(data) {
//     // Get last value dim
//     var dimensions = data.dimensions.slice();
//     var valueType;
//     var valueDim;
//     while (dimensions.length && (
//         valueDim = dimensions.pop(),
//         valueType = data.getDimensionInfo(valueDim).type,
//         valueType === 'ordinal' || valueType === 'time'
//     )) {} // jshint ignore:line
//     return valueDim;
// }

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float64Array, Int32Array, Uint32Array, Uint16Array */

/**
 * List for data storage
 * @module echarts/data/List
 */

var isObject$4 = isObject$1;

var UNDEFINED = 'undefined';
var INDEX_NOT_FOUND = -1;

// Use prefix to avoid index to be the same as otherIdList[idx],
// which will cause weird udpate animation.
var ID_PREFIX = 'e\0\0';

var dataCtors = {
    'float': typeof Float64Array === UNDEFINED
        ? Array : Float64Array,
    'int': typeof Int32Array === UNDEFINED
        ? Array : Int32Array,
    // Ordinal data type can be string or int
    'ordinal': Array,
    'number': Array,
    'time': Array
};

// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is
// different from the Ctor of typed array.
var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array;
var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;

function getIndicesCtor(list) {
    // The possible max value in this._indicies is always this._rawCount despite of filtering.
    return list._rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
}

function cloneChunk(originalChunk) {
    var Ctor = originalChunk.constructor;
    // Only shallow clone is enough when Array.
    return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk);
}

var TRANSFERABLE_PROPERTIES = [
    'hasItemOption', '_nameList', '_idList', '_invertedIndicesMap',
    '_rawData', '_chunkSize', '_chunkCount', '_dimValueGetter',
    '_count', '_rawCount', '_nameDimIdx', '_idDimIdx'
];
var CLONE_PROPERTIES = [
    '_extent', '_approximateExtent', '_rawExtent'
];

function transferProperties(target, source) {
    each$1(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) {
        if (source.hasOwnProperty(propName)) {
            target[propName] = source[propName];
        }
    });

    target.__wrappedMethods = source.__wrappedMethods;

    each$1(CLONE_PROPERTIES, function (propName) {
        target[propName] = clone(source[propName]);
    });

    target._calculationInfo = extend(source._calculationInfo);
}





/**
 * @constructor
 * @alias module:echarts/data/List
 *
 * @param {Array.<string|Object>} dimensions
 *      For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
 *      Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
 *      Spetial fields: {
 *          ordinalMeta: <module:echarts/data/OrdinalMeta>
 *          createInvertedIndices: <boolean>
 *      }
 * @param {module:echarts/model/Model} hostModel
 */
var List = function (dimensions, hostModel) {

    dimensions = dimensions || ['x', 'y'];

    var dimensionInfos = {};
    var dimensionNames = [];
    var invertedIndicesMap = {};

    for (var i = 0; i < dimensions.length; i++) {
        // Use the original dimensions[i], where other flag props may exists.
        var dimensionInfo = dimensions[i];

        if (isString(dimensionInfo)) {
            dimensionInfo = {name: dimensionInfo};
        }

        var dimensionName = dimensionInfo.name;
        dimensionInfo.type = dimensionInfo.type || 'float';
        if (!dimensionInfo.coordDim) {
            dimensionInfo.coordDim = dimensionName;
            dimensionInfo.coordDimIndex = 0;
        }

        dimensionInfo.otherDims = dimensionInfo.otherDims || {};
        dimensionNames.push(dimensionName);
        dimensionInfos[dimensionName] = dimensionInfo;

        dimensionInfo.index = i;

        if (dimensionInfo.createInvertedIndices) {
            invertedIndicesMap[dimensionName] = [];
        }
    }

    /**
     * @readOnly
     * @type {Array.<string>}
     */
    this.dimensions = dimensionNames;

    /**
     * Infomation of each data dimension, like data type.
     * @type {Object}
     */
    this._dimensionInfos = dimensionInfos;

    /**
     * @type {module:echarts/model/Model}
     */
    this.hostModel = hostModel;

    /**
     * @type {module:echarts/model/Model}
     */
    this.dataType;

    /**
     * Indices stores the indices of data subset after filtered.
     * This data subset will be used in chart.
     * @type {Array.<number>}
     * @readOnly
     */
    this._indices = null;

    this._count = 0;
    this._rawCount = 0;

    /**
     * Data storage
     * @type {Object.<key, Array.<TypedArray|Array>>}
     * @private
     */
    this._storage = {};

    /**
     * @type {Array.<string>}
     */
    this._nameList = [];
    /**
     * @type {Array.<string>}
     */
    this._idList = [];

    /**
     * Models of data option is stored sparse for optimizing memory cost
     * @type {Array.<module:echarts/model/Model>}
     * @private
     */
    this._optionModels = [];

    /**
     * Global visual properties after visual coding
     * @type {Object}
     * @private
     */
    this._visual = {};

    /**
     * Globel layout properties.
     * @type {Object}
     * @private
     */
    this._layout = {};

    /**
     * Item visual properties after visual coding
     * @type {Array.<Object>}
     * @private
     */
    this._itemVisuals = [];

    /**
     * Key: visual type, Value: boolean
     * @type {Object}
     * @readOnly
     */
    this.hasItemVisual = {};

    /**
     * Item layout properties after layout
     * @type {Array.<Object>}
     * @private
     */
    this._itemLayouts = [];

    /**
     * Graphic elemnents
     * @type {Array.<module:zrender/Element>}
     * @private
     */
    this._graphicEls = [];

    /**
     * Max size of each chunk.
     * @type {number}
     * @private
     */
    this._chunkSize = 1e5;

    /**
     * @type {number}
     * @private
     */
    this._chunkCount = 0;

    /**
     * @type {Array.<Array|Object>}
     * @private
     */
    this._rawData;

    /**
     * Raw extent will not be cloned, but only transfered.
     * It will not be calculated util needed.
     * key: dim,
     * value: {end: number, extent: Array.<number>}
     * @type {Object}
     * @private
     */
    this._rawExtent = {};

    /**
     * @type {Object}
     * @private
     */
    this._extent = {};

    /**
     * key: dim
     * value: extent
     * @type {Object}
     * @private
     */
    this._approximateExtent = {};

    /**
     * Cache summary info for fast visit. See "dimensionHelper".
     * @type {Object}
     * @private
     */
    this._dimensionsSummary = summarizeDimensions(this);

    /**
     * @type {Object.<Array|TypedArray>}
     * @private
     */
    this._invertedIndicesMap = invertedIndicesMap;

    /**
     * @type {Object}
     * @private
     */
    this._calculationInfo = {};

    /**
     * User output info of this data.
     * DO NOT use it in other places!
     *
     * When preparing user params for user callbacks, we have
     * to clone these inner data structures to prevent users
     * from modifying them to effect built-in logic. And for
     * performance consideration we make this `userOutput` to
     * avoid clone them too many times.
     *
     * @type {Object}
     * @readOnly
     */
    this.userOutput = this._dimensionsSummary.userOutput;
};

var listProto = List.prototype;

listProto.type = 'list';

/**
 * If each data item has it's own option
 * @type {boolean}
 */
listProto.hasItemOption = true;

/**
 * The meanings of the input parameter `dim`:
 *
 * + If dim is a number (e.g., `1`), it means the index of the dimension.
 *   For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.
 * + If dim is a number-like string (e.g., `"1"`):
 *     + If there is the same concrete dim name defined in `this.dimensions`, it means that concrete name.
 *     + If not, it will be converted to a number, which means the index of the dimension.
 *        (why? because of the backward compatbility. We have been tolerating number-like string in
 *        dimension setting, although now it seems that it is not a good idea.)
 *     For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`,
 *     if no dimension name is defined as `"1"`.
 * + If dim is a not-number-like string, it means the concrete dim name.
 *   For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`,
 *   or customized in `dimensions` property of option like `"age"`.
 *
 * Get dimension name
 * @param {string|number} dim See above.
 * @return {string} Concrete dim name.
 */
listProto.getDimension = function (dim) {
    if (typeof dim === 'number'
        // If being a number-like string but not being defined a dimension name.
        || (!isNaN(dim) && !this._dimensionInfos.hasOwnProperty(dim))
    ) {
        dim = this.dimensions[dim];
    }
    return dim;
};

/**
 * Get type and calculation info of particular dimension
 * @param {string|number} dim
 *        Dimension can be concrete names like x, y, z, lng, lat, angle, radius
 *        Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
 */
listProto.getDimensionInfo = function (dim) {
    // Do not clone, because there may be categories in dimInfo.
    return this._dimensionInfos[this.getDimension(dim)];
};

/**
 * @return {Array.<string>} concrete dimension name list on coord.
 */
listProto.getDimensionsOnCoord = function () {
    return this._dimensionsSummary.dataDimsOnCoord.slice();
};

/**
 * @param {string} coordDim
 * @param {number} [idx] A coordDim may map to more than one data dim.
 *        If idx is `true`, return a array of all mapped dims.
 *        If idx is not specified, return the first dim not extra.
 * @return {string|Array.<string>} concrete data dim.
 *        If idx is number, and not found, return null/undefined.
 *        If idx is `true`, and not found, return empty array (always return array).
 */
listProto.mapDimension = function (coordDim, idx) {
    var dimensionsSummary = this._dimensionsSummary;

    if (idx == null) {
        return dimensionsSummary.encodeFirstDimNotExtra[coordDim];
    }

    var dims = dimensionsSummary.encode[coordDim];
    return idx === true
        // always return array if idx is `true`
        ? (dims || []).slice()
        : (dims && dims[idx]);
};

/**
 * Initialize from data
 * @param {Array.<Object|number|Array>} data source or data or data provider.
 * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
 *        defualt label/tooltip.
 *        A name can be specified in encode.itemName,
 *        or dataItem.name (only for series option data),
 *        or provided in nameList from outside.
 * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number
 */
listProto.initData = function (data, nameList, dimValueGetter) {

    var notProvider = Source.isInstance(data) || isArrayLike(data);
    if (notProvider) {
        data = new DefaultDataProvider(data, this.dimensions.length);
    }

    if (__DEV__) {
        if (!notProvider && (typeof data.getItem !== 'function' || typeof data.count !== 'function')) {
            throw new Error('Inavlid data provider.');
        }
    }

    this._rawData = data;

    // Clear
    this._storage = {};
    this._indices = null;

    this._nameList = nameList || [];

    this._idList = [];

    this._nameRepeatCount = {};

    if (!dimValueGetter) {
        this.hasItemOption = false;
    }

    /**
     * @readOnly
     */
    this.defaultDimValueGetter = defaultDimValueGetters[
        this._rawData.getSource().sourceFormat
    ];
    // Default dim value getter
    this._dimValueGetter = dimValueGetter = dimValueGetter
        || this.defaultDimValueGetter;
    this._dimValueGetterArrayRows = defaultDimValueGetters.arrayRows;

    // Reset raw extent.
    this._rawExtent = {};

    this._initDataFromProvider(0, data.count());

    // If data has no item option.
    if (data.pure) {
        this.hasItemOption = false;
    }
};

listProto.getProvider = function () {
    return this._rawData;
};

/**
 * Caution: Can be only called on raw data (before `this._indices` created).
 */
listProto.appendData = function (data) {
    if (__DEV__) {
        assert$1(!this._indices, 'appendData can only be called on raw data.');
    }

    var rawData = this._rawData;
    var start = this.count();
    rawData.appendData(data);
    var end = rawData.count();
    if (!rawData.persistent) {
        end += start;
    }
    this._initDataFromProvider(start, end);
};

/**
 * Caution: Can be only called on raw data (before `this._indices` created).
 * This method does not modify `rawData` (`dataProvider`), but only
 * add values to storage.
 *
 * The final count will be increased by `Math.max(values.length, names.length)`.
 *
 * @param {Array.<Array.<*>>} values That is the SourceType: 'arrayRows', like
 *        [
 *            [12, 33, 44],
 *            [NaN, 43, 1],
 *            ['-', 'asdf', 0]
 *        ]
 *        Each item is exaclty cooresponding to a dimension.
 * @param {Array.<string>} [names]
 */
listProto.appendValues = function (values, names) {
    var chunkSize = this._chunkSize;
    var storage = this._storage;
    var dimensions = this.dimensions;
    var dimLen = dimensions.length;
    var rawExtent = this._rawExtent;

    var start = this.count();
    var end = start + Math.max(values.length, names ? names.length : 0);
    var originalChunkCount = this._chunkCount;

    for (var i = 0; i < dimLen; i++) {
        var dim = dimensions[i];
        if (!rawExtent[dim]) {
            rawExtent[dim] = getInitialExtent();
        }
        if (!storage[dim]) {
            storage[dim] = [];
        }
        prepareChunks(storage, this._dimensionInfos[dim], chunkSize, originalChunkCount, end);
        this._chunkCount = storage[dim].length;
    }

    var emptyDataItem = new Array(dimLen);
    for (var idx = start; idx < end; idx++) {
        var sourceIdx = idx - start;
        var chunkIndex = Math.floor(idx / chunkSize);
        var chunkOffset = idx % chunkSize;

        // Store the data by dimensions
        for (var k = 0; k < dimLen; k++) {
            var dim = dimensions[k];
            var val = this._dimValueGetterArrayRows(
                values[sourceIdx] || emptyDataItem, dim, sourceIdx, k
            );
            storage[dim][chunkIndex][chunkOffset] = val;

            var dimRawExtent = rawExtent[dim];
            val < dimRawExtent[0] && (dimRawExtent[0] = val);
            val > dimRawExtent[1] && (dimRawExtent[1] = val);
        }

        if (names) {
            this._nameList[idx] = names[sourceIdx];
        }
    }

    this._rawCount = this._count = end;

    // Reset data extent
    this._extent = {};

    prepareInvertedIndex(this);
};

listProto._initDataFromProvider = function (start, end) {
    // Optimize.
    if (start >= end) {
        return;
    }

    var chunkSize = this._chunkSize;
    var rawData = this._rawData;
    var storage = this._storage;
    var dimensions = this.dimensions;
    var dimLen = dimensions.length;
    var dimensionInfoMap = this._dimensionInfos;
    var nameList = this._nameList;
    var idList = this._idList;
    var rawExtent = this._rawExtent;
    var nameRepeatCount = this._nameRepeatCount = {};
    var nameDimIdx;

    var originalChunkCount = this._chunkCount;
    for (var i = 0; i < dimLen; i++) {
        var dim = dimensions[i];
        if (!rawExtent[dim]) {
            rawExtent[dim] = getInitialExtent();
        }

        var dimInfo = dimensionInfoMap[dim];
        if (dimInfo.otherDims.itemName === 0) {
            nameDimIdx = this._nameDimIdx = i;
        }
        if (dimInfo.otherDims.itemId === 0) {
            this._idDimIdx = i;
        }

        if (!storage[dim]) {
            storage[dim] = [];
        }

        prepareChunks(storage, dimInfo, chunkSize, originalChunkCount, end);

        this._chunkCount = storage[dim].length;
    }

    var dataItem = new Array(dimLen);
    for (var idx = start; idx < end; idx++) {
        // NOTICE: Try not to write things into dataItem
        dataItem = rawData.getItem(idx, dataItem);
        // Each data item is value
        // [1, 2]
        // 2
        // Bar chart, line chart which uses category axis
        // only gives the 'y' value. 'x' value is the indices of category
        // Use a tempValue to normalize the value to be a (x, y) value
        var chunkIndex = Math.floor(idx / chunkSize);
        var chunkOffset = idx % chunkSize;

        // Store the data by dimensions
        for (var k = 0; k < dimLen; k++) {
            var dim = dimensions[k];
            var dimStorage = storage[dim][chunkIndex];
            // PENDING NULL is empty or zero
            var val = this._dimValueGetter(dataItem, dim, idx, k);
            dimStorage[chunkOffset] = val;

            var dimRawExtent = rawExtent[dim];
            val < dimRawExtent[0] && (dimRawExtent[0] = val);
            val > dimRawExtent[1] && (dimRawExtent[1] = val);
        }

        // ??? FIXME not check by pure but sourceFormat?
        // TODO refactor these logic.
        if (!rawData.pure) {
            var name = nameList[idx];

            if (dataItem && name == null) {
                // If dataItem is {name: ...}, it has highest priority.
                // That is appropriate for many common cases.
                if (dataItem.name != null) {
                    // There is no other place to persistent dataItem.name,
                    // so save it to nameList.
                    nameList[idx] = name = dataItem.name;
                }
                else if (nameDimIdx != null) {
                    var nameDim = dimensions[nameDimIdx];
                    var nameDimChunk = storage[nameDim][chunkIndex];
                    if (nameDimChunk) {
                        name = nameDimChunk[chunkOffset];
                        var ordinalMeta = dimensionInfoMap[nameDim].ordinalMeta;
                        if (ordinalMeta && ordinalMeta.categories.length) {
                            name = ordinalMeta.categories[name];
                        }
                    }
                }
            }

            // Try using the id in option
            // id or name is used on dynamical data, mapping old and new items.
            var id = dataItem == null ? null : dataItem.id;

            if (id == null && name != null) {
                // Use name as id and add counter to avoid same name
                nameRepeatCount[name] = nameRepeatCount[name] || 0;
                id = name;
                if (nameRepeatCount[name] > 0) {
                    id += '__ec__' + nameRepeatCount[name];
                }
                nameRepeatCount[name]++;
            }
            id != null && (idList[idx] = id);
        }
    }

    if (!rawData.persistent && rawData.clean) {
        // Clean unused data if data source is typed array.
        rawData.clean();
    }

    this._rawCount = this._count = end;

    // Reset data extent
    this._extent = {};

    prepareInvertedIndex(this);
};

function prepareChunks(storage, dimInfo, chunkSize, chunkCount, end) {
    var DataCtor = dataCtors[dimInfo.type];
    var lastChunkIndex = chunkCount - 1;
    var dim = dimInfo.name;
    var resizeChunkArray = storage[dim][lastChunkIndex];
    if (resizeChunkArray && resizeChunkArray.length < chunkSize) {
        var newStore = new DataCtor(Math.min(end - lastChunkIndex * chunkSize, chunkSize));
        // The cost of the copy is probably inconsiderable
        // within the initial chunkSize.
        for (var j = 0; j < resizeChunkArray.length; j++) {
            newStore[j] = resizeChunkArray[j];
        }
        storage[dim][lastChunkIndex] = newStore;
    }

    // Create new chunks.
    for (var k = chunkCount * chunkSize; k < end; k += chunkSize) {
        storage[dim].push(new DataCtor(Math.min(end - k, chunkSize)));
    }
}

function prepareInvertedIndex(list) {
    var invertedIndicesMap = list._invertedIndicesMap;
    each$1(invertedIndicesMap, function (invertedIndices, dim) {
        var dimInfo = list._dimensionInfos[dim];

        // Currently, only dimensions that has ordinalMeta can create inverted indices.
        var ordinalMeta = dimInfo.ordinalMeta;
        if (ordinalMeta) {
            invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(
                ordinalMeta.categories.length
            );
            // The default value of TypedArray is 0. To avoid miss
            // mapping to 0, we should set it as INDEX_NOT_FOUND.
            for (var i = 0; i < invertedIndices.length; i++) {
                invertedIndices[i] = INDEX_NOT_FOUND;
            }
            for (var i = 0; i < list._count; i++) {
                // Only support the case that all values are distinct.
                invertedIndices[list.get(dim, i)] = i;
            }
        }
    });
}

function getRawValueFromStore(list, dimIndex, rawIndex) {
    var val;
    if (dimIndex != null) {
        var chunkSize = list._chunkSize;
        var chunkIndex = Math.floor(rawIndex / chunkSize);
        var chunkOffset = rawIndex % chunkSize;
        var dim = list.dimensions[dimIndex];
        var chunk = list._storage[dim][chunkIndex];
        if (chunk) {
            val = chunk[chunkOffset];
            var ordinalMeta = list._dimensionInfos[dim].ordinalMeta;
            if (ordinalMeta && ordinalMeta.categories.length) {
                val = ordinalMeta.categories[val];
            }
        }
    }
    return val;
}

/**
 * @return {number}
 */
listProto.count = function () {
    return this._count;
};

listProto.getIndices = function () {
    var newIndices;

    var indices = this._indices;
    if (indices) {
        var Ctor = indices.constructor;
        var thisCount = this._count;
        // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.
        if (Ctor === Array) {
            newIndices = new Ctor(thisCount);
            for (var i = 0; i < thisCount; i++) {
                newIndices[i] = indices[i];
            }
        }
        else {
            newIndices = new Ctor(indices.buffer, 0, thisCount);
        }
    }
    else {
        var Ctor = getIndicesCtor(this);
        var newIndices = new Ctor(this.count());
        for (var i = 0; i < newIndices.length; i++) {
            newIndices[i] = i;
        }
    }

    return newIndices;
};

/**
 * Get value. Return NaN if idx is out of range.
 * @param {string} dim Dim must be concrete name.
 * @param {number} idx
 * @param {boolean} stack
 * @return {number}
 */
listProto.get = function (dim, idx /*, stack */) {
    if (!(idx >= 0 && idx < this._count)) {
        return NaN;
    }
    var storage = this._storage;
    if (!storage[dim]) {
        // TODO Warn ?
        return NaN;
    }

    idx = this.getRawIndex(idx);

    var chunkIndex = Math.floor(idx / this._chunkSize);
    var chunkOffset = idx % this._chunkSize;

    var chunkStore = storage[dim][chunkIndex];
    var value = chunkStore[chunkOffset];
    // FIXME ordinal data type is not stackable
    // if (stack) {
    //     var dimensionInfo = this._dimensionInfos[dim];
    //     if (dimensionInfo && dimensionInfo.stackable) {
    //         var stackedOn = this.stackedOn;
    //         while (stackedOn) {
    //             // Get no stacked data of stacked on
    //             var stackedValue = stackedOn.get(dim, idx);
    //             // Considering positive stack, negative stack and empty data
    //             if ((value >= 0 && stackedValue > 0)  // Positive stack
    //                 || (value <= 0 && stackedValue < 0) // Negative stack
    //             ) {
    //                 value += stackedValue;
    //             }
    //             stackedOn = stackedOn.stackedOn;
    //         }
    //     }
    // }

    return value;
};

/**
 * @param {string} dim concrete dim
 * @param {number} rawIndex
 * @return {number|string}
 */
listProto.getByRawIndex = function (dim, rawIdx) {
    if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
        return NaN;
    }
    var dimStore = this._storage[dim];
    if (!dimStore) {
        // TODO Warn ?
        return NaN;
    }

    var chunkIndex = Math.floor(rawIdx / this._chunkSize);
    var chunkOffset = rawIdx % this._chunkSize;
    var chunkStore = dimStore[chunkIndex];
    return chunkStore[chunkOffset];
};

/**
 * FIXME Use `get` on chrome maybe slow(in filterSelf and selectRange).
 * Hack a much simpler _getFast
 * @private
 */
listProto._getFast = function (dim, rawIdx) {
    var chunkIndex = Math.floor(rawIdx / this._chunkSize);
    var chunkOffset = rawIdx % this._chunkSize;
    var chunkStore = this._storage[dim][chunkIndex];
    return chunkStore[chunkOffset];
};

/**
 * Get value for multi dimensions.
 * @param {Array.<string>} [dimensions] If ignored, using all dimensions.
 * @param {number} idx
 * @return {number}
 */
listProto.getValues = function (dimensions, idx /*, stack */) {
    var values = [];

    if (!isArray(dimensions)) {
        // stack = idx;
        idx = dimensions;
        dimensions = this.dimensions;
    }

    for (var i = 0, len = dimensions.length; i < len; i++) {
        values.push(this.get(dimensions[i], idx /*, stack */));
    }

    return values;
};

/**
 * If value is NaN. Inlcuding '-'
 * Only check the coord dimensions.
 * @param {string} dim
 * @param {number} idx
 * @return {number}
 */
listProto.hasValue = function (idx) {
    var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord;
    for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) {
        // Ordinal type originally can be string or number.
        // But when an ordinal type is used on coord, it can
        // not be string but only number. So we can also use isNaN.
        if (isNaN(this.get(dataDimsOnCoord[i], idx))) {
            return false;
        }
    }
    return true;
};

/**
 * Get extent of data in one dimension
 * @param {string} dim
 * @param {boolean} stack
 */
listProto.getDataExtent = function (dim /*, stack */) {
    // Make sure use concrete dim as cache name.
    dim = this.getDimension(dim);
    var dimData = this._storage[dim];
    var initialExtent = getInitialExtent();

    // stack = !!((stack || false) && this.getCalculationInfo(dim));

    if (!dimData) {
        return initialExtent;
    }

    // Make more strict checkings to ensure hitting cache.
    var currEnd = this.count();
    // var cacheName = [dim, !!stack].join('_');
    // var cacheName = dim;

    // Consider the most cases when using data zoom, `getDataExtent`
    // happened before filtering. We cache raw extent, which is not
    // necessary to be cleared and recalculated when restore data.
    var useRaw = !this._indices; // && !stack;
    var dimExtent;

    if (useRaw) {
        return this._rawExtent[dim].slice();
    }
    dimExtent = this._extent[dim];
    if (dimExtent) {
        return dimExtent.slice();
    }
    dimExtent = initialExtent;

    var min = dimExtent[0];
    var max = dimExtent[1];

    for (var i = 0; i < currEnd; i++) {
        // var value = stack ? this.get(dim, i, true) : this._getFast(dim, this.getRawIndex(i));
        var value = this._getFast(dim, this.getRawIndex(i));
        value < min && (min = value);
        value > max && (max = value);
    }

    dimExtent = [min, max];

    this._extent[dim] = dimExtent;

    return dimExtent;
};

/**
 * Optimize for the scenario that data is filtered by a given extent.
 * Consider that if data amount is more than hundreds of thousand,
 * extent calculation will cost more than 10ms and the cache will
 * be erased because of the filtering.
 */
listProto.getApproximateExtent = function (dim /*, stack */) {
    dim = this.getDimension(dim);
    return this._approximateExtent[dim] || this.getDataExtent(dim /*, stack */);
};

listProto.setApproximateExtent = function (extent, dim /*, stack */) {
    dim = this.getDimension(dim);
    this._approximateExtent[dim] = extent.slice();
};

/**
 * @param {string} key
 * @return {*}
 */
listProto.getCalculationInfo = function (key) {
    return this._calculationInfo[key];
};

/**
 * @param {string|Object} key or k-v object
 * @param {*} [value]
 */
listProto.setCalculationInfo = function (key, value) {
    isObject$4(key)
        ? extend(this._calculationInfo, key)
        : (this._calculationInfo[key] = value);
};

/**
 * Get sum of data in one dimension
 * @param {string} dim
 */
listProto.getSum = function (dim /*, stack */) {
    var dimData = this._storage[dim];
    var sum = 0;
    if (dimData) {
        for (var i = 0, len = this.count(); i < len; i++) {
            var value = this.get(dim, i /*, stack */);
            if (!isNaN(value)) {
                sum += value;
            }
        }
    }
    return sum;
};

/**
 * Get median of data in one dimension
 * @param {string} dim
 */
listProto.getMedian = function (dim /*, stack */) {
    var dimDataArray = [];
    // map all data of one dimension
    this.each(dim, function (val, idx) {
        if (!isNaN(val)) {
            dimDataArray.push(val);
        }
    });

    // TODO
    // Use quick select?

    // immutability & sort
    var sortedDimDataArray = [].concat(dimDataArray).sort(function (a, b) {
        return a - b;
    });
    var len = this.count();
    // calculate median
    return len === 0
        ? 0
        : len % 2 === 1
        ? sortedDimDataArray[(len - 1) / 2]
        : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
};

// /**
//  * Retreive the index with given value
//  * @param {string} dim Concrete dimension.
//  * @param {number} value
//  * @return {number}
//  */
// Currently incorrect: should return dataIndex but not rawIndex.
// Do not fix it until this method is to be used somewhere.
// FIXME Precision of float value
// listProto.indexOf = function (dim, value) {
//     var storage = this._storage;
//     var dimData = storage[dim];
//     var chunkSize = this._chunkSize;
//     if (dimData) {
//         for (var i = 0, len = this.count(); i < len; i++) {
//             var chunkIndex = Math.floor(i / chunkSize);
//             var chunkOffset = i % chunkSize;
//             if (dimData[chunkIndex][chunkOffset] === value) {
//                 return i;
//             }
//         }
//     }
//     return -1;
// };

/**
 * Only support the dimension which inverted index created.
 * Do not support other cases until required.
 * @param {string} concrete dim
 * @param {number|string} value
 * @return {number} rawIndex
 */
listProto.rawIndexOf = function (dim, value) {
    var invertedIndices = dim && this._invertedIndicesMap[dim];
    if (__DEV__) {
        if (!invertedIndices) {
            throw new Error('Do not supported yet');
        }
    }
    var rawIndex = invertedIndices[value];
    if (rawIndex == null || isNaN(rawIndex)) {
        return INDEX_NOT_FOUND;
    }
    return rawIndex;
};

/**
 * Retreive the index with given name
 * @param {number} idx
 * @param {number} name
 * @return {number}
 */
listProto.indexOfName = function (name) {
    for (var i = 0, len = this.count(); i < len; i++) {
        if (this.getName(i) === name) {
            return i;
        }
    }

    return -1;
};

/**
 * Retreive the index with given raw data index
 * @param {number} idx
 * @param {number} name
 * @return {number}
 */
listProto.indexOfRawIndex = function (rawIndex) {
    if (rawIndex >= this._rawCount || rawIndex < 0) {
        return -1;
    }

    if (!this._indices) {
        return rawIndex;
    }

    // Indices are ascending
    var indices = this._indices;

    // If rawIndex === dataIndex
    var rawDataIndex = indices[rawIndex];
    if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
        return rawIndex;
    }

    var left = 0;
    var right = this._count - 1;
    while (left <= right) {
        var mid = (left + right) / 2 | 0;
        if (indices[mid] < rawIndex) {
            left = mid + 1;
        }
        else if (indices[mid] > rawIndex) {
            right = mid - 1;
        }
        else {
            return mid;
        }
    }
    return -1;
};

/**
 * Retreive the index of nearest value
 * @param {string} dim
 * @param {number} value
 * @param {number} [maxDistance=Infinity]
 * @return {Array.<number>} Considere multiple points has the same value.
 */
listProto.indicesOfNearest = function (dim, value, maxDistance) {
    var storage = this._storage;
    var dimData = storage[dim];
    var nearestIndices = [];

    if (!dimData) {
        return nearestIndices;
    }

    if (maxDistance == null) {
        maxDistance = Infinity;
    }

    var minDist = Number.MAX_VALUE;
    var minDiff = -1;
    for (var i = 0, len = this.count(); i < len; i++) {
        var diff = value - this.get(dim, i /*, stack */);
        var dist = Math.abs(diff);
        if (diff <= maxDistance && dist <= minDist) {
            // For the case of two data are same on xAxis, which has sequence data.
            // Show the nearest index
            // https://github.com/ecomfe/echarts/issues/2869
            if (dist < minDist || (diff >= 0 && minDiff < 0)) {
                minDist = dist;
                minDiff = diff;
                nearestIndices.length = 0;
            }
            nearestIndices.push(i);
        }
    }
    return nearestIndices;
};

/**
 * Get raw data index
 * @param {number} idx
 * @return {number}
 */
listProto.getRawIndex = getRawIndexWithoutIndices;

function getRawIndexWithoutIndices(idx) {
    return idx;
}

function getRawIndexWithIndices(idx) {
    if (idx < this._count && idx >= 0) {
        return this._indices[idx];
    }
    return -1;
}

/**
 * Get raw data item
 * @param {number} idx
 * @return {number}
 */
listProto.getRawDataItem = function (idx) {
    if (!this._rawData.persistent) {
        var val = [];
        for (var i = 0; i < this.dimensions.length; i++) {
            var dim = this.dimensions[i];
            val.push(this.get(dim, idx));
        }
        return val;
    }
    else {
        return this._rawData.getItem(this.getRawIndex(idx));
    }
};

/**
 * @param {number} idx
 * @param {boolean} [notDefaultIdx=false]
 * @return {string}
 */
listProto.getName = function (idx) {
    var rawIndex = this.getRawIndex(idx);
    return this._nameList[rawIndex]
        || getRawValueFromStore(this, this._nameDimIdx, rawIndex)
        || '';
};

/**
 * @param {number} idx
 * @param {boolean} [notDefaultIdx=false]
 * @return {string}
 */
listProto.getId = function (idx) {
    return getId(this, this.getRawIndex(idx));
};

function getId(list, rawIndex) {
    var id = list._idList[rawIndex];
    if (id == null) {
        id = getRawValueFromStore(list, list._idDimIdx, rawIndex);
    }
    if (id == null) {
        // FIXME Check the usage in graph, should not use prefix.
        id = ID_PREFIX + rawIndex;
    }
    return id;
}

function normalizeDimensions(dimensions) {
    if (!isArray(dimensions)) {
        dimensions = [dimensions];
    }
    return dimensions;
}

function validateDimensions(list, dims) {
    for (var i = 0; i < dims.length; i++) {
        // stroage may be empty when no data, so use
        // dimensionInfos to check.
        if (!list._dimensionInfos[dims[i]]) {
            console.error('Unkown dimension ' + dims[i]);
        }
    }
}

/**
 * Data iteration
 * @param {string|Array.<string>}
 * @param {Function} cb
 * @param {*} [context=this]
 *
 * @example
 *  list.each('x', function (x, idx) {});
 *  list.each(['x', 'y'], function (x, y, idx) {});
 *  list.each(function (idx) {})
 */
listProto.each = function (dims, cb, context, contextCompat) {
    'use strict';

    if (!this._count) {
        return;
    }

    if (typeof dims === 'function') {
        contextCompat = context;
        context = cb;
        cb = dims;
        dims = [];
    }

    // contextCompat just for compat echarts3
    context = context || contextCompat || this;

    dims = map(normalizeDimensions(dims), this.getDimension, this);

    if (__DEV__) {
        validateDimensions(this, dims);
    }

    var dimSize = dims.length;

    for (var i = 0; i < this.count(); i++) {
        // Simple optimization
        switch (dimSize) {
            case 0:
                cb.call(context, i);
                break;
            case 1:
                cb.call(context, this.get(dims[0], i), i);
                break;
            case 2:
                cb.call(context, this.get(dims[0], i), this.get(dims[1], i), i);
                break;
            default:
                var k = 0;
                var value = [];
                for (; k < dimSize; k++) {
                    value[k] = this.get(dims[k], i);
                }
                // Index
                value[k] = i;
                cb.apply(context, value);
        }
    }
};

/**
 * Data filter
 * @param {string|Array.<string>}
 * @param {Function} cb
 * @param {*} [context=this]
 */
listProto.filterSelf = function (dimensions, cb, context, contextCompat) {
    'use strict';

    if (!this._count) {
        return;
    }

    if (typeof dimensions === 'function') {
        contextCompat = context;
        context = cb;
        cb = dimensions;
        dimensions = [];
    }

    // contextCompat just for compat echarts3
    context = context || contextCompat || this;

    dimensions = map(
        normalizeDimensions(dimensions), this.getDimension, this
    );

    if (__DEV__) {
        validateDimensions(this, dimensions);
    }


    var count = this.count();
    var Ctor = getIndicesCtor(this);
    var newIndices = new Ctor(count);
    var value = [];
    var dimSize = dimensions.length;

    var offset = 0;
    var dim0 = dimensions[0];

    for (var i = 0; i < count; i++) {
        var keep;
        var rawIdx = this.getRawIndex(i);
        // Simple optimization
        if (dimSize === 0) {
            keep = cb.call(context, i);
        }
        else if (dimSize === 1) {
            var val = this._getFast(dim0, rawIdx);
            keep = cb.call(context, val, i);
        }
        else {
            for (var k = 0; k < dimSize; k++) {
                value[k] = this._getFast(dim0, rawIdx);
            }
            value[k] = i;
            keep = cb.apply(context, value);
        }
        if (keep) {
            newIndices[offset++] = rawIdx;
        }
    }

    // Set indices after filtered.
    if (offset < count) {
        this._indices = newIndices;
    }
    this._count = offset;
    // Reset data extent
    this._extent = {};

    this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;

    return this;
};

/**
 * Select data in range. (For optimization of filter)
 * (Manually inline code, support 5 million data filtering in data zoom.)
 */
listProto.selectRange = function (range) {
    'use strict';

    if (!this._count) {
        return;
    }

    var dimensions = [];
    for (var dim in range) {
        if (range.hasOwnProperty(dim)) {
            dimensions.push(dim);
        }
    }

    if (__DEV__) {
        validateDimensions(this, dimensions);
    }

    var dimSize = dimensions.length;
    if (!dimSize) {
        return;
    }

    var originalCount = this.count();
    var Ctor = getIndicesCtor(this);
    var newIndices = new Ctor(originalCount);

    var offset = 0;
    var dim0 = dimensions[0];

    var min = range[dim0][0];
    var max = range[dim0][1];

    var quickFinished = false;
    if (!this._indices) {
        // Extreme optimization for common case. About 2x faster in chrome.
        var idx = 0;
        if (dimSize === 1) {
            var dimStorage = this._storage[dimensions[0]];
            for (var k = 0; k < this._chunkCount; k++) {
                var chunkStorage = dimStorage[k];
                var len = Math.min(this._count - k * this._chunkSize, this._chunkSize);
                for (var i = 0; i < len; i++) {
                    var val = chunkStorage[i];
                    // NaN will not be filtered. Consider the case, in line chart, empty
                    // value indicates the line should be broken. But for the case like
                    // scatter plot, a data item with empty value will not be rendered,
                    // but the axis extent may be effected if some other dim of the data
                    // item has value. Fortunately it is not a significant negative effect.
                    if (
                        (val >= min && val <= max) || isNaN(val)
                    ) {
                        newIndices[offset++] = idx;
                    }
                    idx++;
                }
            }
            quickFinished = true;
        }
        else if (dimSize === 2) {
            var dimStorage = this._storage[dim0];
            var dimStorage2 = this._storage[dimensions[1]];
            var min2 = range[dimensions[1]][0];
            var max2 = range[dimensions[1]][1];
            for (var k = 0; k < this._chunkCount; k++) {
                var chunkStorage = dimStorage[k];
                var chunkStorage2 = dimStorage2[k];
                var len = Math.min(this._count - k * this._chunkSize, this._chunkSize);
                for (var i = 0; i < len; i++) {
                    var val = chunkStorage[i];
                    var val2 = chunkStorage2[i];
                    // Do not filter NaN, see comment above.
                    if ((
                            (val >= min && val <= max) || isNaN(val)
                        )
                        && (
                            (val2 >= min2 && val2 <= max2) || isNaN(val2)
                        )
                    ) {
                        newIndices[offset++] = idx;
                    }
                    idx++;
                }
            }
            quickFinished = true;
        }
    }
    if (!quickFinished) {
        if (dimSize === 1) {
            for (var i = 0; i < originalCount; i++) {
                var rawIndex = this.getRawIndex(i);
                var val = this._getFast(dim0, rawIndex);
                // Do not filter NaN, see comment above.
                if (
                    (val >= min && val <= max) || isNaN(val)
                ) {
                    newIndices[offset++] = rawIndex;
                }
            }
        }
        else {
            for (var i = 0; i < originalCount; i++) {
                var keep = true;
                var rawIndex = this.getRawIndex(i);
                for (var k = 0; k < dimSize; k++) {
                    var dimk = dimensions[k];
                    var val = this._getFast(dim, rawIndex);
                    // Do not filter NaN, see comment above.
                    if (val < range[dimk][0] || val > range[dimk][1]) {
                        keep = false;
                    }
                }
                if (keep) {
                    newIndices[offset++] = this.getRawIndex(i);
                }
            }
        }
    }

    // Set indices after filtered.
    if (offset < originalCount) {
        this._indices = newIndices;
    }
    this._count = offset;
    // Reset data extent
    this._extent = {};

    this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;

    return this;
};

/**
 * Data mapping to a plain array
 * @param {string|Array.<string>} [dimensions]
 * @param {Function} cb
 * @param {*} [context=this]
 * @return {Array}
 */
listProto.mapArray = function (dimensions, cb, context, contextCompat) {
    'use strict';

    if (typeof dimensions === 'function') {
        contextCompat = context;
        context = cb;
        cb = dimensions;
        dimensions = [];
    }

    // contextCompat just for compat echarts3
    context = context || contextCompat || this;

    var result = [];
    this.each(dimensions, function () {
        result.push(cb && cb.apply(this, arguments));
    }, context);
    return result;
};

// Data in excludeDimensions is copied, otherwise transfered.
function cloneListForMapAndSample(original, excludeDimensions) {
    var allDimensions = original.dimensions;
    var list = new List(
        map(allDimensions, original.getDimensionInfo, original),
        original.hostModel
    );
    // FIXME If needs stackedOn, value may already been stacked
    transferProperties(list, original);

    var storage = list._storage = {};
    var originalStorage = original._storage;

    // Init storage
    for (var i = 0; i < allDimensions.length; i++) {
        var dim = allDimensions[i];
        if (originalStorage[dim]) {
            // Notice that we do not reset invertedIndicesMap here, becuase
            // there is no scenario of mapping or sampling ordinal dimension.
            if (indexOf(excludeDimensions, dim) >= 0) {
                storage[dim] = cloneDimStore(originalStorage[dim]);
                list._rawExtent[dim] = getInitialExtent();
                list._extent[dim] = null;
            }
            else {
                // Direct reference for other dimensions
                storage[dim] = originalStorage[dim];
            }
        }
    }
    return list;
}

function cloneDimStore(originalDimStore) {
    var newDimStore = new Array(originalDimStore.length);
    for (var j = 0; j < originalDimStore.length; j++) {
        newDimStore[j] = cloneChunk(originalDimStore[j]);
    }
    return newDimStore;
}

function getInitialExtent() {
    return [Infinity, -Infinity];
}

/**
 * Data mapping to a new List with given dimensions
 * @param {string|Array.<string>} dimensions
 * @param {Function} cb
 * @param {*} [context=this]
 * @return {Array}
 */
listProto.map = function (dimensions, cb, context, contextCompat) {
    'use strict';

    // contextCompat just for compat echarts3
    context = context || contextCompat || this;

    dimensions = map(
        normalizeDimensions(dimensions), this.getDimension, this
    );

    if (__DEV__) {
        validateDimensions(this, dimensions);
    }

    var list = cloneListForMapAndSample(this, dimensions);

    // Following properties are all immutable.
    // So we can reference to the same value
    list._indices = this._indices;
    list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;

    var storage = list._storage;

    var tmpRetValue = [];
    var chunkSize = this._chunkSize;
    var dimSize = dimensions.length;
    var dataCount = this.count();
    var values = [];
    var rawExtent = list._rawExtent;

    for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) {
        for (var dimIndex = 0; dimIndex < dimSize; dimIndex++) {
            values[dimIndex] = this.get(dimensions[dimIndex], dataIndex /*, stack */);
        }
        values[dimSize] = dataIndex;

        var retValue = cb && cb.apply(context, values);
        if (retValue != null) {
            // a number or string (in oridinal dimension)?
            if (typeof retValue !== 'object') {
                tmpRetValue[0] = retValue;
                retValue = tmpRetValue;
            }

            var rawIndex = this.getRawIndex(dataIndex);
            var chunkIndex = Math.floor(rawIndex / chunkSize);
            var chunkOffset = rawIndex % chunkSize;

            for (var i = 0; i < retValue.length; i++) {
                var dim = dimensions[i];
                var val = retValue[i];
                var rawExtentOnDim = rawExtent[dim];

                var dimStore = storage[dim];
                if (dimStore) {
                    dimStore[chunkIndex][chunkOffset] = val;
                }

                if (val < rawExtentOnDim[0]) {
                    rawExtentOnDim[0] = val;
                }
                if (val > rawExtentOnDim[1]) {
                    rawExtentOnDim[1] = val;
                }
            }
        }
    }

    return list;
};

/**
 * Large data down sampling on given dimension
 * @param {string} dimension
 * @param {number} rate
 * @param {Function} sampleValue
 * @param {Function} sampleIndex Sample index for name and id
 */
listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) {
    var list = cloneListForMapAndSample(this, [dimension]);
    var targetStorage = list._storage;

    var frameValues = [];
    var frameSize = Math.floor(1 / rate);

    var dimStore = targetStorage[dimension];
    var len = this.count();
    var chunkSize = this._chunkSize;
    var rawExtentOnDim = list._rawExtent[dimension];

    var newIndices = new (getIndicesCtor(this))(len);

    var offset = 0;
    for (var i = 0; i < len; i += frameSize) {
        // Last frame
        if (frameSize > len - i) {
            frameSize = len - i;
            frameValues.length = frameSize;
        }
        for (var k = 0; k < frameSize; k++) {
            var dataIdx = this.getRawIndex(i + k);
            var originalChunkIndex = Math.floor(dataIdx / chunkSize);
            var originalChunkOffset = dataIdx % chunkSize;
            frameValues[k] = dimStore[originalChunkIndex][originalChunkOffset];
        }
        var value = sampleValue(frameValues);
        var sampleFrameIdx = this.getRawIndex(
            Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)
        );
        var sampleChunkIndex = Math.floor(sampleFrameIdx / chunkSize);
        var sampleChunkOffset = sampleFrameIdx % chunkSize;
        // Only write value on the filtered data
        dimStore[sampleChunkIndex][sampleChunkOffset] = value;

        if (value < rawExtentOnDim[0]) {
            rawExtentOnDim[0] = value;
        }
        if (value > rawExtentOnDim[1]) {
            rawExtentOnDim[1] = value;
        }

        newIndices[offset++] = sampleFrameIdx;
    }

    list._count = offset;
    list._indices = newIndices;

    list.getRawIndex = getRawIndexWithIndices;

    return list;
};

/**
 * Get model of one data item.
 *
 * @param {number} idx
 */
// FIXME Model proxy ?
listProto.getItemModel = function (idx) {
    var hostModel = this.hostModel;
    return new Model(this.getRawDataItem(idx), hostModel, hostModel && hostModel.ecModel);
};

/**
 * Create a data differ
 * @param {module:echarts/data/List} otherList
 * @return {module:echarts/data/DataDiffer}
 */
listProto.diff = function (otherList) {
    var thisList = this;

    return new DataDiffer(
        otherList ? otherList.getIndices() : [],
        this.getIndices(),
        function (idx) {
            return getId(otherList, idx);
        },
        function (idx) {
            return getId(thisList, idx);
        }
    );
};
/**
 * Get visual property.
 * @param {string} key
 */
listProto.getVisual = function (key) {
    var visual = this._visual;
    return visual && visual[key];
};

/**
 * Set visual property
 * @param {string|Object} key
 * @param {*} [value]
 *
 * @example
 *  setVisual('color', color);
 *  setVisual({
 *      'color': color
 *  });
 */
listProto.setVisual = function (key, val) {
    if (isObject$4(key)) {
        for (var name in key) {
            if (key.hasOwnProperty(name)) {
                this.setVisual(name, key[name]);
            }
        }
        return;
    }
    this._visual = this._visual || {};
    this._visual[key] = val;
};

/**
 * Set layout property.
 * @param {string|Object} key
 * @param {*} [val]
 */
listProto.setLayout = function (key, val) {
    if (isObject$4(key)) {
        for (var name in key) {
            if (key.hasOwnProperty(name)) {
                this.setLayout(name, key[name]);
            }
        }
        return;
    }
    this._layout[key] = val;
};

/**
 * Get layout property.
 * @param  {string} key.
 * @return {*}
 */
listProto.getLayout = function (key) {
    return this._layout[key];
};

/**
 * Get layout of single data item
 * @param {number} idx
 */
listProto.getItemLayout = function (idx) {
    return this._itemLayouts[idx];
};

/**
 * Set layout of single data item
 * @param {number} idx
 * @param {Object} layout
 * @param {boolean=} [merge=false]
 */
listProto.setItemLayout = function (idx, layout, merge$$1) {
    this._itemLayouts[idx] = merge$$1
        ? extend(this._itemLayouts[idx] || {}, layout)
        : layout;
};

/**
 * Clear all layout of single data item
 */
listProto.clearItemLayouts = function () {
    this._itemLayouts.length = 0;
};

/**
 * Get visual property of single data item
 * @param {number} idx
 * @param {string} key
 * @param {boolean} [ignoreParent=false]
 */
listProto.getItemVisual = function (idx, key, ignoreParent) {
    var itemVisual = this._itemVisuals[idx];
    var val = itemVisual && itemVisual[key];
    if (val == null && !ignoreParent) {
        // Use global visual property
        return this.getVisual(key);
    }
    return val;
};

/**
 * Set visual property of single data item
 *
 * @param {number} idx
 * @param {string|Object} key
 * @param {*} [value]
 *
 * @example
 *  setItemVisual(0, 'color', color);
 *  setItemVisual(0, {
 *      'color': color
 *  });
 */
listProto.setItemVisual = function (idx, key, value) {
    var itemVisual = this._itemVisuals[idx] || {};
    var hasItemVisual = this.hasItemVisual;
    this._itemVisuals[idx] = itemVisual;

    if (isObject$4(key)) {
        for (var name in key) {
            if (key.hasOwnProperty(name)) {
                itemVisual[name] = key[name];
                hasItemVisual[name] = true;
            }
        }
        return;
    }
    itemVisual[key] = value;
    hasItemVisual[key] = true;
};

/**
 * Clear itemVisuals and list visual.
 */
listProto.clearAllVisual = function () {
    this._visual = {};
    this._itemVisuals = [];
    this.hasItemVisual = {};
};

var setItemDataAndSeriesIndex = function (child) {
    child.seriesIndex = this.seriesIndex;
    child.dataIndex = this.dataIndex;
    child.dataType = this.dataType;
};
/**
 * Set graphic element relative to data. It can be set as null
 * @param {number} idx
 * @param {module:zrender/Element} [el]
 */
listProto.setItemGraphicEl = function (idx, el) {
    var hostModel = this.hostModel;

    if (el) {
        // Add data index and series index for indexing the data by element
        // Useful in tooltip
        el.dataIndex = idx;
        el.dataType = this.dataType;
        el.seriesIndex = hostModel && hostModel.seriesIndex;
        if (el.type === 'group') {
            el.traverse(setItemDataAndSeriesIndex, el);
        }
    }

    this._graphicEls[idx] = el;
};

/**
 * @param {number} idx
 * @return {module:zrender/Element}
 */
listProto.getItemGraphicEl = function (idx) {
    return this._graphicEls[idx];
};

/**
 * @param {Function} cb
 * @param {*} context
 */
listProto.eachItemGraphicEl = function (cb, context) {
    each$1(this._graphicEls, function (el, idx) {
        if (el) {
            cb && cb.call(context, el, idx);
        }
    });
};

/**
 * Shallow clone a new list except visual and layout properties, and graph elements.
 * New list only change the indices.
 */
listProto.cloneShallow = function (list) {
    if (!list) {
        var dimensionInfoList = map(this.dimensions, this.getDimensionInfo, this);
        list = new List(dimensionInfoList, this.hostModel);
    }

    // FIXME
    list._storage = this._storage;

    transferProperties(list, this);

    // Clone will not change the data extent and indices
    if (this._indices) {
        var Ctor = this._indices.constructor;
        list._indices = new Ctor(this._indices);
    }
    else {
        list._indices = null;
    }
    list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;

    return list;
};

/**
 * Wrap some method to add more feature
 * @param {string} methodName
 * @param {Function} injectFunction
 */
listProto.wrapMethod = function (methodName, injectFunction) {
    var originalMethod = this[methodName];
    if (typeof originalMethod !== 'function') {
        return;
    }
    this.__wrappedMethods = this.__wrappedMethods || [];
    this.__wrappedMethods.push(methodName);
    this[methodName] = function () {
        var res = originalMethod.apply(this, arguments);
        return injectFunction.apply(this, [res].concat(slice(arguments)));
    };
};

// Methods that create a new list based on this list should be listed here.
// Notice that those method should `RETURN` the new list.
listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map'];
// Methods that change indices of this list should be listed here.
listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @deprecated
 * Use `echarts/data/helper/createDimensions` instead.
 */

/**
 * @see {module:echarts/test/ut/spec/data/completeDimensions}
 *
 * Complete the dimensions array, by user defined `dimension` and `encode`,
 * and guessing from the data structure.
 * If no 'value' dimension specified, the first no-named dimension will be
 * named as 'value'.
 *
 * @param {Array.<string>} sysDims Necessary dimensions, like ['x', 'y'], which
 *      provides not only dim template, but also default order.
 *      properties: 'name', 'type', 'displayName'.
 *      `name` of each item provides default coord name.
 *      [{dimsDef: [string|Object, ...]}, ...] dimsDef of sysDim item provides default dim name, and
 *                                    provide dims count that the sysDim required.
 *      [{ordinalMeta}] can be specified.
 * @param {module:echarts/data/Source|Array|Object} source or data (for compatibal with pervious)
 * @param {Object} [opt]
 * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
 *      For example: ['asdf', {name, type}, ...].
 * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
 * @param {string} [opt.generateCoord] Generate coord dim with the given name.
 *                 If not specified, extra dim names will be:
 *                 'value', 'value0', 'value1', ...
 * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`.
 *                 If `generateCoordCount` specified, the generated dim names will be:
 *                 `generateCoord` + 0, `generateCoord` + 1, ...
 *                 can be Infinity, indicate that use all of the remain columns.
 * @param {number} [opt.dimCount] If not specified, guess by the first data item.
 * @param {number} [opt.encodeDefaulter] If not specified, auto find the next available data dim.
 * @return {Array.<Object>} [{
 *      name: string mandatory,
 *      displayName: string, the origin name in dimsDef, see source helper.
 *                 If displayName given, the tooltip will displayed vertically.
 *      coordDim: string mandatory,
 *      coordDimIndex: number mandatory,
 *      type: string optional,
 *      otherDims: { never null/undefined
 *          tooltip: number optional,
 *          label: number optional,
 *          itemName: number optional,
 *          seriesName: number optional,
 *      },
 *      isExtraCoord: boolean true if coord is generated
 *          (not specified in encode and not series specified)
 *      other props ...
 * }]
 */
function completeDimensions(sysDims, source, opt) {
    if (!Source.isInstance(source)) {
        source = Source.seriesDataToSource(source);
    }

    opt = opt || {};
    sysDims = (sysDims || []).slice();
    var dimsDef = (opt.dimsDef || []).slice();
    var encodeDef = createHashMap(opt.encodeDef);
    var dataDimNameMap = createHashMap();
    var coordDimNameMap = createHashMap();
    // var valueCandidate;
    var result = [];

    var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimCount);

    // Apply user defined dims (`name` and `type`) and init result.
    for (var i = 0; i < dimCount; i++) {
        var dimDefItem = dimsDef[i] = extend(
            {}, isObject$1(dimsDef[i]) ? dimsDef[i] : {name: dimsDef[i]}
        );
        var userDimName = dimDefItem.name;
        var resultItem = result[i] = {otherDims: {}};
        // Name will be applied later for avoiding duplication.
        if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
            // Only if `series.dimensions` is defined in option
            // displayName, will be set, and dimension will be diplayed vertically in
            // tooltip by default.
            resultItem.name = resultItem.displayName = userDimName;
            dataDimNameMap.set(userDimName, i);
        }
        dimDefItem.type != null && (resultItem.type = dimDefItem.type);
        dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName);
    }

    // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.
    encodeDef.each(function (dataDims, coordDim) {
        dataDims = normalizeToArray(dataDims).slice();

        // Note: It is allowed that `dataDims.length` is `0`, e.g., options is
        // `{encode: {x: -1, y: 1}}`. Should not filter anything in
        // this case.
        if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) {
            encodeDef.set(coordDim, false);
            return;
        }

        var validDataDims = encodeDef.set(coordDim, []);
        each$1(dataDims, function (resultDimIdx, idx) {
            // The input resultDimIdx can be dim name or index.
            isString(resultDimIdx) && (resultDimIdx = dataDimNameMap.get(resultDimIdx));
            if (resultDimIdx != null && resultDimIdx < dimCount) {
                validDataDims[idx] = resultDimIdx;
                applyDim(result[resultDimIdx], coordDim, idx);
            }
        });
    });

    // Apply templetes and default order from `sysDims`.
    var availDimIdx = 0;
    each$1(sysDims, function (sysDimItem, sysDimIndex) {
        var coordDim;
        var sysDimItem;
        var sysDimItemDimsDef;
        var sysDimItemOtherDims;
        if (isString(sysDimItem)) {
            coordDim = sysDimItem;
            sysDimItem = {};
        }
        else {
            coordDim = sysDimItem.name;
            var ordinalMeta = sysDimItem.ordinalMeta;
            sysDimItem.ordinalMeta = null;
            sysDimItem = clone(sysDimItem);
            sysDimItem.ordinalMeta = ordinalMeta;
            // `coordDimIndex` should not be set directly.
            sysDimItemDimsDef = sysDimItem.dimsDef;
            sysDimItemOtherDims = sysDimItem.otherDims;
            sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex =
                sysDimItem.dimsDef = sysDimItem.otherDims = null;
        }

        var dataDims = encodeDef.get(coordDim);

        // negative resultDimIdx means no need to mapping.
        if (dataDims === false) {
            return;
        }

        var dataDims = normalizeToArray(dataDims);

        // dimensions provides default dim sequences.
        if (!dataDims.length) {
            for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) {
                while (availDimIdx < result.length && result[availDimIdx].coordDim != null) {
                    availDimIdx++;
                }
                availDimIdx < result.length && dataDims.push(availDimIdx++);
            }
        }

        // Apply templates.
        each$1(dataDims, function (resultDimIdx, coordDimIndex) {
            var resultItem = result[resultDimIdx];
            applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex);
            if (resultItem.name == null && sysDimItemDimsDef) {
                var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex];
                !isObject$1(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = {name: sysDimItemDimsDefItem});
                resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name;
                resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip;
            }
            // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}}
            sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims);
        });
    });

    function applyDim(resultItem, coordDim, coordDimIndex) {
        if (OTHER_DIMENSIONS.get(coordDim) != null) {
            resultItem.otherDims[coordDim] = coordDimIndex;
        }
        else {
            resultItem.coordDim = coordDim;
            resultItem.coordDimIndex = coordDimIndex;
            coordDimNameMap.set(coordDim, true);
        }
    }

    // Make sure the first extra dim is 'value'.
    var generateCoord = opt.generateCoord;
    var generateCoordCount = opt.generateCoordCount;
    var fromZero = generateCoordCount != null;
    generateCoordCount = generateCoord ? (generateCoordCount || 1) : 0;
    var extra = generateCoord || 'value';

    // Set dim `name` and other `coordDim` and other props.
    for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
        var resultItem = result[resultDimIdx] = result[resultDimIdx] || {};
        var coordDim = resultItem.coordDim;

        if (coordDim == null) {
            resultItem.coordDim = genName(
                extra, coordDimNameMap, fromZero
            );
            resultItem.coordDimIndex = 0;
            if (!generateCoord || generateCoordCount <= 0) {
                resultItem.isExtraCoord = true;
            }
            generateCoordCount--;
        }

        resultItem.name == null && (resultItem.name = genName(
            resultItem.coordDim,
            dataDimNameMap
        ));

        if (resultItem.type == null && guessOrdinal(source, resultDimIdx, resultItem.name)) {
            resultItem.type = 'ordinal';
        }
    }

    return result;
}

// ??? TODO
// Originally detect dimCount by data[0]. Should we
// optimize it to only by sysDims and dimensions and encode.
// So only necessary dims will be initialized.
// But
// (1) custom series should be considered. where other dims
// may be visited.
// (2) sometimes user need to calcualte bubble size or use visualMap
// on other dimensions besides coordSys needed.
// So, dims that is not used by system, should be shared in storage?
function getDimCount(source, sysDims, dimsDef, optDimCount) {
    // Note that the result dimCount should not small than columns count
    // of data, otherwise `dataDimNameMap` checking will be incorrect.
    var dimCount = Math.max(
        source.dimensionsDetectCount || 1,
        sysDims.length,
        dimsDef.length,
        optDimCount || 0
    );
    each$1(sysDims, function (sysDimItem) {
        var sysDimItemDimsDef = sysDimItem.dimsDef;
        sysDimItemDimsDef && (dimCount = Math.max(dimCount, sysDimItemDimsDef.length));
    });
    return dimCount;
}

function genName(name, map$$1, fromZero) {
    if (fromZero || map$$1.get(name) != null) {
        var i = 0;
        while (map$$1.get(name + i) != null) {
            i++;
        }
        name += i;
    }
    map$$1.set(name, true);
    return name;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Substitute `completeDimensions`.
 * `completeDimensions` is to be deprecated.
 */
/**
 * @param {module:echarts/data/Source|module:echarts/data/List} source or data.
 * @param {Object|Array} [opt]
 * @param {Array.<string|Object>} [opt.coordDimensions=[]]
 * @param {number} [opt.dimensionsCount]
 * @param {string} [opt.generateCoord]
 * @param {string} [opt.generateCoordCount]
 * @param {Array.<string|Object>} [opt.dimensionsDefine=source.dimensionsDefine] Overwrite source define.
 * @param {Object|HashMap} [opt.encodeDefine=source.encodeDefine] Overwrite source define.
 * @return {Array.<Object>} dimensionsInfo
 */
var createDimensions = function (source, opt) {
    opt = opt || {};
    return completeDimensions(opt.coordDimensions || [], source, {
        dimsDef: opt.dimensionsDefine || source.dimensionsDefine,
        encodeDef: opt.encodeDefine || source.encodeDefine,
        dimCount: opt.dimensionsCount,
        generateCoord: opt.generateCoord,
        generateCoordCount: opt.generateCoordCount
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Note that it is too complicated to support 3d stack by value
 * (have to create two-dimension inverted index), so in 3d case
 * we just support that stacked by index.
 *
 * @param {module:echarts/model/Series} seriesModel
 * @param {Array.<string|Object>} dimensionInfoList The same as the input of <module:echarts/data/List>.
 *        The input dimensionInfoList will be modified.
 * @param {Object} [opt]
 * @param {boolean} [opt.stackedCoordDimension=''] Specify a coord dimension if needed.
 * @param {boolean} [opt.byIndex=false]
 * @return {Object} calculationInfo
 * {
 *     stackedDimension: string
 *     stackedByDimension: string
 *     isStackedByIndex: boolean
 *     stackedOverDimension: string
 *     stackResultDimension: string
 * }
 */
function enableDataStack(seriesModel, dimensionInfoList, opt) {
    opt = opt || {};
    var byIndex = opt.byIndex;
    var stackedCoordDimension = opt.stackedCoordDimension;

    // Compatibal: when `stack` is set as '', do not stack.
    var mayStack = !!(seriesModel && seriesModel.get('stack'));
    var stackedByDimInfo;
    var stackedDimInfo;
    var stackResultDimension;
    var stackedOverDimension;

    each$1(dimensionInfoList, function (dimensionInfo, index) {
        if (isString(dimensionInfo)) {
            dimensionInfoList[index] = dimensionInfo = {name: dimensionInfo};
        }

        if (mayStack && !dimensionInfo.isExtraCoord) {
            // Find the first ordinal dimension as the stackedByDimInfo.
            if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) {
                stackedByDimInfo = dimensionInfo;
            }
            // Find the first stackable dimension as the stackedDimInfo.
            if (!stackedDimInfo
                && dimensionInfo.type !== 'ordinal'
                && dimensionInfo.type !== 'time'
                && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)
            ) {
                stackedDimInfo = dimensionInfo;
            }
        }
    });

    if (stackedDimInfo && !byIndex && !stackedByDimInfo) {
        // Compatible with previous design, value axis (time axis) only stack by index.
        // It may make sense if the user provides elaborately constructed data.
        byIndex = true;
    }

    // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`.
    // That put stack logic in List is for using conveniently in echarts extensions, but it
    // might not be a good way.
    if (stackedDimInfo) {
        // Use a weird name that not duplicated with other names.
        stackResultDimension = '__\0ecstackresult';
        stackedOverDimension = '__\0ecstackedover';

        // Create inverted index to fast query index by value.
        if (stackedByDimInfo) {
            stackedByDimInfo.createInvertedIndices = true;
        }

        var stackedDimCoordDim = stackedDimInfo.coordDim;
        var stackedDimType = stackedDimInfo.type;
        var stackedDimCoordIndex = 0;

        each$1(dimensionInfoList, function (dimensionInfo) {
            if (dimensionInfo.coordDim === stackedDimCoordDim) {
                stackedDimCoordIndex++;
            }
        });

        dimensionInfoList.push({
            name: stackResultDimension,
            coordDim: stackedDimCoordDim,
            coordDimIndex: stackedDimCoordIndex,
            type: stackedDimType,
            isExtraCoord: true,
            isCalculationCoord: true
        });

        stackedDimCoordIndex++;

        dimensionInfoList.push({
            name: stackedOverDimension,
            // This dimension contains stack base (generally, 0), so do not set it as
            // `stackedDimCoordDim` to avoid extent calculation, consider log scale.
            coordDim: stackedOverDimension,
            coordDimIndex: stackedDimCoordIndex,
            type: stackedDimType,
            isExtraCoord: true,
            isCalculationCoord: true
        });
    }

    return {
        stackedDimension: stackedDimInfo && stackedDimInfo.name,
        stackedByDimension: stackedByDimInfo && stackedByDimInfo.name,
        isStackedByIndex: byIndex,
        stackedOverDimension: stackedOverDimension,
        stackResultDimension: stackResultDimension
    };
}

/**
 * @param {module:echarts/data/List} data
 * @param {string} stackedDim
 */
function isDimensionStacked(data, stackedDim /*, stackedByDim*/) {
    // Each single series only maps to one pair of axis. So we do not need to
    // check stackByDim, whatever stacked by a dimension or stacked by index.
    return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension');
        // && (
        //     stackedByDim != null
        //         ? stackedByDim === data.getCalculationInfo('stackedByDimension')
        //         : data.getCalculationInfo('isStackedByIndex')
        // );
}

/**
 * @param {module:echarts/data/List} data
 * @param {string} targetDim
 * @param {string} [stackedByDim] If not input this parameter, check whether
 *                                stacked by index.
 * @return {string} dimension
 */
function getStackedDimension(data, targetDim) {
    return isDimensionStacked(data, targetDim)
        ? data.getCalculationInfo('stackResultDimension')
        : targetDim;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/data/Source|Array} source Or raw data.
 * @param {module:echarts/model/Series} seriesModel
 * @param {Object} [opt]
 * @param {string} [opt.generateCoord]
 */
function createListFromArray(source, seriesModel, opt) {
    opt = opt || {};

    if (!Source.isInstance(source)) {
        source = Source.seriesDataToSource(source);
    }

    var coordSysName = seriesModel.get('coordinateSystem');
    var registeredCoordSys = CoordinateSystemManager.get(coordSysName);

    var coordSysDefine = getCoordSysDefineBySeries(seriesModel);

    var coordSysDimDefs;

    if (coordSysDefine) {
        coordSysDimDefs = map(coordSysDefine.coordSysDims, function (dim) {
            var dimInfo = {name: dim};
            var axisModel = coordSysDefine.axisMap.get(dim);
            if (axisModel) {
                var axisType = axisModel.get('type');
                dimInfo.type = getDimensionTypeByAxis(axisType);
                // dimInfo.stackable = isStackable(axisType);
            }
            return dimInfo;
        });
    }

    if (!coordSysDimDefs) {
        // Get dimensions from registered coordinate system
        coordSysDimDefs = (registeredCoordSys && (
            registeredCoordSys.getDimensionsInfo
                ? registeredCoordSys.getDimensionsInfo()
                : registeredCoordSys.dimensions.slice()
        )) || ['x', 'y'];
    }

    var dimInfoList = createDimensions(source, {
        coordDimensions: coordSysDimDefs,
        generateCoord: opt.generateCoord
    });

    var firstCategoryDimIndex;
    var hasNameEncode;
    coordSysDefine && each$1(dimInfoList, function (dimInfo, dimIndex) {
        var coordDim = dimInfo.coordDim;
        var categoryAxisModel = coordSysDefine.categoryAxisMap.get(coordDim);
        if (categoryAxisModel) {
            if (firstCategoryDimIndex == null) {
                firstCategoryDimIndex = dimIndex;
            }
            dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta();
        }
        if (dimInfo.otherDims.itemName != null) {
            hasNameEncode = true;
        }
    });
    if (!hasNameEncode && firstCategoryDimIndex != null) {
        dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0;
    }

    var stackCalculationInfo = enableDataStack(seriesModel, dimInfoList);

    var list = new List(dimInfoList, seriesModel);

    list.setCalculationInfo(stackCalculationInfo);

    var dimValueGetter = (firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source))
        ? function (itemOpt, dimName, dataIndex, dimIndex) {
            // Use dataIndex as ordinal value in categoryAxis
            return dimIndex === firstCategoryDimIndex
                ? dataIndex
                : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex);
        }
        : null;

    list.hasItemOption = false;
    list.initData(source, null, dimValueGetter);

    return list;
}

function isNeedCompleteOrdinalData(source) {
    if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) {
        var sampleItem = firstDataNotNull(source.data || []);
        return sampleItem != null
            && !isArray(getDataItemValue(sampleItem));
    }
}

function firstDataNotNull(data) {
    var i = 0;
    while (i < data.length && data[i] == null) {
        i++;
    }
    return data[i];
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * // Scale class management
 * @module echarts/scale/Scale
 */

/**
 * @param {Object} [setting]
 */
function Scale(setting) {
    this._setting = setting || {};

    /**
     * Extent
     * @type {Array.<number>}
     * @protected
     */
    this._extent = [Infinity, -Infinity];

    /**
     * Step is calculated in adjustExtent
     * @type {Array.<number>}
     * @protected
     */
    this._interval = 0;

    this.init && this.init.apply(this, arguments);
}

/**
 * Parse input val to valid inner number.
 * @param {*} val
 * @return {number}
 */
Scale.prototype.parse = function (val) {
    // Notice: This would be a trap here, If the implementation
    // of this method depends on extent, and this method is used
    // before extent set (like in dataZoom), it would be wrong.
    // Nevertheless, parse does not depend on extent generally.
    return val;
};

Scale.prototype.getSetting = function (name) {
    return this._setting[name];
};

Scale.prototype.contain = function (val) {
    var extent = this._extent;
    return val >= extent[0] && val <= extent[1];
};

/**
 * Normalize value to linear [0, 1], return 0.5 if extent span is 0
 * @param {number} val
 * @return {number}
 */
Scale.prototype.normalize = function (val) {
    var extent = this._extent;
    if (extent[1] === extent[0]) {
        return 0.5;
    }
    return (val - extent[0]) / (extent[1] - extent[0]);
};

/**
 * Scale normalized value
 * @param {number} val
 * @return {number}
 */
Scale.prototype.scale = function (val) {
    var extent = this._extent;
    return val * (extent[1] - extent[0]) + extent[0];
};

/**
 * Set extent from data
 * @param {Array.<number>} other
 */
Scale.prototype.unionExtent = function (other) {
    var extent = this._extent;
    other[0] < extent[0] && (extent[0] = other[0]);
    other[1] > extent[1] && (extent[1] = other[1]);
    // not setExtent because in log axis it may transformed to power
    // this.setExtent(extent[0], extent[1]);
};

/**
 * Set extent from data
 * @param {module:echarts/data/List} data
 * @param {string} dim
 */
Scale.prototype.unionExtentFromData = function (data, dim) {
    this.unionExtent(data.getApproximateExtent(dim));
};

/**
 * Get extent
 * @return {Array.<number>}
 */
Scale.prototype.getExtent = function () {
    return this._extent.slice();
};

/**
 * Set extent
 * @param {number} start
 * @param {number} end
 */
Scale.prototype.setExtent = function (start, end) {
    var thisExtent = this._extent;
    if (!isNaN(start)) {
        thisExtent[0] = start;
    }
    if (!isNaN(end)) {
        thisExtent[1] = end;
    }
};

/**
 * When axis extent depends on data and no data exists,
 * axis ticks should not be drawn, which is named 'blank'.
 */
Scale.prototype.isBlank = function () {
    return this._isBlank;
},

/**
 * When axis extent depends on data and no data exists,
 * axis ticks should not be drawn, which is named 'blank'.
 */
Scale.prototype.setBlank = function (isBlank) {
    this._isBlank = isBlank;
};

/**
 * @abstract
 * @param {*} tick
 * @return {string} label of the tick.
 */
Scale.prototype.getLabel = null;


enableClassExtend(Scale);
enableClassManagement(Scale, {
    registerWhenExtend: true
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @constructor
 * @param {Object} [opt]
 * @param {Object} [opt.categories=[]]
 * @param {Object} [opt.needCollect=false]
 * @param {Object} [opt.deduplication=false]
 */
function OrdinalMeta(opt) {

    /**
     * @readOnly
     * @type {Array.<string>}
     */
    this.categories = opt.categories || [];

    /**
     * @private
     * @type {boolean}
     */
    this._needCollect = opt.needCollect;

    /**
     * @private
     * @type {boolean}
     */
    this._deduplication = opt.deduplication;

    /**
     * @private
     * @type {boolean}
     */
    this._map;
}

/**
 * @param {module:echarts/model/Model} axisModel
 * @return {module:echarts/data/OrdinalMeta}
 */
OrdinalMeta.createByAxisModel = function (axisModel) {
    var option = axisModel.option;
    var data = option.data;
    var categories = data && map(data, getName);

    return new OrdinalMeta({
        categories: categories,
        needCollect: !categories,
        // deduplication is default in axis.
        deduplication: option.dedplication !== false
    });
};

var proto$1 = OrdinalMeta.prototype;

/**
 * @param {string} category
 * @return {number} ordinal
 */
proto$1.getOrdinal = function (category) {
    return getOrCreateMap(this).get(category);
};

/**
 * @param {*} category
 * @return {number} The ordinal. If not found, return NaN.
 */
proto$1.parseAndCollect = function (category) {
    var index;
    var needCollect = this._needCollect;

    // The value of category dim can be the index of the given category set.
    // This feature is only supported when !needCollect, because we should
    // consider a common case: a value is 2017, which is a number but is
    // expected to be tread as a category. This case usually happen in dataset,
    // where it happent to be no need of the index feature.
    if (typeof category !== 'string' && !needCollect) {
        return category;
    }

    // Optimize for the scenario:
    // category is ['2012-01-01', '2012-01-02', ...], where the input
    // data has been ensured not duplicate and is large data.
    // Notice, if a dataset dimension provide categroies, usually echarts
    // should remove duplication except user tell echarts dont do that
    // (set axis.deduplication = false), because echarts do not know whether
    // the values in the category dimension has duplication (consider the
    // parallel-aqi example)
    if (needCollect && !this._deduplication) {
        index = this.categories.length;
        this.categories[index] = category;
        return index;
    }

    var map$$1 = getOrCreateMap(this);
    index = map$$1.get(category);

    if (index == null) {
        if (needCollect) {
            index = this.categories.length;
            this.categories[index] = category;
            map$$1.set(category, index);
        }
        else {
            index = NaN;
        }
    }

    return index;
};

// Consider big data, do not create map until needed.
function getOrCreateMap(ordinalMeta) {
    return ordinalMeta._map || (
        ordinalMeta._map = createHashMap(ordinalMeta.categories)
    );
}

function getName(obj) {
    if (isObject$1(obj) && obj.value != null) {
        return obj.value;
    }
    else {
        return obj + '';
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Linear continuous scale
 * @module echarts/coord/scale/Ordinal
 *
 * http://en.wikipedia.org/wiki/Level_of_measurement
 */

// FIXME only one data

var scaleProto = Scale.prototype;

var OrdinalScale = Scale.extend({

    type: 'ordinal',

    /**
     * @param {module:echarts/data/OrdianlMeta|Array.<string>} ordinalMeta
     */
    init: function (ordinalMeta, extent) {
        // Caution: Should not use instanceof, consider ec-extensions using
        // import approach to get OrdinalMeta class.
        if (!ordinalMeta || isArray(ordinalMeta)) {
            ordinalMeta = new OrdinalMeta({categories: ordinalMeta});
        }
        this._ordinalMeta = ordinalMeta;
        this._extent = extent || [0, ordinalMeta.categories.length - 1];
    },

    parse: function (val) {
        return typeof val === 'string'
            ? this._ordinalMeta.getOrdinal(val)
            // val might be float.
            : Math.round(val);
    },

    contain: function (rank) {
        rank = this.parse(rank);
        return scaleProto.contain.call(this, rank)
            && this._ordinalMeta.categories[rank] != null;
    },

    /**
     * Normalize given rank or name to linear [0, 1]
     * @param {number|string} [val]
     * @return {number}
     */
    normalize: function (val) {
        return scaleProto.normalize.call(this, this.parse(val));
    },

    scale: function (val) {
        return Math.round(scaleProto.scale.call(this, val));
    },

    /**
     * @return {Array}
     */
    getTicks: function () {
        var ticks = [];
        var extent = this._extent;
        var rank = extent[0];

        while (rank <= extent[1]) {
            ticks.push(rank);
            rank++;
        }

        return ticks;
    },

    /**
     * Get item on rank n
     * @param {number} n
     * @return {string}
     */
    getLabel: function (n) {
        if (!this.isBlank()) {
            // Note that if no data, ordinalMeta.categories is an empty array.
            return this._ordinalMeta.categories[n];
        }
    },

    /**
     * @return {number}
     */
    count: function () {
        return this._extent[1] - this._extent[0] + 1;
    },

    /**
     * @override
     */
    unionExtentFromData: function (data, dim) {
        this.unionExtent(data.getApproximateExtent(dim));
    },

    getOrdinalMeta: function () {
        return this._ordinalMeta;
    },

    niceTicks: noop,
    niceExtent: noop
});

/**
 * @return {module:echarts/scale/Time}
 */
OrdinalScale.create = function () {
    return new OrdinalScale();
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * For testable.
 */

var roundNumber$1 = round$1;

/**
 * @param {Array.<number>} extent Both extent[0] and extent[1] should be valid number.
 *                                Should be extent[0] < extent[1].
 * @param {number} splitNumber splitNumber should be >= 1.
 * @param {number} [minInterval]
 * @param {number} [maxInterval]
 * @return {Object} {interval, intervalPrecision, niceTickExtent}
 */
function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) {
    var result = {};
    var span = extent[1] - extent[0];

    var interval = result.interval = nice(span / splitNumber, true);
    if (minInterval != null && interval < minInterval) {
        interval = result.interval = minInterval;
    }
    if (maxInterval != null && interval > maxInterval) {
        interval = result.interval = maxInterval;
    }
    // Tow more digital for tick.
    var precision = result.intervalPrecision = getIntervalPrecision(interval);
    // Niced extent inside original extent
    var niceTickExtent = result.niceTickExtent = [
        roundNumber$1(Math.ceil(extent[0] / interval) * interval, precision),
        roundNumber$1(Math.floor(extent[1] / interval) * interval, precision)
    ];

    fixExtent(niceTickExtent, extent);

    return result;
}

/**
 * @param {number} interval
 * @return {number} interval precision
 */
function getIntervalPrecision(interval) {
    // Tow more digital for tick.
    return getPrecisionSafe(interval) + 2;
}

function clamp(niceTickExtent, idx, extent) {
    niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]);
}

// In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent.
function fixExtent(niceTickExtent, extent) {
    !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]);
    !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]);
    clamp(niceTickExtent, 0, extent);
    clamp(niceTickExtent, 1, extent);
    if (niceTickExtent[0] > niceTickExtent[1]) {
        niceTickExtent[0] = niceTickExtent[1];
    }
}

function intervalScaleGetTicks(interval, extent, niceTickExtent, intervalPrecision) {
    var ticks = [];

    // If interval is 0, return [];
    if (!interval) {
        return ticks;
    }

    // Consider this case: using dataZoom toolbox, zoom and zoom.
    var safeLimit = 10000;

    if (extent[0] < niceTickExtent[0]) {
        ticks.push(extent[0]);
    }
    var tick = niceTickExtent[0];

    while (tick <= niceTickExtent[1]) {
        ticks.push(tick);
        // Avoid rounding error
        tick = roundNumber$1(tick + interval, intervalPrecision);
        if (tick === ticks[ticks.length - 1]) {
            // Consider out of safe float point, e.g.,
            // -3711126.9907707 + 2e-10 === -3711126.9907707
            break;
        }
        if (ticks.length > safeLimit) {
            return [];
        }
    }
    // Consider this case: the last item of ticks is smaller
    // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
    if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) {
        ticks.push(extent[1]);
    }

    return ticks;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Interval scale
 * @module echarts/scale/Interval
 */


var roundNumber = round$1;

/**
 * @alias module:echarts/coord/scale/Interval
 * @constructor
 */
var IntervalScale = Scale.extend({

    type: 'interval',

    _interval: 0,

    _intervalPrecision: 2,

    setExtent: function (start, end) {
        var thisExtent = this._extent;
        //start,end may be a Number like '25',so...
        if (!isNaN(start)) {
            thisExtent[0] = parseFloat(start);
        }
        if (!isNaN(end)) {
            thisExtent[1] = parseFloat(end);
        }
    },

    unionExtent: function (other) {
        var extent = this._extent;
        other[0] < extent[0] && (extent[0] = other[0]);
        other[1] > extent[1] && (extent[1] = other[1]);

        // unionExtent may called by it's sub classes
        IntervalScale.prototype.setExtent.call(this, extent[0], extent[1]);
    },
    /**
     * Get interval
     */
    getInterval: function () {
        return this._interval;
    },

    /**
     * Set interval
     */
    setInterval: function (interval) {
        this._interval = interval;
        // Dropped auto calculated niceExtent and use user setted extent
        // We assume user wan't to set both interval, min, max to get a better result
        this._niceExtent = this._extent.slice();

        this._intervalPrecision = getIntervalPrecision(interval);
    },

    /**
     * @return {Array.<number>}
     */
    getTicks: function () {
        return intervalScaleGetTicks(
            this._interval, this._extent, this._niceExtent, this._intervalPrecision
        );
    },

    /**
     * @param {number} data
     * @param {Object} [opt]
     * @param {number|string} [opt.precision] If 'auto', use nice presision.
     * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2.
     * @return {string}
     */
    getLabel: function (data, opt) {
        if (data == null) {
            return '';
        }

        var precision = opt && opt.precision;

        if (precision == null) {
            precision = getPrecisionSafe(data) || 0;
        }
        else if (precision === 'auto') {
            // Should be more precise then tick.
            precision = this._intervalPrecision;
        }

        // (1) If `precision` is set, 12.005 should be display as '12.00500'.
        // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'.
        data = roundNumber(data, precision, true);

        return addCommas(data);
    },

    /**
     * Update interval and extent of intervals for nice ticks
     *
     * @param {number} [splitNumber = 5] Desired number of ticks
     * @param {number} [minInterval]
     * @param {number} [maxInterval]
     */
    niceTicks: function (splitNumber, minInterval, maxInterval) {
        splitNumber = splitNumber || 5;
        var extent = this._extent;
        var span = extent[1] - extent[0];
        if (!isFinite(span)) {
            return;
        }
        // User may set axis min 0 and data are all negative
        // FIXME If it needs to reverse ?
        if (span < 0) {
            span = -span;
            extent.reverse();
        }

        var result = intervalScaleNiceTicks(
            extent, splitNumber, minInterval, maxInterval
        );

        this._intervalPrecision = result.intervalPrecision;
        this._interval = result.interval;
        this._niceExtent = result.niceTickExtent;
    },

    /**
     * Nice extent.
     * @param {Object} opt
     * @param {number} [opt.splitNumber = 5] Given approx tick number
     * @param {boolean} [opt.fixMin=false]
     * @param {boolean} [opt.fixMax=false]
     * @param {boolean} [opt.minInterval]
     * @param {boolean} [opt.maxInterval]
     */
    niceExtent: function (opt) {
        var extent = this._extent;
        // If extent start and end are same, expand them
        if (extent[0] === extent[1]) {
            if (extent[0] !== 0) {
                // Expand extent
                var expandSize = extent[0];
                // In the fowllowing case
                //      Axis has been fixed max 100
                //      Plus data are all 100 and axis extent are [100, 100].
                // Extend to the both side will cause expanded max is larger than fixed max.
                // So only expand to the smaller side.
                if (!opt.fixMax) {
                    extent[1] += expandSize / 2;
                    extent[0] -= expandSize / 2;
                }
                else {
                    extent[0] -= expandSize / 2;
                }
            }
            else {
                extent[1] = 1;
            }
        }
        var span = extent[1] - extent[0];
        // If there are no data and extent are [Infinity, -Infinity]
        if (!isFinite(span)) {
            extent[0] = 0;
            extent[1] = 1;
        }

        this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);

        // var extent = this._extent;
        var interval = this._interval;

        if (!opt.fixMin) {
            extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval);
        }
        if (!opt.fixMax) {
            extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval);
        }
    }
});

/**
 * @return {module:echarts/scale/Time}
 */
IntervalScale.create = function () {
    return new IntervalScale();
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float32Array */

var STACK_PREFIX = '__ec_stack_';
var LARGE_BAR_MIN_WIDTH = 0.5;

var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array;

function getSeriesStackId(seriesModel) {
    return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
}

function getAxisKey(axis) {
    return axis.dim + axis.index;
}

/**
 * @param {Object} opt
 * @param {module:echarts/coord/Axis} opt.axis Only support category axis currently.
 * @param {number} opt.count Positive interger.
 * @param {number} [opt.barWidth]
 * @param {number} [opt.barMaxWidth]
 * @param {number} [opt.barMinWidth]
 * @param {number} [opt.barGap]
 * @param {number} [opt.barCategoryGap]
 * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined.
 */
function getLayoutOnAxis(opt) {
    var params = [];
    var baseAxis = opt.axis;
    var axisKey = 'axis0';

    if (baseAxis.type !== 'category') {
        return;
    }
    var bandWidth = baseAxis.getBandWidth();

    for (var i = 0; i < opt.count || 0; i++) {
        params.push(defaults({
            bandWidth: bandWidth,
            axisKey: axisKey,
            stackId: STACK_PREFIX + i
        }, opt));
    }
    var widthAndOffsets = doCalBarWidthAndOffset(params);

    var result = [];
    for (var i = 0; i < opt.count; i++) {
        var item = widthAndOffsets[axisKey][STACK_PREFIX + i];
        item.offsetCenter = item.offset + item.width / 2;
        result.push(item);
    }

    return result;
}

function prepareLayoutBarSeries(seriesType, ecModel) {
    var seriesModels = [];
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
        // Check series coordinate, do layout for cartesian2d only
        if (isOnCartesian(seriesModel) && !isInLargeMode(seriesModel)) {
            seriesModels.push(seriesModel);
        }
    });
    return seriesModels;
}


/**
 * Map from (baseAxis.dim + '_' + baseAxis.index) to min gap of two adjacent
 * values.
 * This works for time axes, value axes, and log axes.
 * For a single time axis, return value is in the form like
 * {'x_0': [1000000]}.
 * The value of 1000000 is in milliseconds.
 */
function getValueAxesMinGaps(barSeries) {
    /**
     * Map from axis.index to values.
     * For a single time axis, axisValues is in the form like
     * {'x_0': [1495555200000, 1495641600000, 1495728000000]}.
     * Items in axisValues[x], e.g. 1495555200000, are time values of all
     * series.
     */
    var axisValues = {};
    each$1(barSeries, function (seriesModel) {
        var cartesian = seriesModel.coordinateSystem;
        var baseAxis = cartesian.getBaseAxis();
        if (baseAxis.type !== 'time' && baseAxis.type !== 'value') {
            return;
        }

        var data = seriesModel.getData();
        var key = baseAxis.dim + '_' + baseAxis.index;
        var dim = data.mapDimension(baseAxis.dim);
        for (var i = 0, cnt = data.count(); i < cnt; ++i) {
            var value = data.get(dim, i);
            if (!axisValues[key]) {
                // No previous data for the axis
                axisValues[key] = [value];
            }
            else {
                // No value in previous series
                axisValues[key].push(value);
            }
            // Ignore duplicated time values in the same axis
        }
    });

    var axisMinGaps = [];
    for (var key in axisValues) {
        if (axisValues.hasOwnProperty(key)) {
            var valuesInAxis = axisValues[key];
            if (valuesInAxis) {
                // Sort axis values into ascending order to calculate gaps
                valuesInAxis.sort(function (a, b) {
                    return a - b;
                });

                var min = null;
                for (var j = 1; j < valuesInAxis.length; ++j) {
                    var delta = valuesInAxis[j] - valuesInAxis[j - 1];
                    if (delta > 0) {
                        // Ignore 0 delta because they are of the same axis value
                        min = min === null ? delta : Math.min(min, delta);
                    }
                }
                // Set to null if only have one data
                axisMinGaps[key] = min;
            }
        }
    }
    return axisMinGaps;
}

function makeColumnLayout(barSeries) {
    var axisMinGaps = getValueAxesMinGaps(barSeries);

    var seriesInfoList = [];
    each$1(barSeries, function (seriesModel) {
        var cartesian = seriesModel.coordinateSystem;
        var baseAxis = cartesian.getBaseAxis();
        var axisExtent = baseAxis.getExtent();

        var bandWidth;
        if (baseAxis.type === 'category') {
            bandWidth = baseAxis.getBandWidth();
        }
        else if (baseAxis.type === 'value' || baseAxis.type === 'time') {
            var key = baseAxis.dim + '_' + baseAxis.index;
            var minGap = axisMinGaps[key];
            var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]);
            var scale = baseAxis.scale.getExtent();
            var scaleSpan = Math.abs(scale[1] - scale[0]);
            bandWidth = minGap
                ? extentSpan / scaleSpan * minGap
                : extentSpan; // When there is only one data value
        }
        else {
            var data = seriesModel.getData();
            bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count();
        }

        var barWidth = parsePercent$1(
            seriesModel.get('barWidth'), bandWidth
        );
        var barMaxWidth = parsePercent$1(
            seriesModel.get('barMaxWidth'), bandWidth
        );
        var barMinWidth = parsePercent$1(
            // barMinWidth by default is 1 in cartesian. Because in value axis,
            // the auto-calculated bar width might be less than 1.
            seriesModel.get('barMinWidth') || 1, bandWidth
        );
        var barGap = seriesModel.get('barGap');
        var barCategoryGap = seriesModel.get('barCategoryGap');

        seriesInfoList.push({
            bandWidth: bandWidth,
            barWidth: barWidth,
            barMaxWidth: barMaxWidth,
            barMinWidth: barMinWidth,
            barGap: barGap,
            barCategoryGap: barCategoryGap,
            axisKey: getAxisKey(baseAxis),
            stackId: getSeriesStackId(seriesModel)
        });
    });

    return doCalBarWidthAndOffset(seriesInfoList);
}

function doCalBarWidthAndOffset(seriesInfoList) {
    // Columns info on each category axis. Key is cartesian name
    var columnsMap = {};

    each$1(seriesInfoList, function (seriesInfo, idx) {
        var axisKey = seriesInfo.axisKey;
        var bandWidth = seriesInfo.bandWidth;
        var columnsOnAxis = columnsMap[axisKey] || {
            bandWidth: bandWidth,
            remainedWidth: bandWidth,
            autoWidthCount: 0,
            categoryGap: '20%',
            gap: '30%',
            stacks: {}
        };
        var stacks = columnsOnAxis.stacks;
        columnsMap[axisKey] = columnsOnAxis;

        var stackId = seriesInfo.stackId;

        if (!stacks[stackId]) {
            columnsOnAxis.autoWidthCount++;
        }
        stacks[stackId] = stacks[stackId] || {
            width: 0,
            maxWidth: 0
        };

        // Caution: In a single coordinate system, these barGrid attributes
        // will be shared by series. Consider that they have default values,
        // only the attributes set on the last series will work.
        // Do not change this fact unless there will be a break change.

        // TODO
        var barWidth = seriesInfo.barWidth;
        if (barWidth && !stacks[stackId].width) {
            // See #6312, do not restrict width.
            stacks[stackId].width = barWidth;
            barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
            columnsOnAxis.remainedWidth -= barWidth;
        }

        var barMaxWidth = seriesInfo.barMaxWidth;
        barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
        var barMinWidth = seriesInfo.barMinWidth;
        barMinWidth && (stacks[stackId].minWidth = barMinWidth);
        var barGap = seriesInfo.barGap;
        (barGap != null) && (columnsOnAxis.gap = barGap);
        var barCategoryGap = seriesInfo.barCategoryGap;
        (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap);
    });

    var result = {};

    each$1(columnsMap, function (columnsOnAxis, coordSysName) {

        result[coordSysName] = {};

        var stacks = columnsOnAxis.stacks;
        var bandWidth = columnsOnAxis.bandWidth;
        var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth);
        var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1);

        var remainedWidth = columnsOnAxis.remainedWidth;
        var autoWidthCount = columnsOnAxis.autoWidthCount;
        var autoWidth = (remainedWidth - categoryGap)
            / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
        autoWidth = Math.max(autoWidth, 0);

        // Find if any auto calculated bar exceeded maxBarWidth
        each$1(stacks, function (column) {
            var maxWidth = column.maxWidth;
            var minWidth = column.minWidth;
            if (!column.width) {
                var finalWidth = autoWidth;
                if (maxWidth && maxWidth < finalWidth) {
                    finalWidth = Math.min(maxWidth, remainedWidth);
                }
                // `minWidth` has higher priority. `minWidth` decide that wheter the
                // bar is able to be visible. So `minWidth` should not be restricted
                // by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In
                // the extreme cases for `value` axis, bars are allowed to overlap
                // with each other if `minWidth` specified.
                if (minWidth && minWidth > finalWidth) {
                    finalWidth = minWidth;
                }
                if (finalWidth !== autoWidth) {
                    column.width = finalWidth;
                    remainedWidth -= finalWidth;
                    autoWidthCount--;
                }
            }
            else {
                // `barMinWidth/barMaxWidth` has higher priority than `barWidth`, as
                // CSS does. Becuase barWidth can be a percent value, where
                // `barMaxWidth` can be used to restrict the final width.
                var finalWidth = column.width;
                if (maxWidth) {
                    finalWidth = Math.min(finalWidth, maxWidth);
                }
                // `minWidth` has higher priority, as described above
                if (minWidth) {
                    finalWidth = Math.max(finalWidth, minWidth);
                }
                column.width = finalWidth;
                remainedWidth -= finalWidth;
                autoWidthCount--;
            }
        });

        // Recalculate width again
        autoWidth = (remainedWidth - categoryGap)
            / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
        autoWidth = Math.max(autoWidth, 0);

        var widthSum = 0;
        var lastColumn;
        each$1(stacks, function (column, idx) {
            if (!column.width) {
                column.width = autoWidth;
            }
            lastColumn = column;
            widthSum += column.width * (1 + barGapPercent);
        });
        if (lastColumn) {
            widthSum -= lastColumn.width * barGapPercent;
        }

        var offset = -widthSum / 2;
        each$1(stacks, function (column, stackId) {
            result[coordSysName][stackId] = result[coordSysName][stackId] || {
                bandWidth: bandWidth,
                offset: offset,
                width: column.width
            };

            offset += column.width * (1 + barGapPercent);
        });
    });

    return result;
}

/**
 * @param {Object} barWidthAndOffset The result of makeColumnLayout
 * @param {module:echarts/coord/Axis} axis
 * @param {module:echarts/model/Series} [seriesModel] If not provided, return all.
 * @return {Object} {stackId: {offset, width}} or {offset, width} if seriesModel provided.
 */
function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) {
    if (barWidthAndOffset && axis) {
        var result = barWidthAndOffset[getAxisKey(axis)];
        if (result != null && seriesModel != null) {
            result = result[getSeriesStackId(seriesModel)];
        }
        return result;
    }
}

/**
 * @param {string} seriesType
 * @param {module:echarts/model/Global} ecModel
 */
function layout(seriesType, ecModel) {

    var seriesModels = prepareLayoutBarSeries(seriesType, ecModel);
    var barWidthAndOffset = makeColumnLayout(seriesModels);

    var lastStackCoords = {};
    each$1(seriesModels, function (seriesModel) {

        var data = seriesModel.getData();
        var cartesian = seriesModel.coordinateSystem;
        var baseAxis = cartesian.getBaseAxis();

        var stackId = getSeriesStackId(seriesModel);
        var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
        var columnOffset = columnLayoutInfo.offset;
        var columnWidth = columnLayoutInfo.width;
        var valueAxis = cartesian.getOtherAxis(baseAxis);

        var barMinHeight = seriesModel.get('barMinHeight') || 0;

        lastStackCoords[stackId] = lastStackCoords[stackId] || [];
        data.setLayout({
            bandWidth: columnLayoutInfo.bandWidth,
            offset: columnOffset,
            size: columnWidth
        });

        var valueDim = data.mapDimension(valueAxis.dim);
        var baseDim = data.mapDimension(baseAxis.dim);
        var stacked = isDimensionStacked(data, valueDim /*, baseDim*/);
        var isValueAxisH = valueAxis.isHorizontal();

        var valueAxisStart = getValueAxisStart(baseAxis, valueAxis, stacked);

        for (var idx = 0, len = data.count(); idx < len; idx++) {
            var value = data.get(valueDim, idx);
            var baseValue = data.get(baseDim, idx);

            // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
            if (isNaN(value) || isNaN(baseValue)) {
                continue;
            }

            var sign = value >= 0 ? 'p' : 'n';
            var baseCoord = valueAxisStart;

            // Because of the barMinHeight, we can not use the value in
            // stackResultDimension directly.
            if (stacked) {
                // Only ordinal axis can be stacked.
                if (!lastStackCoords[stackId][baseValue]) {
                    lastStackCoords[stackId][baseValue] = {
                        p: valueAxisStart, // Positive stack
                        n: valueAxisStart  // Negative stack
                    };
                }
                // Should also consider #4243
                baseCoord = lastStackCoords[stackId][baseValue][sign];
            }

            var x;
            var y;
            var width;
            var height;

            if (isValueAxisH) {
                var coord = cartesian.dataToPoint([value, baseValue]);
                x = baseCoord;
                y = coord[1] + columnOffset;
                width = coord[0] - valueAxisStart;
                height = columnWidth;

                if (Math.abs(width) < barMinHeight) {
                    width = (width < 0 ? -1 : 1) * barMinHeight;
                }
                stacked && (lastStackCoords[stackId][baseValue][sign] += width);
            }
            else {
                var coord = cartesian.dataToPoint([baseValue, value]);
                x = coord[0] + columnOffset;
                y = baseCoord;
                width = columnWidth;
                height = coord[1] - valueAxisStart;

                if (Math.abs(height) < barMinHeight) {
                    // Include zero to has a positive bar
                    height = (height <= 0 ? -1 : 1) * barMinHeight;
                }
                stacked && (lastStackCoords[stackId][baseValue][sign] += height);
            }
            data.setItemLayout(idx, {
                x: x,
                y: y,
                width: width,
                height: height
            });
        }

    }, this);
}

// TODO: Do not support stack in large mode yet.
var largeLayout = {

    seriesType: 'bar',

    plan: createRenderPlanner(),

    reset: function (seriesModel) {
        if (!isOnCartesian(seriesModel) || !isInLargeMode(seriesModel)) {
            return;
        }

        var data = seriesModel.getData();
        var cartesian = seriesModel.coordinateSystem;
        var baseAxis = cartesian.getBaseAxis();
        var valueAxis = cartesian.getOtherAxis(baseAxis);
        var valueDim = data.mapDimension(valueAxis.dim);
        var baseDim = data.mapDimension(baseAxis.dim);
        var valueAxisHorizontal = valueAxis.isHorizontal();
        var valueDimIdx = valueAxisHorizontal ? 0 : 1;

        var barWidth = retrieveColumnLayout(
            makeColumnLayout([seriesModel]), baseAxis, seriesModel
        ).width;
        if (!(barWidth > LARGE_BAR_MIN_WIDTH)) { // jshint ignore:line
            barWidth = LARGE_BAR_MIN_WIDTH;
        }

        return {progress: progress};

        function progress(params, data) {
            var count = params.count;
            var largePoints = new LargeArr(count * 2);
            var largeDataIndices = new LargeArr(count);
            var dataIndex;
            var coord = [];
            var valuePair = [];
            var pointsOffset = 0;
            var idxOffset = 0;

            while ((dataIndex = params.next()) != null) {
                valuePair[valueDimIdx] = data.get(valueDim, dataIndex);
                valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex);

                coord = cartesian.dataToPoint(valuePair, null, coord);
                // Data index might not be in order, depends on `progressiveChunkMode`.
                largePoints[pointsOffset++] = coord[0];
                largePoints[pointsOffset++] = coord[1];
                largeDataIndices[idxOffset++] = dataIndex;
            }

            data.setLayout({
                largePoints: largePoints,
                largeDataIndices: largeDataIndices,
                barWidth: barWidth,
                valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
                valueAxisHorizontal: valueAxisHorizontal
            });
        }
    }
};

function isOnCartesian(seriesModel) {
    return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d';
}

function isInLargeMode(seriesModel) {
    return seriesModel.pipelineContext && seriesModel.pipelineContext.large;
}

// See cases in `test/bar-start.html` and `#7412`, `#8747`.
function getValueAxisStart(baseAxis, valueAxis, stacked) {
    return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0));
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* A third-party license is embeded for some of the code in this file:
* The "scaleLevels" was originally copied from "d3.js" with some
* modifications made for this project.
* (See more details in the comment on the definition of "scaleLevels" below.)
* The use of the source code of this file is also subject to the terms
* and consitions of the license of "d3.js" (BSD-3Clause, see
* </licenses/LICENSE-d3>).
*/


// [About UTC and local time zone]:
// In most cases, `number.parseDate` will treat input data string as local time
// (except time zone is specified in time string). And `format.formateTime` returns
// local time by default. option.useUTC is false by default. This design have
// concidered these common case:
// (1) Time that is persistent in server is in UTC, but it is needed to be diplayed
// in local time by default.
// (2) By default, the input data string (e.g., '2011-01-02') should be displayed
// as its original time, without any time difference.

var intervalScaleProto = IntervalScale.prototype;

var mathCeil = Math.ceil;
var mathFloor = Math.floor;
var ONE_SECOND = 1000;
var ONE_MINUTE = ONE_SECOND * 60;
var ONE_HOUR = ONE_MINUTE * 60;
var ONE_DAY = ONE_HOUR * 24;

// FIXME 公用？
var bisect = function (a, x, lo, hi) {
    while (lo < hi) {
        var mid = lo + hi >>> 1;
        if (a[mid][1] < x) {
            lo = mid + 1;
        }
        else {
            hi = mid;
        }
    }
    return lo;
};

/**
 * @alias module:echarts/coord/scale/Time
 * @constructor
 */
var TimeScale = IntervalScale.extend({
    type: 'time',

    /**
     * @override
     */
    getLabel: function (val) {
        var stepLvl = this._stepLvl;

        var date = new Date(val);

        return formatTime(stepLvl[0], date, this.getSetting('useUTC'));
    },

    /**
     * @override
     */
    niceExtent: function (opt) {
        var extent = this._extent;
        // If extent start and end are same, expand them
        if (extent[0] === extent[1]) {
            // Expand extent
            extent[0] -= ONE_DAY;
            extent[1] += ONE_DAY;
        }
        // If there are no data and extent are [Infinity, -Infinity]
        if (extent[1] === -Infinity && extent[0] === Infinity) {
            var d = new Date();
            extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate());
            extent[0] = extent[1] - ONE_DAY;
        }

        this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);

        // var extent = this._extent;
        var interval = this._interval;

        if (!opt.fixMin) {
            extent[0] = round$1(mathFloor(extent[0] / interval) * interval);
        }
        if (!opt.fixMax) {
            extent[1] = round$1(mathCeil(extent[1] / interval) * interval);
        }
    },

    /**
     * @override
     */
    niceTicks: function (approxTickNum, minInterval, maxInterval) {
        approxTickNum = approxTickNum || 10;

        var extent = this._extent;
        var span = extent[1] - extent[0];
        var approxInterval = span / approxTickNum;

        if (minInterval != null && approxInterval < minInterval) {
            approxInterval = minInterval;
        }
        if (maxInterval != null && approxInterval > maxInterval) {
            approxInterval = maxInterval;
        }

        var scaleLevelsLen = scaleLevels.length;
        var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen);

        var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)];
        var interval = level[1];
        // Same with interval scale if span is much larger than 1 year
        if (level[0] === 'year') {
            var yearSpan = span / interval;

            // From "Nice Numbers for Graph Labels" of Graphic Gems
            // var niceYearSpan = numberUtil.nice(yearSpan, false);
            var yearStep = nice(yearSpan / approxTickNum, true);

            interval *= yearStep;
        }

        var timezoneOffset = this.getSetting('useUTC')
            ? 0 : (new Date(+extent[0] || +extent[1])).getTimezoneOffset() * 60 * 1000;
        var niceExtent = [
            Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset),
            Math.round(mathFloor((extent[1] - timezoneOffset) / interval) * interval + timezoneOffset)
        ];

        fixExtent(niceExtent, extent);

        this._stepLvl = level;
        // Interval will be used in getTicks
        this._interval = interval;
        this._niceExtent = niceExtent;
    },

    parse: function (val) {
        // val might be float.
        return +parseDate(val);
    }
});

each$1(['contain', 'normalize'], function (methodName) {
    TimeScale.prototype[methodName] = function (val) {
        return intervalScaleProto[methodName].call(this, this.parse(val));
    };
});

/**
 * This implementation was originally copied from "d3.js"
 * <https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/time/scale.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 */
var scaleLevels = [
    // Format              interval
    ['hh:mm:ss', ONE_SECOND],          // 1s
    ['hh:mm:ss', ONE_SECOND * 5],      // 5s
    ['hh:mm:ss', ONE_SECOND * 10],     // 10s
    ['hh:mm:ss', ONE_SECOND * 15],     // 15s
    ['hh:mm:ss', ONE_SECOND * 30],     // 30s
    ['hh:mm\nMM-dd', ONE_MINUTE],      // 1m
    ['hh:mm\nMM-dd', ONE_MINUTE * 5],  // 5m
    ['hh:mm\nMM-dd', ONE_MINUTE * 10], // 10m
    ['hh:mm\nMM-dd', ONE_MINUTE * 15], // 15m
    ['hh:mm\nMM-dd', ONE_MINUTE * 30], // 30m
    ['hh:mm\nMM-dd', ONE_HOUR],        // 1h
    ['hh:mm\nMM-dd', ONE_HOUR * 2],    // 2h
    ['hh:mm\nMM-dd', ONE_HOUR * 6],    // 6h
    ['hh:mm\nMM-dd', ONE_HOUR * 12],   // 12h
    ['MM-dd\nyyyy', ONE_DAY],          // 1d
    ['MM-dd\nyyyy', ONE_DAY * 2],      // 2d
    ['MM-dd\nyyyy', ONE_DAY * 3],      // 3d
    ['MM-dd\nyyyy', ONE_DAY * 4],      // 4d
    ['MM-dd\nyyyy', ONE_DAY * 5],      // 5d
    ['MM-dd\nyyyy', ONE_DAY * 6],      // 6d
    ['week', ONE_DAY * 7],             // 7d
    ['MM-dd\nyyyy', ONE_DAY * 10],     // 10d
    ['week', ONE_DAY * 14],            // 2w
    ['week', ONE_DAY * 21],            // 3w
    ['month', ONE_DAY * 31],           // 1M
    ['week', ONE_DAY * 42],            // 6w
    ['month', ONE_DAY * 62],           // 2M
    ['week', ONE_DAY * 70],            // 10w
    ['quarter', ONE_DAY * 95],         // 3M
    ['month', ONE_DAY * 31 * 4],       // 4M
    ['month', ONE_DAY * 31 * 5],       // 5M
    ['half-year', ONE_DAY * 380 / 2],  // 6M
    ['month', ONE_DAY * 31 * 8],       // 8M
    ['month', ONE_DAY * 31 * 10],      // 10M
    ['year', ONE_DAY * 380]            // 1Y
];

/**
 * @param {module:echarts/model/Model}
 * @return {module:echarts/scale/Time}
 */
TimeScale.create = function (model) {
    return new TimeScale({useUTC: model.ecModel.get('useUTC')});
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Log scale
 * @module echarts/scale/Log
 */

// Use some method of IntervalScale
var scaleProto$1 = Scale.prototype;
var intervalScaleProto$1 = IntervalScale.prototype;

var getPrecisionSafe$1 = getPrecisionSafe;
var roundingErrorFix = round$1;

var mathFloor$1 = Math.floor;
var mathCeil$1 = Math.ceil;
var mathPow$1 = Math.pow;

var mathLog = Math.log;

var LogScale = Scale.extend({

    type: 'log',

    base: 10,

    $constructor: function () {
        Scale.apply(this, arguments);
        this._originalScale = new IntervalScale();
    },

    /**
     * @return {Array.<number>}
     */
    getTicks: function () {
        var originalScale = this._originalScale;
        var extent = this._extent;
        var originalExtent = originalScale.getExtent();

        return map(intervalScaleProto$1.getTicks.call(this), function (val) {
            var powVal = round$1(mathPow$1(this.base, val));

            // Fix #4158
            powVal = (val === extent[0] && originalScale.__fixMin)
                ? fixRoundingError(powVal, originalExtent[0])
                : powVal;
            powVal = (val === extent[1] && originalScale.__fixMax)
                ? fixRoundingError(powVal, originalExtent[1])
                : powVal;

            return powVal;
        }, this);
    },

    /**
     * @param {number} val
     * @return {string}
     */
    getLabel: intervalScaleProto$1.getLabel,

    /**
     * @param  {number} val
     * @return {number}
     */
    scale: function (val) {
        val = scaleProto$1.scale.call(this, val);
        return mathPow$1(this.base, val);
    },

    /**
     * @param {number} start
     * @param {number} end
     */
    setExtent: function (start, end) {
        var base = this.base;
        start = mathLog(start) / mathLog(base);
        end = mathLog(end) / mathLog(base);
        intervalScaleProto$1.setExtent.call(this, start, end);
    },

    /**
     * @return {number} end
     */
    getExtent: function () {
        var base = this.base;
        var extent = scaleProto$1.getExtent.call(this);
        extent[0] = mathPow$1(base, extent[0]);
        extent[1] = mathPow$1(base, extent[1]);

        // Fix #4158
        var originalScale = this._originalScale;
        var originalExtent = originalScale.getExtent();
        originalScale.__fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0]));
        originalScale.__fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1]));

        return extent;
    },

    /**
     * @param  {Array.<number>} extent
     */
    unionExtent: function (extent) {
        this._originalScale.unionExtent(extent);

        var base = this.base;
        extent[0] = mathLog(extent[0]) / mathLog(base);
        extent[1] = mathLog(extent[1]) / mathLog(base);
        scaleProto$1.unionExtent.call(this, extent);
    },

    /**
     * @override
     */
    unionExtentFromData: function (data, dim) {
        // TODO
        // filter value that <= 0
        this.unionExtent(data.getApproximateExtent(dim));
    },

    /**
     * Update interval and extent of intervals for nice ticks
     * @param  {number} [approxTickNum = 10] Given approx tick number
     */
    niceTicks: function (approxTickNum) {
        approxTickNum = approxTickNum || 10;
        var extent = this._extent;
        var span = extent[1] - extent[0];
        if (span === Infinity || span <= 0) {
            return;
        }

        var interval = quantity(span);
        var err = approxTickNum / span * interval;

        // Filter ticks to get closer to the desired count.
        if (err <= 0.5) {
            interval *= 10;
        }

        // Interval should be integer
        while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) {
            interval *= 10;
        }

        var niceExtent = [
            round$1(mathCeil$1(extent[0] / interval) * interval),
            round$1(mathFloor$1(extent[1] / interval) * interval)
        ];

        this._interval = interval;
        this._niceExtent = niceExtent;
    },

    /**
     * Nice extent.
     * @override
     */
    niceExtent: function (opt) {
        intervalScaleProto$1.niceExtent.call(this, opt);

        var originalScale = this._originalScale;
        originalScale.__fixMin = opt.fixMin;
        originalScale.__fixMax = opt.fixMax;
    }

});

each$1(['contain', 'normalize'], function (methodName) {
    LogScale.prototype[methodName] = function (val) {
        val = mathLog(val) / mathLog(this.base);
        return scaleProto$1[methodName].call(this, val);
    };
});

LogScale.create = function () {
    return new LogScale();
};

function fixRoundingError(val, originalVal) {
    return roundingErrorFix(val, getPrecisionSafe$1(originalVal));
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Get axis scale extent before niced.
 * Item of returned array can only be number (including Infinity and NaN).
 */
function getScaleExtent(scale, model) {
    var scaleType = scale.type;

    var min = model.getMin();
    var max = model.getMax();
    var fixMin = min != null;
    var fixMax = max != null;
    var originalExtent = scale.getExtent();

    var axisDataLen;
    var boundaryGap;
    var span;
    if (scaleType === 'ordinal') {
        axisDataLen = model.getCategories().length;
    }
    else {
        boundaryGap = model.get('boundaryGap');
        if (!isArray(boundaryGap)) {
            boundaryGap = [boundaryGap || 0, boundaryGap || 0];
        }
        if (typeof boundaryGap[0] === 'boolean') {
            if (__DEV__) {
                console.warn('Boolean type for boundaryGap is only '
                    + 'allowed for ordinal axis. Please use string in '
                    + 'percentage instead, e.g., "20%". Currently, '
                    + 'boundaryGap is set to be 0.');
            }
            boundaryGap = [0, 0];
        }
        boundaryGap[0] = parsePercent$1(boundaryGap[0], 1);
        boundaryGap[1] = parsePercent$1(boundaryGap[1], 1);
        span = (originalExtent[1] - originalExtent[0])
            || Math.abs(originalExtent[0]);
    }

    // Notice: When min/max is not set (that is, when there are null/undefined,
    // which is the most common case), these cases should be ensured:
    // (1) For 'ordinal', show all axis.data.
    // (2) For others:
    //      + `boundaryGap` is applied (if min/max set, boundaryGap is
    //      disabled).
    //      + If `needCrossZero`, min/max should be zero, otherwise, min/max should
    //      be the result that originalExtent enlarged by boundaryGap.
    // (3) If no data, it should be ensured that `scale.setBlank` is set.

    // FIXME
    // (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used?
    // (2) When `needCrossZero` and all data is positive/negative, should it be ensured
    // that the results processed by boundaryGap are positive/negative?

    if (min == null) {
        min = scaleType === 'ordinal'
            ? (axisDataLen ? 0 : NaN)
            : originalExtent[0] - boundaryGap[0] * span;
    }
    if (max == null) {
        max = scaleType === 'ordinal'
            ? (axisDataLen ? axisDataLen - 1 : NaN)
            : originalExtent[1] + boundaryGap[1] * span;
    }

    if (min === 'dataMin') {
        min = originalExtent[0];
    }
    else if (typeof min === 'function') {
        min = min({
            min: originalExtent[0],
            max: originalExtent[1]
        });
    }

    if (max === 'dataMax') {
        max = originalExtent[1];
    }
    else if (typeof max === 'function') {
        max = max({
            min: originalExtent[0],
            max: originalExtent[1]
        });
    }

    (min == null || !isFinite(min)) && (min = NaN);
    (max == null || !isFinite(max)) && (max = NaN);

    scale.setBlank(
        eqNaN(min)
        || eqNaN(max)
        || (scaleType === 'ordinal' && !scale.getOrdinalMeta().categories.length)
    );

    // Evaluate if axis needs cross zero
    if (model.getNeedCrossZero()) {
        // Axis is over zero and min is not set
        if (min > 0 && max > 0 && !fixMin) {
            min = 0;
        }
        // Axis is under zero and max is not set
        if (min < 0 && max < 0 && !fixMax) {
            max = 0;
        }
    }

    // If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis
    // is base axis
    // FIXME
    // (1) Consider support value axis, where below zero and axis `onZero` should be handled properly.
    // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent?
    //     Should not depend on series type `bar`?
    // (3) Fix that might overlap when using dataZoom.
    // (4) Consider other chart types using `barGrid`?
    // See #6728, #4862, `test/bar-overflow-time-plot.html`
    var ecModel = model.ecModel;
    if (ecModel && (scaleType === 'time' /*|| scaleType === 'interval' */)) {
        var barSeriesModels = prepareLayoutBarSeries('bar', ecModel);
        var isBaseAxisAndHasBarSeries;

        each$1(barSeriesModels, function (seriesModel) {
            isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis;
        });

        if (isBaseAxisAndHasBarSeries) {
            // Calculate placement of bars on axis
            var barWidthAndOffset = makeColumnLayout(barSeriesModels);

            // Adjust axis min and max to account for overflow
            var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset);
            min = adjustedScale.min;
            max = adjustedScale.max;
        }
    }

    return [min, max];
}

function adjustScaleForOverflow(min, max, model, barWidthAndOffset) {

    // Get Axis Length
    var axisExtent = model.axis.getExtent();
    var axisLength = axisExtent[1] - axisExtent[0];

    // Get bars on current base axis and calculate min and max overflow
    var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis);
    if (barsOnCurrentAxis === undefined) {
        return {min: min, max: max};
    }

    var minOverflow = Infinity;
    each$1(barsOnCurrentAxis, function (item) {
        minOverflow = Math.min(item.offset, minOverflow);
    });
    var maxOverflow = -Infinity;
    each$1(barsOnCurrentAxis, function (item) {
        maxOverflow = Math.max(item.offset + item.width, maxOverflow);
    });
    minOverflow = Math.abs(minOverflow);
    maxOverflow = Math.abs(maxOverflow);
    var totalOverFlow = minOverflow + maxOverflow;

    // Calulate required buffer based on old range and overflow
    var oldRange = max - min;
    var oldRangePercentOfNew = (1 - (minOverflow + maxOverflow) / axisLength);
    var overflowBuffer = ((oldRange / oldRangePercentOfNew) - oldRange);

    max += overflowBuffer * (maxOverflow / totalOverFlow);
    min -= overflowBuffer * (minOverflow / totalOverFlow);

    return {min: min, max: max};
}

function niceScaleExtent(scale, model) {
    var extent = getScaleExtent(scale, model);
    var fixMin = model.getMin() != null;
    var fixMax = model.getMax() != null;
    var splitNumber = model.get('splitNumber');

    if (scale.type === 'log') {
        scale.base = model.get('logBase');
    }

    var scaleType = scale.type;
    scale.setExtent(extent[0], extent[1]);
    scale.niceExtent({
        splitNumber: splitNumber,
        fixMin: fixMin,
        fixMax: fixMax,
        minInterval: (scaleType === 'interval' || scaleType === 'time')
            ? model.get('minInterval') : null,
        maxInterval: (scaleType === 'interval' || scaleType === 'time')
            ? model.get('maxInterval') : null
    });

    // If some one specified the min, max. And the default calculated interval
    // is not good enough. He can specify the interval. It is often appeared
    // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard
    // to be 60.
    // FIXME
    var interval = model.get('interval');
    if (interval != null) {
        scale.setInterval && scale.setInterval(interval);
    }
}

/**
 * @param {module:echarts/model/Model} model
 * @param {string} [axisType] Default retrieve from model.type
 * @return {module:echarts/scale/*}
 */
function createScaleByModel(model, axisType) {
    axisType = axisType || model.get('type');
    if (axisType) {
        switch (axisType) {
            // Buildin scale
            case 'category':
                return new OrdinalScale(
                    model.getOrdinalMeta
                        ? model.getOrdinalMeta()
                        : model.getCategories(),
                    [Infinity, -Infinity]
                );
            case 'value':
                return new IntervalScale();
            // Extended scale, like time and log
            default:
                return (Scale.getClass(axisType) || IntervalScale).create(model);
        }
    }
}

/**
 * Check if the axis corss 0
 */
function ifAxisCrossZero(axis) {
    var dataExtent = axis.scale.getExtent();
    var min = dataExtent[0];
    var max = dataExtent[1];
    return !((min > 0 && max > 0) || (min < 0 && max < 0));
}

/**
 * @param {module:echarts/coord/Axis} axis
 * @return {Function} Label formatter function.
 *         param: {number} tickValue,
 *         param: {number} idx, the index in all ticks.
 *                         If category axis, this param is not requied.
 *         return: {string} label string.
 */
function makeLabelFormatter(axis) {
    var labelFormatter = axis.getLabelModel().get('formatter');
    var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null;

    if (typeof labelFormatter === 'string') {
        labelFormatter = (function (tpl) {
            return function (val) {
                // For category axis, get raw value; for numeric axis,
                // get foramtted label like '1,333,444'.
                val = axis.scale.getLabel(val);
                return tpl.replace('{value}', val != null ? val : '');
            };
        })(labelFormatter);
        // Consider empty array
        return labelFormatter;
    }
    else if (typeof labelFormatter === 'function') {
        return function (tickValue, idx) {
            // The original intention of `idx` is "the index of the tick in all ticks".
            // But the previous implementation of category axis do not consider the
            // `axisLabel.interval`, which cause that, for example, the `interval` is
            // `1`, then the ticks "name5", "name7", "name9" are displayed, where the
            // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep
            // the definition here for back compatibility.
            if (categoryTickStart != null) {
                idx = tickValue - categoryTickStart;
            }
            return labelFormatter(getAxisRawValue(axis, tickValue), idx);
        };
    }
    else {
        return function (tick) {
            return axis.scale.getLabel(tick);
        };
    }
}

function getAxisRawValue(axis, value) {
    // In category axis with data zoom, tick is not the original
    // index of axis.data. So tick should not be exposed to user
    // in category axis.
    return axis.type === 'category' ? axis.scale.getLabel(value) : value;
}

/**
 * @param {module:echarts/coord/Axis} axis
 * @return {module:zrender/core/BoundingRect} Be null/undefined if no labels.
 */
function estimateLabelUnionRect(axis) {
    var axisModel = axis.model;
    var scale = axis.scale;

    if (!axisModel.get('axisLabel.show') || scale.isBlank()) {
        return;
    }

    var isCategory = axis.type === 'category';

    var realNumberScaleTicks;
    var tickCount;
    var categoryScaleExtent = scale.getExtent();

    // Optimize for large category data, avoid call `getTicks()`.
    if (isCategory) {
        tickCount = scale.count();
    }
    else {
        realNumberScaleTicks = scale.getTicks();
        tickCount = realNumberScaleTicks.length;
    }

    var axisLabelModel = axis.getLabelModel();
    var labelFormatter = makeLabelFormatter(axis);

    var rect;
    var step = 1;
    // Simple optimization for large amount of labels
    if (tickCount > 40) {
        step = Math.ceil(tickCount / 40);
    }
    for (var i = 0; i < tickCount; i += step) {
        var tickValue = realNumberScaleTicks ? realNumberScaleTicks[i] : categoryScaleExtent[0] + i;
        var label = labelFormatter(tickValue);
        var unrotatedSingleRect = axisLabelModel.getTextRect(label);
        var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0);

        rect ? rect.union(singleRect) : (rect = singleRect);
    }

    return rect;
}

function rotateTextRect(textRect, rotate) {
    var rotateRadians = rotate * Math.PI / 180;
    var boundingBox = textRect.plain();
    var beforeWidth = boundingBox.width;
    var beforeHeight = boundingBox.height;
    var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
    var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
    var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);

    return rotatedRect;
}

/**
 * @param {module:echarts/src/model/Model} model axisLabelModel or axisTickModel
 * @return {number|String} Can be null|'auto'|number|function
 */
function getOptionCategoryInterval(model) {
    var interval = model.get('interval');
    return interval == null ? 'auto' : interval;
}

/**
 * Set `categoryInterval` as 0 implicitly indicates that
 * show all labels reguardless of overlap.
 * @param {Object} axis axisModel.axis
 * @return {boolean}
 */
function shouldShowAllLabels(axis) {
    return axis.type === 'category'
        && getOptionCategoryInterval(axis.getLabelModel()) === 0;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// import * as axisHelper from './axisHelper';

var axisModelCommonMixin = {

    /**
     * @param {boolean} origin
     * @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN
     */
    getMin: function (origin) {
        var option = this.option;
        var min = (!origin && option.rangeStart != null)
            ? option.rangeStart : option.min;

        if (this.axis
            && min != null
            && min !== 'dataMin'
            && typeof min !== 'function'
            && !eqNaN(min)
        ) {
            min = this.axis.scale.parse(min);
        }
        return min;
    },

    /**
     * @param {boolean} origin
     * @return {number|string} max value or 'dataMax' or null/undefined (means auto) or NaN
     */
    getMax: function (origin) {
        var option = this.option;
        var max = (!origin && option.rangeEnd != null)
            ? option.rangeEnd : option.max;

        if (this.axis
            && max != null
            && max !== 'dataMax'
            && typeof max !== 'function'
            && !eqNaN(max)
        ) {
            max = this.axis.scale.parse(max);
        }
        return max;
    },

    /**
     * @return {boolean}
     */
    getNeedCrossZero: function () {
        var option = this.option;
        return (option.rangeStart != null || option.rangeEnd != null)
            ? false : !option.scale;
    },

    /**
     * Should be implemented by each axis model if necessary.
     * @return {module:echarts/model/Component} coordinate system model
     */
    getCoordSysModel: noop,

    /**
     * @param {number} rangeStart Can only be finite number or null/undefined or NaN.
     * @param {number} rangeEnd Can only be finite number or null/undefined or NaN.
     */
    setRange: function (rangeStart, rangeEnd) {
        this.option.rangeStart = rangeStart;
        this.option.rangeEnd = rangeEnd;
    },

    /**
     * Reset range
     */
    resetRange: function () {
        // rangeStart and rangeEnd is readonly.
        this.option.rangeStart = this.option.rangeEnd = null;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Symbol factory

/**
 * Triangle shape
 * @inner
 */
var Triangle = extendShape({
    type: 'triangle',
    shape: {
        cx: 0,
        cy: 0,
        width: 0,
        height: 0
    },
    buildPath: function (path, shape) {
        var cx = shape.cx;
        var cy = shape.cy;
        var width = shape.width / 2;
        var height = shape.height / 2;
        path.moveTo(cx, cy - height);
        path.lineTo(cx + width, cy + height);
        path.lineTo(cx - width, cy + height);
        path.closePath();
    }
});

/**
 * Diamond shape
 * @inner
 */
var Diamond = extendShape({
    type: 'diamond',
    shape: {
        cx: 0,
        cy: 0,
        width: 0,
        height: 0
    },
    buildPath: function (path, shape) {
        var cx = shape.cx;
        var cy = shape.cy;
        var width = shape.width / 2;
        var height = shape.height / 2;
        path.moveTo(cx, cy - height);
        path.lineTo(cx + width, cy);
        path.lineTo(cx, cy + height);
        path.lineTo(cx - width, cy);
        path.closePath();
    }
});

/**
 * Pin shape
 * @inner
 */
var Pin = extendShape({
    type: 'pin',
    shape: {
        // x, y on the cusp
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },

    buildPath: function (path, shape) {
        var x = shape.x;
        var y = shape.y;
        var w = shape.width / 5 * 3;
        // Height must be larger than width
        var h = Math.max(w, shape.height);
        var r = w / 2;

        // Dist on y with tangent point and circle center
        var dy = r * r / (h - r);
        var cy = y - h + r + dy;
        var angle = Math.asin(dy / r);
        // Dist on x with tangent point and circle center
        var dx = Math.cos(angle) * r;

        var tanX = Math.sin(angle);
        var tanY = Math.cos(angle);

        var cpLen = r * 0.6;
        var cpLen2 = r * 0.7;

        path.moveTo(x - dx, cy + dy);

        path.arc(
            x, cy, r,
            Math.PI - angle,
            Math.PI * 2 + angle
        );
        path.bezierCurveTo(
            x + dx - tanX * cpLen, cy + dy + tanY * cpLen,
            x, y - cpLen2,
            x, y
        );
        path.bezierCurveTo(
            x, y - cpLen2,
            x - dx + tanX * cpLen, cy + dy + tanY * cpLen,
            x - dx, cy + dy
        );
        path.closePath();
    }
});

/**
 * Arrow shape
 * @inner
 */
var Arrow = extendShape({

    type: 'arrow',

    shape: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },

    buildPath: function (ctx, shape) {
        var height = shape.height;
        var width = shape.width;
        var x = shape.x;
        var y = shape.y;
        var dx = width / 3 * 2;
        ctx.moveTo(x, y);
        ctx.lineTo(x + dx, y + height);
        ctx.lineTo(x, y + height / 4 * 3);
        ctx.lineTo(x - dx, y + height);
        ctx.lineTo(x, y);
        ctx.closePath();
    }
});

/**
 * Map of path contructors
 * @type {Object.<string, module:zrender/graphic/Path>}
 */
var symbolCtors = {

    line: Line,

    rect: Rect,

    roundRect: Rect,

    square: Rect,

    circle: Circle,

    diamond: Diamond,

    pin: Pin,

    arrow: Arrow,

    triangle: Triangle
};

var symbolShapeMakers = {

    line: function (x, y, w, h, shape) {
        // FIXME
        shape.x1 = x;
        shape.y1 = y + h / 2;
        shape.x2 = x + w;
        shape.y2 = y + h / 2;
    },

    rect: function (x, y, w, h, shape) {
        shape.x = x;
        shape.y = y;
        shape.width = w;
        shape.height = h;
    },

    roundRect: function (x, y, w, h, shape) {
        shape.x = x;
        shape.y = y;
        shape.width = w;
        shape.height = h;
        shape.r = Math.min(w, h) / 4;
    },

    square: function (x, y, w, h, shape) {
        var size = Math.min(w, h);
        shape.x = x;
        shape.y = y;
        shape.width = size;
        shape.height = size;
    },

    circle: function (x, y, w, h, shape) {
        // Put circle in the center of square
        shape.cx = x + w / 2;
        shape.cy = y + h / 2;
        shape.r = Math.min(w, h) / 2;
    },

    diamond: function (x, y, w, h, shape) {
        shape.cx = x + w / 2;
        shape.cy = y + h / 2;
        shape.width = w;
        shape.height = h;
    },

    pin: function (x, y, w, h, shape) {
        shape.x = x + w / 2;
        shape.y = y + h / 2;
        shape.width = w;
        shape.height = h;
    },

    arrow: function (x, y, w, h, shape) {
        shape.x = x + w / 2;
        shape.y = y + h / 2;
        shape.width = w;
        shape.height = h;
    },

    triangle: function (x, y, w, h, shape) {
        shape.cx = x + w / 2;
        shape.cy = y + h / 2;
        shape.width = w;
        shape.height = h;
    }
};

var symbolBuildProxies = {};
each$1(symbolCtors, function (Ctor, name) {
    symbolBuildProxies[name] = new Ctor();
});

var SymbolClz = extendShape({

    type: 'symbol',

    shape: {
        symbolType: '',
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },

    calculateTextPosition: function (out, style, rect) {
        var res = calculateTextPosition(out, style, rect);
        var shape = this.shape;
        if (shape && shape.symbolType === 'pin' && style.textPosition === 'inside') {
            res.y = rect.y + rect.height * 0.4;
        }
        return res;
    },

    buildPath: function (ctx, shape, inBundle) {
        var symbolType = shape.symbolType;
        if (symbolType !== 'none') {
            var proxySymbol = symbolBuildProxies[symbolType];
            if (!proxySymbol) {
                // Default rect
                symbolType = 'rect';
                proxySymbol = symbolBuildProxies[symbolType];
            }
            symbolShapeMakers[symbolType](
                shape.x, shape.y, shape.width, shape.height, proxySymbol.shape
            );
            proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
        }
    }
});

// Provide setColor helper method to avoid determine if set the fill or stroke outside
function symbolPathSetColor(color, innerColor) {
    if (this.type !== 'image') {
        var symbolStyle = this.style;
        var symbolShape = this.shape;
        if (symbolShape && symbolShape.symbolType === 'line') {
            symbolStyle.stroke = color;
        }
        else if (this.__isEmptyBrush) {
            symbolStyle.stroke = color;
            symbolStyle.fill = innerColor || '#fff';
        }
        else {
            // FIXME 判断图形默认是填充还是描边，使用 onlyStroke ?
            symbolStyle.fill && (symbolStyle.fill = color);
            symbolStyle.stroke && (symbolStyle.stroke = color);
        }
        this.dirty(false);
    }
}

/**
 * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
 * @param {string} symbolType
 * @param {number} x
 * @param {number} y
 * @param {number} w
 * @param {number} h
 * @param {string} color
 * @param {boolean} [keepAspect=false] whether to keep the ratio of w/h,
 *                            for path and image only.
 */
function createSymbol(symbolType, x, y, w, h, color, keepAspect) {
    // TODO Support image object, DynamicImage.

    var isEmpty = symbolType.indexOf('empty') === 0;
    if (isEmpty) {
        symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
    }
    var symbolPath;

    if (symbolType.indexOf('image://') === 0) {
        symbolPath = makeImage(
            symbolType.slice(8),
            new BoundingRect(x, y, w, h),
            keepAspect ? 'center' : 'cover'
        );
    }
    else if (symbolType.indexOf('path://') === 0) {
        symbolPath = makePath(
            symbolType.slice(7),
            {},
            new BoundingRect(x, y, w, h),
            keepAspect ? 'center' : 'cover'
        );
    }
    else {
        symbolPath = new SymbolClz({
            shape: {
                symbolType: symbolType,
                x: x,
                y: y,
                width: w,
                height: h
            }
        });
    }

    symbolPath.__isEmptyBrush = isEmpty;

    symbolPath.setColor = symbolPathSetColor;

    symbolPath.setColor(color);

    return symbolPath;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// import createGraphFromNodeEdge from './chart/helper/createGraphFromNodeEdge';
/**
 * Create a muti dimension List structure from seriesModel.
 * @param  {module:echarts/model/Model} seriesModel
 * @return {module:echarts/data/List} list
 */
function createList(seriesModel) {
    return createListFromArray(seriesModel.getSource(), seriesModel);
}

var dataStack$1 = {
    isDimensionStacked: isDimensionStacked,
    enableDataStack: enableDataStack,
    getStackedDimension: getStackedDimension
};

/**
 * Create scale
 * @param {Array.<number>} dataExtent
 * @param {Object|module:echarts/Model} option
 */
function createScale(dataExtent, option) {
    var axisModel = option;
    if (!Model.isInstance(option)) {
        axisModel = new Model(option);
        mixin(axisModel, axisModelCommonMixin);
    }

    var scale = createScaleByModel(axisModel);
    scale.setExtent(dataExtent[0], dataExtent[1]);

    niceScaleExtent(scale, axisModel);
    return scale;
}

/**
 * Mixin common methods to axis model,
 *
 * Inlcude methods
 * `getFormattedLabels() => Array.<string>`
 * `getCategories() => Array.<string>`
 * `getMin(origin: boolean) => number`
 * `getMax(origin: boolean) => number`
 * `getNeedCrossZero() => boolean`
 * `setRange(start: number, end: number)`
 * `resetRange()`
 */
function mixinAxisModelCommonMethods(Model$$1) {
    mixin(Model$$1, axisModelCommonMixin);
}

var helper = (Object.freeze || Object)({
	createList: createList,
	getLayoutRect: getLayoutRect,
	dataStack: dataStack$1,
	createScale: createScale,
	mixinAxisModelCommonMethods: mixinAxisModelCommonMethods,
	completeDimensions: completeDimensions,
	createDimensions: createDimensions,
	createSymbol: createSymbol
});

var EPSILON$3 = 1e-8;

function isAroundEqual$1(a, b) {
    return Math.abs(a - b) < EPSILON$3;
}

function contain$1(points, x, y) {
    var w = 0;
    var p = points[0];

    if (!p) {
        return false;
    }

    for (var i = 1; i < points.length; i++) {
        var p2 = points[i];
        w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
        p = p2;
    }

    // Close polygon
    var p0 = points[0];
    if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
        w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
    }

    return w !== 0;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/coord/geo/Region
 */

/**
 * @param {string|Region} name
 * @param {Array} geometries
 * @param {Array.<number>} cp
 */
function Region(name, geometries, cp) {

    /**
     * @type {string}
     * @readOnly
     */
    this.name = name;

    /**
     * @type {Array.<Array>}
     * @readOnly
     */
    this.geometries = geometries;

    if (!cp) {
        var rect = this.getBoundingRect();
        cp = [
            rect.x + rect.width / 2,
            rect.y + rect.height / 2
        ];
    }
    else {
        cp = [cp[0], cp[1]];
    }
    /**
     * @type {Array.<number>}
     */
    this.center = cp;
}

Region.prototype = {

    constructor: Region,

    properties: null,

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getBoundingRect: function () {
        var rect = this._rect;
        if (rect) {
            return rect;
        }

        var MAX_NUMBER = Number.MAX_VALUE;
        var min$$1 = [MAX_NUMBER, MAX_NUMBER];
        var max$$1 = [-MAX_NUMBER, -MAX_NUMBER];
        var min2 = [];
        var max2 = [];
        var geometries = this.geometries;
        for (var i = 0; i < geometries.length; i++) {
            // Only support polygon
            if (geometries[i].type !== 'polygon') {
                continue;
            }
            // Doesn't consider hole
            var exterior = geometries[i].exterior;
            fromPoints(exterior, min2, max2);
            min(min$$1, min$$1, min2);
            max(max$$1, max$$1, max2);
        }
        // No data
        if (i === 0) {
            min$$1[0] = min$$1[1] = max$$1[0] = max$$1[1] = 0;
        }

        return (this._rect = new BoundingRect(
            min$$1[0], min$$1[1], max$$1[0] - min$$1[0], max$$1[1] - min$$1[1]
        ));
    },

    /**
     * @param {<Array.<number>} coord
     * @return {boolean}
     */
    contain: function (coord) {
        var rect = this.getBoundingRect();
        var geometries = this.geometries;
        if (!rect.contain(coord[0], coord[1])) {
            return false;
        }
        loopGeo: for (var i = 0, len$$1 = geometries.length; i < len$$1; i++) {
            // Only support polygon.
            if (geometries[i].type !== 'polygon') {
                continue;
            }
            var exterior = geometries[i].exterior;
            var interiors = geometries[i].interiors;
            if (contain$1(exterior, coord[0], coord[1])) {
                // Not in the region if point is in the hole.
                for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
                    if (contain$1(interiors[k])) {
                        continue loopGeo;
                    }
                }
                return true;
            }
        }
        return false;
    },

    transformTo: function (x, y, width, height) {
        var rect = this.getBoundingRect();
        var aspect = rect.width / rect.height;
        if (!width) {
            width = aspect * height;
        }
        else if (!height) {
            height = width / aspect;
        }
        var target = new BoundingRect(x, y, width, height);
        var transform = rect.calculateTransform(target);
        var geometries = this.geometries;
        for (var i = 0; i < geometries.length; i++) {
            // Only support polygon.
            if (geometries[i].type !== 'polygon') {
                continue;
            }
            var exterior = geometries[i].exterior;
            var interiors = geometries[i].interiors;
            for (var p = 0; p < exterior.length; p++) {
                applyTransform(exterior[p], exterior[p], transform);
            }
            for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
                for (var p = 0; p < interiors[h].length; p++) {
                    applyTransform(interiors[h][p], interiors[h][p], transform);
                }
            }
        }
        rect = this._rect;
        rect.copy(target);
        // Update center
        this.center = [
            rect.x + rect.width / 2,
            rect.y + rect.height / 2
        ];
    },

    cloneShallow: function (name) {
        name == null && (name = this.name);
        var newRegion = new Region(name, this.geometries, this.center);
        newRegion._rect = this._rect;
        newRegion.transformTo = null; // Simply avoid to be called.
        return newRegion;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Parse and decode geo json
 * @module echarts/coord/geo/parseGeoJson
 */

function decode(json) {
    if (!json.UTF8Encoding) {
        return json;
    }
    var encodeScale = json.UTF8Scale;
    if (encodeScale == null) {
        encodeScale = 1024;
    }

    var features = json.features;

    for (var f = 0; f < features.length; f++) {
        var feature = features[f];
        var geometry = feature.geometry;
        var coordinates = geometry.coordinates;
        var encodeOffsets = geometry.encodeOffsets;

        for (var c = 0; c < coordinates.length; c++) {
            var coordinate = coordinates[c];

            if (geometry.type === 'Polygon') {
                coordinates[c] = decodePolygon(
                    coordinate,
                    encodeOffsets[c],
                    encodeScale
                );
            }
            else if (geometry.type === 'MultiPolygon') {
                for (var c2 = 0; c2 < coordinate.length; c2++) {
                    var polygon = coordinate[c2];
                    coordinate[c2] = decodePolygon(
                        polygon,
                        encodeOffsets[c][c2],
                        encodeScale
                    );
                }
            }
        }
    }
    // Has been decoded
    json.UTF8Encoding = false;
    return json;
}

function decodePolygon(coordinate, encodeOffsets, encodeScale) {
    var result = [];
    var prevX = encodeOffsets[0];
    var prevY = encodeOffsets[1];

    for (var i = 0; i < coordinate.length; i += 2) {
        var x = coordinate.charCodeAt(i) - 64;
        var y = coordinate.charCodeAt(i + 1) - 64;
        // ZigZag decoding
        x = (x >> 1) ^ (-(x & 1));
        y = (y >> 1) ^ (-(y & 1));
        // Delta deocding
        x += prevX;
        y += prevY;

        prevX = x;
        prevY = y;
        // Dequantize
        result.push([x / encodeScale, y / encodeScale]);
    }

    return result;
}

/**
 * @alias module:echarts/coord/geo/parseGeoJson
 * @param {Object} geoJson
 * @return {module:zrender/container/Group}
 */
var parseGeoJson$1 = function (geoJson) {

    decode(geoJson);

    return map(filter(geoJson.features, function (featureObj) {
        // Output of mapshaper may have geometry null
        return featureObj.geometry
            && featureObj.properties
            && featureObj.geometry.coordinates.length > 0;
    }), function (featureObj) {
        var properties = featureObj.properties;
        var geo = featureObj.geometry;

        var coordinates = geo.coordinates;

        var geometries = [];
        if (geo.type === 'Polygon') {
            geometries.push({
                type: 'polygon',
                // According to the GeoJSON specification.
                // First must be exterior, and the rest are all interior(holes).
                exterior: coordinates[0],
                interiors: coordinates.slice(1)
            });
        }
        if (geo.type === 'MultiPolygon') {
            each$1(coordinates, function (item) {
                if (item[0]) {
                    geometries.push({
                        type: 'polygon',
                        exterior: item[0],
                        interiors: item.slice(1)
                    });
                }
            });
        }

        var region = new Region(
            properties.name,
            geometries,
            properties.cp
        );
        region.properties = properties;
        return region;
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$6 = makeInner();

/**
 * @param {module:echats/coord/Axis} axis
 * @return {Object} {
 *     labels: [{
 *         formattedLabel: string,
 *         rawLabel: string,
 *         tickValue: number
 *     }, ...],
 *     labelCategoryInterval: number
 * }
 */
function createAxisLabels(axis) {
    // Only ordinal scale support tick interval
    return axis.type === 'category'
        ? makeCategoryLabels(axis)
        : makeRealNumberLabels(axis);
}

/**
 * @param {module:echats/coord/Axis} axis
 * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea.
 * @return {Object} {
 *     ticks: Array.<number>
 *     tickCategoryInterval: number
 * }
 */
function createAxisTicks(axis, tickModel) {
    // Only ordinal scale support tick interval
    return axis.type === 'category'
        ? makeCategoryTicks(axis, tickModel)
        : {ticks: axis.scale.getTicks()};
}

function makeCategoryLabels(axis) {
    var labelModel = axis.getLabelModel();
    var result = makeCategoryLabelsActually(axis, labelModel);

    return (!labelModel.get('show') || axis.scale.isBlank())
        ? {labels: [], labelCategoryInterval: result.labelCategoryInterval}
        : result;
}

function makeCategoryLabelsActually(axis, labelModel) {
    var labelsCache = getListCache(axis, 'labels');
    var optionLabelInterval = getOptionCategoryInterval(labelModel);
    var result = listCacheGet(labelsCache, optionLabelInterval);

    if (result) {
        return result;
    }

    var labels;
    var numericLabelInterval;

    if (isFunction$1(optionLabelInterval)) {
        labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval);
    }
    else {
        numericLabelInterval = optionLabelInterval === 'auto'
            ? makeAutoCategoryInterval(axis) : optionLabelInterval;
        labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval);
    }

    // Cache to avoid calling interval function repeatly.
    return listCacheSet(labelsCache, optionLabelInterval, {
        labels: labels, labelCategoryInterval: numericLabelInterval
    });
}

function makeCategoryTicks(axis, tickModel) {
    var ticksCache = getListCache(axis, 'ticks');
    var optionTickInterval = getOptionCategoryInterval(tickModel);
    var result = listCacheGet(ticksCache, optionTickInterval);

    if (result) {
        return result;
    }

    var ticks;
    var tickCategoryInterval;

    // Optimize for the case that large category data and no label displayed,
    // we should not return all ticks.
    if (!tickModel.get('show') || axis.scale.isBlank()) {
        ticks = [];
    }

    if (isFunction$1(optionTickInterval)) {
        ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true);
    }
    // Always use label interval by default despite label show. Consider this
    // scenario, Use multiple grid with the xAxis sync, and only one xAxis shows
    // labels. `splitLine` and `axisTick` should be consistent in this case.
    else if (optionTickInterval === 'auto') {
        var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel());
        tickCategoryInterval = labelsResult.labelCategoryInterval;
        ticks = map(labelsResult.labels, function (labelItem) {
            return labelItem.tickValue;
        });
    }
    else {
        tickCategoryInterval = optionTickInterval;
        ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true);
    }

    // Cache to avoid calling interval function repeatly.
    return listCacheSet(ticksCache, optionTickInterval, {
        ticks: ticks, tickCategoryInterval: tickCategoryInterval
    });
}

function makeRealNumberLabels(axis) {
    var ticks = axis.scale.getTicks();
    var labelFormatter = makeLabelFormatter(axis);
    return {
        labels: map(ticks, function (tickValue, idx) {
            return {
                formattedLabel: labelFormatter(tickValue, idx),
                rawLabel: axis.scale.getLabel(tickValue),
                tickValue: tickValue
            };
        })
    };
}

// Large category data calculation is performence sensitive, and ticks and label
// probably be fetched by multiple times. So we cache the result.
// axis is created each time during a ec process, so we do not need to clear cache.
function getListCache(axis, prop) {
    // Because key can be funciton, and cache size always be small, we use array cache.
    return inner$6(axis)[prop] || (inner$6(axis)[prop] = []);
}

function listCacheGet(cache, key) {
    for (var i = 0; i < cache.length; i++) {
        if (cache[i].key === key) {
            return cache[i].value;
        }
    }
}

function listCacheSet(cache, key, value) {
    cache.push({key: key, value: value});
    return value;
}

function makeAutoCategoryInterval(axis) {
    var result = inner$6(axis).autoInterval;
    return result != null
        ? result
        : (inner$6(axis).autoInterval = axis.calculateCategoryInterval());
}

/**
 * Calculate interval for category axis ticks and labels.
 * To get precise result, at least one of `getRotate` and `isHorizontal`
 * should be implemented in axis.
 */
function calculateCategoryInterval(axis) {
    var params = fetchAutoCategoryIntervalCalculationParams(axis);
    var labelFormatter = makeLabelFormatter(axis);
    var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI;

    var ordinalScale = axis.scale;
    var ordinalExtent = ordinalScale.getExtent();
    // Providing this method is for optimization:
    // avoid generating a long array by `getTicks`
    // in large category data case.
    var tickCount = ordinalScale.count();

    if (ordinalExtent[1] - ordinalExtent[0] < 1) {
        return 0;
    }

    var step = 1;
    // Simple optimization. Empirical value: tick count should less than 40.
    if (tickCount > 40) {
        step = Math.max(1, Math.floor(tickCount / 40));
    }
    var tickValue = ordinalExtent[0];
    var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
    var unitW = Math.abs(unitSpan * Math.cos(rotation));
    var unitH = Math.abs(unitSpan * Math.sin(rotation));

    var maxW = 0;
    var maxH = 0;

    // Caution: Performance sensitive for large category data.
    // Consider dataZoom, we should make appropriate step to avoid O(n) loop.
    for (; tickValue <= ordinalExtent[1]; tickValue += step) {
        var width = 0;
        var height = 0;

        // Not precise, do not consider align and vertical align
        // and each distance from axis line yet.
        var rect = getBoundingRect(
            labelFormatter(tickValue), params.font, 'center', 'top'
        );
        // Magic number
        width = rect.width * 1.3;
        height = rect.height * 1.3;

        // Min size, void long loop.
        maxW = Math.max(maxW, width, 7);
        maxH = Math.max(maxH, height, 7);
    }

    var dw = maxW / unitW;
    var dh = maxH / unitH;
    // 0/0 is NaN, 1/0 is Infinity.
    isNaN(dw) && (dw = Infinity);
    isNaN(dh) && (dh = Infinity);
    var interval = Math.max(0, Math.floor(Math.min(dw, dh)));

    var cache = inner$6(axis.model);
    var axisExtent = axis.getExtent();
    var lastAutoInterval = cache.lastAutoInterval;
    var lastTickCount = cache.lastTickCount;

    // Use cache to keep interval stable while moving zoom window,
    // otherwise the calculated interval might jitter when the zoom
    // window size is close to the interval-changing size.
    // For example, if all of the axis labels are `a, b, c, d, e, f, g`.
    // The jitter will cause that sometimes the displayed labels are
    // `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1).
    if (lastAutoInterval != null
        && lastTickCount != null
        && Math.abs(lastAutoInterval - interval) <= 1
        && Math.abs(lastTickCount - tickCount) <= 1
        // Always choose the bigger one, otherwise the critical
        // point is not the same when zooming in or zooming out.
        && lastAutoInterval > interval
        // If the axis change is caused by chart resize, the cache should not
        // be used. Otherwise some hiden labels might not be shown again.
        && cache.axisExtend0 === axisExtent[0]
        && cache.axisExtend1 === axisExtent[1]
    ) {
        interval = lastAutoInterval;
    }
    // Only update cache if cache not used, otherwise the
    // changing of interval is too insensitive.
    else {
        cache.lastTickCount = tickCount;
        cache.lastAutoInterval = interval;
        cache.axisExtend0 = axisExtent[0];
        cache.axisExtend1 = axisExtent[1];
    }

    return interval;
}

function fetchAutoCategoryIntervalCalculationParams(axis) {
    var labelModel = axis.getLabelModel();
    return {
        axisRotate: axis.getRotate
            ? axis.getRotate()
            : (axis.isHorizontal && !axis.isHorizontal())
            ? 90
            : 0,
        labelRotate: labelModel.get('rotate') || 0,
        font: labelModel.getFont()
    };
}

function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) {
    var labelFormatter = makeLabelFormatter(axis);
    var ordinalScale = axis.scale;
    var ordinalExtent = ordinalScale.getExtent();
    var labelModel = axis.getLabelModel();
    var result = [];

    // TODO: axisType: ordinalTime, pick the tick from each month/day/year/...

    var step = Math.max((categoryInterval || 0) + 1, 1);
    var startTick = ordinalExtent[0];
    var tickCount = ordinalScale.count();

    // Calculate start tick based on zero if possible to keep label consistent
    // while zooming and moving while interval > 0. Otherwise the selection
    // of displayable ticks and symbols probably keep changing.
    // 3 is empirical value.
    if (startTick !== 0 && step > 1 && tickCount / step > 2) {
        startTick = Math.round(Math.ceil(startTick / step) * step);
    }

    // (1) Only add min max label here but leave overlap checking
    // to render stage, which also ensure the returned list
    // suitable for splitLine and splitArea rendering.
    // (2) Scales except category always contain min max label so
    // do not need to perform this process.
    var showAllLabel = shouldShowAllLabels(axis);
    var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel;
    var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel;

    if (includeMinLabel && startTick !== ordinalExtent[0]) {
        addItem(ordinalExtent[0]);
    }

    // Optimize: avoid generating large array by `ordinalScale.getTicks()`.
    var tickValue = startTick;
    for (; tickValue <= ordinalExtent[1]; tickValue += step) {
        addItem(tickValue);
    }

    if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) {
        addItem(ordinalExtent[1]);
    }

    function addItem(tVal) {
        result.push(onlyTick
            ? tVal
            : {
                formattedLabel: labelFormatter(tVal),
                rawLabel: ordinalScale.getLabel(tVal),
                tickValue: tVal
            }
        );
    }

    return result;
}

// When interval is function, the result `false` means ignore the tick.
// It is time consuming for large category data.
function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) {
    var ordinalScale = axis.scale;
    var labelFormatter = makeLabelFormatter(axis);
    var result = [];

    each$1(ordinalScale.getTicks(), function (tickValue) {
        var rawLabel = ordinalScale.getLabel(tickValue);
        if (categoryInterval(tickValue, rawLabel)) {
            result.push(onlyTick
                ? tickValue
                : {
                    formattedLabel: labelFormatter(tickValue),
                    rawLabel: rawLabel,
                    tickValue: tickValue
                }
            );
        }
    });

    return result;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var NORMALIZED_EXTENT = [0, 1];

/**
 * Base class of Axis.
 * @constructor
 */
var Axis = function (dim, scale, extent) {

    /**
     * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'.
     * @type {string}
     */
    this.dim = dim;

    /**
     * Axis scale
     * @type {module:echarts/coord/scale/*}
     */
    this.scale = scale;

    /**
     * @type {Array.<number>}
     * @private
     */
    this._extent = extent || [0, 0];

    /**
     * @type {boolean}
     */
    this.inverse = false;

    /**
     * Usually true when axis has a ordinal scale
     * @type {boolean}
     */
    this.onBand = false;
};

Axis.prototype = {

    constructor: Axis,

    /**
     * If axis extent contain given coord
     * @param {number} coord
     * @return {boolean}
     */
    contain: function (coord) {
        var extent = this._extent;
        var min = Math.min(extent[0], extent[1]);
        var max = Math.max(extent[0], extent[1]);
        return coord >= min && coord <= max;
    },

    /**
     * If axis extent contain given data
     * @param {number} data
     * @return {boolean}
     */
    containData: function (data) {
        return this.contain(this.dataToCoord(data));
    },

    /**
     * Get coord extent.
     * @return {Array.<number>}
     */
    getExtent: function () {
        return this._extent.slice();
    },

    /**
     * Get precision used for formatting
     * @param {Array.<number>} [dataExtent]
     * @return {number}
     */
    getPixelPrecision: function (dataExtent) {
        return getPixelPrecision(
            dataExtent || this.scale.getExtent(),
            this._extent
        );
    },

    /**
     * Set coord extent
     * @param {number} start
     * @param {number} end
     */
    setExtent: function (start, end) {
        var extent = this._extent;
        extent[0] = start;
        extent[1] = end;
    },

    /**
     * Convert data to coord. Data is the rank if it has an ordinal scale
     * @param {number} data
     * @param  {boolean} clamp
     * @return {number}
     */
    dataToCoord: function (data, clamp) {
        var extent = this._extent;
        var scale = this.scale;
        data = scale.normalize(data);

        if (this.onBand && scale.type === 'ordinal') {
            extent = extent.slice();
            fixExtentWithBands(extent, scale.count());
        }

        return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
    },

    /**
     * Convert coord to data. Data is the rank if it has an ordinal scale
     * @param {number} coord
     * @param  {boolean} clamp
     * @return {number}
     */
    coordToData: function (coord, clamp) {
        var extent = this._extent;
        var scale = this.scale;

        if (this.onBand && scale.type === 'ordinal') {
            extent = extent.slice();
            fixExtentWithBands(extent, scale.count());
        }

        var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);

        return this.scale.scale(t);
    },

    /**
     * Convert pixel point to data in axis
     * @param {Array.<number>} point
     * @param  {boolean} clamp
     * @return {number} data
     */
    pointToData: function (point, clamp) {
        // Should be implemented in derived class if necessary.
    },

    /**
     * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,
     * `axis.getTicksCoords` considers `onBand`, which is used by
     * `boundaryGap:true` of category axis and splitLine and splitArea.
     * @param {Object} [opt]
     * @param {number} [opt.tickModel=axis.model.getModel('axisTick')]
     * @param {boolean} [opt.clamp] If `true`, the first and the last
     *        tick must be at the axis end points. Otherwise, clip ticks
     *        that outside the axis extent.
     * @return {Array.<Object>} [{
     *     coord: ...,
     *     tickValue: ...
     * }, ...]
     */
    getTicksCoords: function (opt) {
        opt = opt || {};

        var tickModel = opt.tickModel || this.getTickModel();
        var result = createAxisTicks(this, tickModel);
        var ticks = result.ticks;

        var ticksCoords = map(ticks, function (tickValue) {
            return {
                coord: this.dataToCoord(tickValue),
                tickValue: tickValue
            };
        }, this);

        var alignWithLabel = tickModel.get('alignWithLabel');

        fixOnBandTicksCoords(
            this, ticksCoords, alignWithLabel, opt.clamp
        );

        return ticksCoords;
    },

    /**
     * @return {Array.<Object>} [{
     *     formattedLabel: string,
     *     rawLabel: axis.scale.getLabel(tickValue)
     *     tickValue: number
     * }, ...]
     */
    getViewLabels: function () {
        return createAxisLabels(this).labels;
    },

    /**
     * @return {module:echarts/coord/model/Model}
     */
    getLabelModel: function () {
        return this.model.getModel('axisLabel');
    },

    /**
     * Notice here we only get the default tick model. For splitLine
     * or splitArea, we should pass the splitLineModel or splitAreaModel
     * manually when calling `getTicksCoords`.
     * In GL, this method may be overrided to:
     * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));`
     * @return {module:echarts/coord/model/Model}
     */
    getTickModel: function () {
        return this.model.getModel('axisTick');
    },

    /**
     * Get width of band
     * @return {number}
     */
    getBandWidth: function () {
        var axisExtent = this._extent;
        var dataExtent = this.scale.getExtent();

        var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0);
        // Fix #2728, avoid NaN when only one data.
        len === 0 && (len = 1);

        var size = Math.abs(axisExtent[1] - axisExtent[0]);

        return Math.abs(size) / len;
    },

    /**
     * @abstract
     * @return {boolean} Is horizontal
     */
    isHorizontal: null,

    /**
     * @abstract
     * @return {number} Get axis rotate, by degree.
     */
    getRotate: null,

    /**
     * Only be called in category axis.
     * Can be overrided, consider other axes like in 3D.
     * @return {number} Auto interval for cateogry axis tick and label
     */
    calculateCategoryInterval: function () {
        return calculateCategoryInterval(this);
    }

};

function fixExtentWithBands(extent, nTick) {
    var size = extent[1] - extent[0];
    var len = nTick;
    var margin = size / len / 2;
    extent[0] += margin;
    extent[1] -= margin;
}

// If axis has labels [1, 2, 3, 4]. Bands on the axis are
// |---1---|---2---|---3---|---4---|.
// So the displayed ticks and splitLine/splitArea should between
// each data item, otherwise cause misleading (e.g., split tow bars
// of a single data item when there are two bar series).
// Also consider if tickCategoryInterval > 0 and onBand, ticks and
// splitLine/spliteArea should layout appropriately corresponding
// to displayed labels. (So we should not use `getBandWidth` in this
// case).
function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) {
    var ticksLen = ticksCoords.length;

    if (!axis.onBand || alignWithLabel || !ticksLen) {
        return;
    }

    var axisExtent = axis.getExtent();
    var last;
    var diffSize;
    if (ticksLen === 1) {
        ticksCoords[0].coord = axisExtent[0];
        last = ticksCoords[1] = {coord: axisExtent[0]};
    }
    else {
        var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
        var shift = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;

        each$1(ticksCoords, function (ticksItem) {
            ticksItem.coord -= shift / 2;
        });

        var dataExtent = axis.scale.getExtent();
        diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;

        last = {coord: ticksCoords[ticksLen - 1].coord + shift * diffSize};

        ticksCoords.push(last);
    }

    var inverse = axisExtent[0] > axisExtent[1];

    // Handling clamp.
    if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
        clamp ? (ticksCoords[0].coord = axisExtent[0]) : ticksCoords.shift();
    }
    if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) {
        ticksCoords.unshift({coord: axisExtent[0]});
    }
    if (littleThan(axisExtent[1], last.coord)) {
        clamp ? (last.coord = axisExtent[1]) : ticksCoords.pop();
    }
    if (clamp && littleThan(last.coord, axisExtent[1])) {
        ticksCoords.push({coord: axisExtent[1]});
    }

    function littleThan(a, b) {
        // Avoid rounding error cause calculated tick coord different with extent.
        // It may cause an extra unecessary tick added.
        a = round$1(a);
        b = round$1(b);
        return inverse ? a > b : a < b;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Do not mount those modules on 'src/echarts' for better tree shaking.
 */

var parseGeoJson = parseGeoJson$1;

var ecUtil = {};
each$1(
    [
        'map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter',
        'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction',
        'extend', 'defaults', 'clone', 'merge'
    ],
    function (name) {
        ecUtil[name] = zrUtil[name];
    }
);
var graphic$1 = {};
each$1(
    [
        'extendShape', 'extendPath', 'makePath', 'makeImage',
        'mergePath', 'resizePath', 'createIcon',
        'setHoverStyle', 'setLabelStyle', 'setTextStyle', 'setText',
        'getFont', 'updateProps', 'initProps', 'getTransform',
        'clipPointsByRect', 'clipRectByRect',
        'registerShape', 'getShapeClass',
        'Group',
        'Image',
        'Text',
        'Circle',
        'Sector',
        'Ring',
        'Polygon',
        'Polyline',
        'Rect',
        'Line',
        'BezierCurve',
        'Arc',
        'IncrementalDisplayable',
        'CompoundPath',
        'LinearGradient',
        'RadialGradient',
        'BoundingRect'
    ],
    function (name) {
        graphic$1[name] = graphic[name];
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.line',

    dependencies: ['grid', 'polar'],

    getInitialData: function (option, ecModel) {
        if (__DEV__) {
            var coordSys = option.coordinateSystem;
            if (coordSys !== 'polar' && coordSys !== 'cartesian2d') {
                throw new Error('Line not support coordinateSystem besides cartesian and polar');
            }
        }
        return createListFromArray(this.getSource(), this);
    },

    defaultOption: {
        zlevel: 0,
        z: 2,
        coordinateSystem: 'cartesian2d',
        legendHoverLink: true,

        hoverAnimation: true,
        // stack: null
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // polarIndex: 0,

        // If clip the overflow value
        clip: true,
        // cursor: null,

        label: {
            position: 'top'
        },
        // itemStyle: {
        // },

        lineStyle: {
            width: 2,
            type: 'solid'
        },
        // areaStyle: {
            // origin of areaStyle. Valid values:
            // `'auto'/null/undefined`: from axisLine to data
            // `'start'`: from min to data
            // `'end'`: from data to max
            // origin: 'auto'
        // },
        // false, 'start', 'end', 'middle'
        step: false,

        // Disabled if step is true
        smooth: false,
        smoothMonotone: null,
        symbol: 'emptyCircle',
        symbolSize: 4,
        symbolRotate: null,

        showSymbol: true,
        // `false`: follow the label interval strategy.
        // `true`: show all symbols.
        // `'auto'`: If possible, show all symbols, otherwise
        //           follow the label interval strategy.
        showAllSymbol: 'auto',

        // Whether to connect break point.
        connectNulls: false,

        // Sampling for large data. Can be: 'average', 'max', 'min', 'sum'.
        sampling: 'none',

        animationEasing: 'linear',

        // Disable progressive
        progressive: 0,
        hoverLayerThreshold: Infinity
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @return {string} label string. Not null/undefined
 */
function getDefaultLabel(data, dataIndex) {
    var labelDims = data.mapDimension('defaultedLabel', true);
    var len = labelDims.length;

    // Simple optimization (in lots of cases, label dims length is 1)
    if (len === 1) {
        return retrieveRawValue(data, dataIndex, labelDims[0]);
    }
    else if (len) {
        var vals = [];
        for (var i = 0; i < labelDims.length; i++) {
            var val = retrieveRawValue(data, dataIndex, labelDims[i]);
            vals.push(val);
        }
        return vals.join(' ');
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/chart/helper/Symbol
 */

/**
 * @constructor
 * @alias {module:echarts/chart/helper/Symbol}
 * @param {module:echarts/data/List} data
 * @param {number} idx
 * @extends {module:zrender/graphic/Group}
 */
function SymbolClz$1(data, idx, seriesScope) {
    Group.call(this);
    this.updateData(data, idx, seriesScope);
}

var symbolProto = SymbolClz$1.prototype;

/**
 * @public
 * @static
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @return {Array.<number>} [width, height]
 */
var getSymbolSize = SymbolClz$1.getSymbolSize = function (data, idx) {
    var symbolSize = data.getItemVisual(idx, 'symbolSize');
    return symbolSize instanceof Array
        ? symbolSize.slice()
        : [+symbolSize, +symbolSize];
};

function getScale(symbolSize) {
    return [symbolSize[0] / 2, symbolSize[1] / 2];
}

function driftSymbol(dx, dy) {
    this.parent.drift(dx, dy);
}

symbolProto._createSymbol = function (
    symbolType,
    data,
    idx,
    symbolSize,
    keepAspect
) {
    // Remove paths created before
    this.removeAll();

    var color = data.getItemVisual(idx, 'color');

    // var symbolPath = createSymbol(
    //     symbolType, -0.5, -0.5, 1, 1, color
    // );
    // If width/height are set too small (e.g., set to 1) on ios10
    // and macOS Sierra, a circle stroke become a rect, no matter what
    // the scale is set. So we set width/height as 2. See #4150.
    var symbolPath = createSymbol(
        symbolType, -1, -1, 2, 2, color, keepAspect
    );

    symbolPath.attr({
        z2: 100,
        culling: true,
        scale: getScale(symbolSize)
    });
    // Rewrite drift method
    symbolPath.drift = driftSymbol;

    this._symbolType = symbolType;

    this.add(symbolPath);
};

/**
 * Stop animation
 * @param {boolean} toLastFrame
 */
symbolProto.stopSymbolAnimation = function (toLastFrame) {
    this.childAt(0).stopAnimation(toLastFrame);
};

/**
 * FIXME:
 * Caution: This method breaks the encapsulation of this module,
 * but it indeed brings convenience. So do not use the method
 * unless you detailedly know all the implements of `Symbol`,
 * especially animation.
 *
 * Get symbol path element.
 */
symbolProto.getSymbolPath = function () {
    return this.childAt(0);
};

/**
 * Get scale(aka, current symbol size).
 * Including the change caused by animation
 */
symbolProto.getScale = function () {
    return this.childAt(0).scale;
};

/**
 * Highlight symbol
 */
symbolProto.highlight = function () {
    this.childAt(0).trigger('emphasis');
};

/**
 * Downplay symbol
 */
symbolProto.downplay = function () {
    this.childAt(0).trigger('normal');
};

/**
 * @param {number} zlevel
 * @param {number} z
 */
symbolProto.setZ = function (zlevel, z) {
    var symbolPath = this.childAt(0);
    symbolPath.zlevel = zlevel;
    symbolPath.z = z;
};

symbolProto.setDraggable = function (draggable) {
    var symbolPath = this.childAt(0);
    symbolPath.draggable = draggable;
    symbolPath.cursor = draggable ? 'move' : symbolPath.cursor;
};

/**
 * Update symbol properties
 * @param {module:echarts/data/List} data
 * @param {number} idx
 * @param {Object} [seriesScope]
 * @param {Object} [seriesScope.itemStyle]
 * @param {Object} [seriesScope.hoverItemStyle]
 * @param {Object} [seriesScope.symbolRotate]
 * @param {Object} [seriesScope.symbolOffset]
 * @param {module:echarts/model/Model} [seriesScope.labelModel]
 * @param {module:echarts/model/Model} [seriesScope.hoverLabelModel]
 * @param {boolean} [seriesScope.hoverAnimation]
 * @param {Object} [seriesScope.cursorStyle]
 * @param {module:echarts/model/Model} [seriesScope.itemModel]
 * @param {string} [seriesScope.symbolInnerColor]
 * @param {Object} [seriesScope.fadeIn=false]
 */
symbolProto.updateData = function (data, idx, seriesScope) {
    this.silent = false;

    var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
    var seriesModel = data.hostModel;
    var symbolSize = getSymbolSize(data, idx);
    var isInit = symbolType !== this._symbolType;

    if (isInit) {
        var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect');
        this._createSymbol(symbolType, data, idx, symbolSize, keepAspect);
    }
    else {
        var symbolPath = this.childAt(0);
        symbolPath.silent = false;
        updateProps(symbolPath, {
            scale: getScale(symbolSize)
        }, seriesModel, idx);
    }

    this._updateCommon(data, idx, symbolSize, seriesScope);

    if (isInit) {
        var symbolPath = this.childAt(0);
        var fadeIn = seriesScope && seriesScope.fadeIn;

        var target = {scale: symbolPath.scale.slice()};
        fadeIn && (target.style = {opacity: symbolPath.style.opacity});

        symbolPath.scale = [0, 0];
        fadeIn && (symbolPath.style.opacity = 0);

        initProps(symbolPath, target, seriesModel, idx);
    }

    this._seriesModel = seriesModel;
};

// Update common properties
var normalStyleAccessPath = ['itemStyle'];
var emphasisStyleAccessPath = ['emphasis', 'itemStyle'];
var normalLabelAccessPath = ['label'];
var emphasisLabelAccessPath = ['emphasis', 'label'];

/**
 * @param {module:echarts/data/List} data
 * @param {number} idx
 * @param {Array.<number>} symbolSize
 * @param {Object} [seriesScope]
 */
symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
    var symbolPath = this.childAt(0);
    var seriesModel = data.hostModel;
    var color = data.getItemVisual(idx, 'color');

    // Reset style
    if (symbolPath.type !== 'image') {
        symbolPath.useStyle({
            strokeNoScale: true
        });
    }
    else {
        symbolPath.setStyle({
            opacity: null,
            shadowBlur: null,
            shadowOffsetX: null,
            shadowOffsetY: null,
            shadowColor: null
        });
    }

    var itemStyle = seriesScope && seriesScope.itemStyle;
    var hoverItemStyle = seriesScope && seriesScope.hoverItemStyle;
    var symbolRotate = seriesScope && seriesScope.symbolRotate;
    var symbolOffset = seriesScope && seriesScope.symbolOffset;
    var labelModel = seriesScope && seriesScope.labelModel;
    var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel;
    var hoverAnimation = seriesScope && seriesScope.hoverAnimation;
    var cursorStyle = seriesScope && seriesScope.cursorStyle;

    if (!seriesScope || data.hasItemOption) {
        var itemModel = (seriesScope && seriesScope.itemModel)
            ? seriesScope.itemModel : data.getItemModel(idx);

        // Color must be excluded.
        // Because symbol provide setColor individually to set fill and stroke
        itemStyle = itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']);
        hoverItemStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();

        symbolRotate = itemModel.getShallow('symbolRotate');
        symbolOffset = itemModel.getShallow('symbolOffset');

        labelModel = itemModel.getModel(normalLabelAccessPath);
        hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
        hoverAnimation = itemModel.getShallow('hoverAnimation');
        cursorStyle = itemModel.getShallow('cursor');
    }
    else {
        hoverItemStyle = extend({}, hoverItemStyle);
    }

    var elStyle = symbolPath.style;

    symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);

    if (symbolOffset) {
        symbolPath.attr('position', [
            parsePercent$1(symbolOffset[0], symbolSize[0]),
            parsePercent$1(symbolOffset[1], symbolSize[1])
        ]);
    }

    cursorStyle && symbolPath.attr('cursor', cursorStyle);

    // PENDING setColor before setStyle!!!
    symbolPath.setColor(color, seriesScope && seriesScope.symbolInnerColor);

    symbolPath.setStyle(itemStyle);

    var opacity = data.getItemVisual(idx, 'opacity');
    if (opacity != null) {
        elStyle.opacity = opacity;
    }

    var liftZ = data.getItemVisual(idx, 'liftZ');
    var z2Origin = symbolPath.__z2Origin;
    if (liftZ != null) {
        if (z2Origin == null) {
            symbolPath.__z2Origin = symbolPath.z2;
            symbolPath.z2 += liftZ;
        }
    }
    else if (z2Origin != null) {
        symbolPath.z2 = z2Origin;
        symbolPath.__z2Origin = null;
    }

    var useNameLabel = seriesScope && seriesScope.useNameLabel;

    setLabelStyle(
        elStyle, hoverItemStyle, labelModel, hoverLabelModel,
        {
            labelFetcher: seriesModel,
            labelDataIndex: idx,
            defaultText: getLabelDefaultText,
            isRectText: true,
            autoColor: color
        }
    );

    // Do not execute util needed.
    function getLabelDefaultText(idx, opt) {
        return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx);
    }

    symbolPath.__symbolOriginalScale = getScale(symbolSize);
    symbolPath.hoverStyle = hoverItemStyle;
    symbolPath.highDownOnUpdate = (
        hoverAnimation && seriesModel.isAnimationEnabled()
    ) ? highDownOnUpdate : null;

    setHoverStyle(symbolPath);
};

function highDownOnUpdate(fromState, toState) {
    // Do not support this hover animation util some scenario required.
    // Animation can only be supported in hover layer when using `el.incremetal`.
    if (this.incremental || this.useHoverLayer) {
        return;
    }

    if (toState === 'emphasis') {
        var scale = this.__symbolOriginalScale;
        var ratio = scale[1] / scale[0];
        var emphasisOpt = {
            scale: [
                Math.max(scale[0] * 1.1, scale[0] + 3),
                Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)
            ]
        };
        // FIXME
        // modify it after support stop specified animation.
        // toState === fromState
        //     ? (this.stopAnimation(), this.attr(emphasisOpt))
        this.animateTo(emphasisOpt, 400, 'elasticOut');
    }
    else if (toState === 'normal') {
        this.animateTo({
            scale: this.__symbolOriginalScale
        }, 400, 'elasticOut');
    }
}

/**
 * @param {Function} cb
 * @param {Object} [opt]
 * @param {Object} [opt.keepLabel=true]
 */
symbolProto.fadeOut = function (cb, opt) {
    var symbolPath = this.childAt(0);
    // Avoid mistaken hover when fading out
    this.silent = symbolPath.silent = true;
    // Not show text when animating
    !(opt && opt.keepLabel) && (symbolPath.style.text = null);

    updateProps(
        symbolPath,
        {
            style: {opacity: 0},
            scale: [0, 0]
        },
        this._seriesModel,
        this.dataIndex,
        cb
    );
};

inherits(SymbolClz$1, Group);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/chart/helper/SymbolDraw
 */

/**
 * @constructor
 * @alias module:echarts/chart/helper/SymbolDraw
 * @param {module:zrender/graphic/Group} [symbolCtor]
 */
function SymbolDraw(symbolCtor) {
    this.group = new Group();

    this._symbolCtor = symbolCtor || SymbolClz$1;
}

var symbolDrawProto = SymbolDraw.prototype;

function symbolNeedsDraw(data, point, idx, opt) {
    return point && !isNaN(point[0]) && !isNaN(point[1])
        && !(opt.isIgnore && opt.isIgnore(idx))
        // We do not set clipShape on group, because it will cut part of
        // the symbol element shape. We use the same clip shape here as
        // the line clip.
        && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1]))
        && data.getItemVisual(idx, 'symbol') !== 'none';
}

/**
 * Update symbols draw by new data
 * @param {module:echarts/data/List} data
 * @param {Object} [opt] Or isIgnore
 * @param {Function} [opt.isIgnore]
 * @param {Object} [opt.clipShape]
 */
symbolDrawProto.updateData = function (data, opt) {
    opt = normalizeUpdateOpt(opt);

    var group = this.group;
    var seriesModel = data.hostModel;
    var oldData = this._data;
    var SymbolCtor = this._symbolCtor;

    var seriesScope = makeSeriesScope(data);

    // There is no oldLineData only when first rendering or switching from
    // stream mode to normal mode, where previous elements should be removed.
    if (!oldData) {
        group.removeAll();
    }

    data.diff(oldData)
        .add(function (newIdx) {
            var point = data.getItemLayout(newIdx);
            if (symbolNeedsDraw(data, point, newIdx, opt)) {
                var symbolEl = new SymbolCtor(data, newIdx, seriesScope);
                symbolEl.attr('position', point);
                data.setItemGraphicEl(newIdx, symbolEl);
                group.add(symbolEl);
            }
        })
        .update(function (newIdx, oldIdx) {
            var symbolEl = oldData.getItemGraphicEl(oldIdx);
            var point = data.getItemLayout(newIdx);
            if (!symbolNeedsDraw(data, point, newIdx, opt)) {
                group.remove(symbolEl);
                return;
            }
            if (!symbolEl) {
                symbolEl = new SymbolCtor(data, newIdx);
                symbolEl.attr('position', point);
            }
            else {
                symbolEl.updateData(data, newIdx, seriesScope);
                updateProps(symbolEl, {
                    position: point
                }, seriesModel);
            }

            // Add back
            group.add(symbolEl);

            data.setItemGraphicEl(newIdx, symbolEl);
        })
        .remove(function (oldIdx) {
            var el = oldData.getItemGraphicEl(oldIdx);
            el && el.fadeOut(function () {
                group.remove(el);
            });
        })
        .execute();

    this._data = data;
};

symbolDrawProto.isPersistent = function () {
    return true;
};

symbolDrawProto.updateLayout = function () {
    var data = this._data;
    if (data) {
        // Not use animation
        data.eachItemGraphicEl(function (el, idx) {
            var point = data.getItemLayout(idx);
            el.attr('position', point);
        });
    }
};

symbolDrawProto.incrementalPrepareUpdate = function (data) {
    this._seriesScope = makeSeriesScope(data);
    this._data = null;
    this.group.removeAll();
};

/**
 * Update symbols draw by new data
 * @param {module:echarts/data/List} data
 * @param {Object} [opt] Or isIgnore
 * @param {Function} [opt.isIgnore]
 * @param {Object} [opt.clipShape]
 */
symbolDrawProto.incrementalUpdate = function (taskParams, data, opt) {
    opt = normalizeUpdateOpt(opt);

    function updateIncrementalAndHover(el) {
        if (!el.isGroup) {
            el.incremental = el.useHoverLayer = true;
        }
    }
    for (var idx = taskParams.start; idx < taskParams.end; idx++) {
        var point = data.getItemLayout(idx);
        if (symbolNeedsDraw(data, point, idx, opt)) {
            var el = new this._symbolCtor(data, idx, this._seriesScope);
            el.traverse(updateIncrementalAndHover);
            el.attr('position', point);
            this.group.add(el);
            data.setItemGraphicEl(idx, el);
        }
    }
};

function normalizeUpdateOpt(opt) {
    if (opt != null && !isObject$1(opt)) {
        opt = {isIgnore: opt};
    }
    return opt || {};
}

symbolDrawProto.remove = function (enableAnimation) {
    var group = this.group;
    var data = this._data;
    // Incremental model do not have this._data.
    if (data && enableAnimation) {
        data.eachItemGraphicEl(function (el) {
            el.fadeOut(function () {
                group.remove(el);
            });
        });
    }
    else {
        group.removeAll();
    }
};

function makeSeriesScope(data) {
    var seriesModel = data.hostModel;
    return {
        itemStyle: seriesModel.getModel('itemStyle').getItemStyle(['color']),
        hoverItemStyle: seriesModel.getModel('emphasis.itemStyle').getItemStyle(),
        symbolRotate: seriesModel.get('symbolRotate'),
        symbolOffset: seriesModel.get('symbolOffset'),
        hoverAnimation: seriesModel.get('hoverAnimation'),
        labelModel: seriesModel.getModel('label'),
        hoverLabelModel: seriesModel.getModel('emphasis.label'),
        cursorStyle: seriesModel.get('cursor')
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {Object} coordSys
 * @param {module:echarts/data/List} data
 * @param {string} valueOrigin lineSeries.option.areaStyle.origin
 */
function prepareDataCoordInfo(coordSys, data, valueOrigin) {
    var baseAxis = coordSys.getBaseAxis();
    var valueAxis = coordSys.getOtherAxis(baseAxis);
    var valueStart = getValueStart(valueAxis, valueOrigin);

    var baseAxisDim = baseAxis.dim;
    var valueAxisDim = valueAxis.dim;
    var valueDim = data.mapDimension(valueAxisDim);
    var baseDim = data.mapDimension(baseAxisDim);
    var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0;

    var dims = map(coordSys.dimensions, function (coordDim) {
        return data.mapDimension(coordDim);
    });

    var stacked;
    var stackResultDim = data.getCalculationInfo('stackResultDimension');
    if (stacked |= isDimensionStacked(data, dims[0] /*, dims[1]*/)) { // jshint ignore:line
        dims[0] = stackResultDim;
    }
    if (stacked |= isDimensionStacked(data, dims[1] /*, dims[0]*/)) { // jshint ignore:line
        dims[1] = stackResultDim;
    }

    return {
        dataDimsForPoint: dims,
        valueStart: valueStart,
        valueAxisDim: valueAxisDim,
        baseAxisDim: baseAxisDim,
        stacked: !!stacked,
        valueDim: valueDim,
        baseDim: baseDim,
        baseDataOffset: baseDataOffset,
        stackedOverDimension: data.getCalculationInfo('stackedOverDimension')
    };
}

function getValueStart(valueAxis, valueOrigin) {
    var valueStart = 0;
    var extent = valueAxis.scale.getExtent();

    if (valueOrigin === 'start') {
        valueStart = extent[0];
    }
    else if (valueOrigin === 'end') {
        valueStart = extent[1];
    }
    // auto
    else {
        // Both positive
        if (extent[0] > 0) {
            valueStart = extent[0];
        }
        // Both negative
        else if (extent[1] < 0) {
            valueStart = extent[1];
        }
        // If is one positive, and one negative, onZero shall be true
    }

    return valueStart;
}

function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) {
    var value = NaN;
    if (dataCoordInfo.stacked) {
        value = data.get(data.getCalculationInfo('stackedOverDimension'), idx);
    }
    if (isNaN(value)) {
        value = dataCoordInfo.valueStart;
    }

    var baseDataOffset = dataCoordInfo.baseDataOffset;
    var stackedData = [];
    stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx);
    stackedData[1 - baseDataOffset] = value;

    return coordSys.dataToPoint(stackedData);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// var arrayDiff = require('zrender/src/core/arrayDiff');
// 'zrender/src/core/arrayDiff' has been used before, but it did
// not do well in performance when roam with fixed dataZoom window.

// function convertToIntId(newIdList, oldIdList) {
//     // Generate int id instead of string id.
//     // Compare string maybe slow in score function of arrDiff

//     // Assume id in idList are all unique
//     var idIndicesMap = {};
//     var idx = 0;
//     for (var i = 0; i < newIdList.length; i++) {
//         idIndicesMap[newIdList[i]] = idx;
//         newIdList[i] = idx++;
//     }
//     for (var i = 0; i < oldIdList.length; i++) {
//         var oldId = oldIdList[i];
//         // Same with newIdList
//         if (idIndicesMap[oldId]) {
//             oldIdList[i] = idIndicesMap[oldId];
//         }
//         else {
//             oldIdList[i] = idx++;
//         }
//     }
// }

function diffData(oldData, newData) {
    var diffResult = [];

    newData.diff(oldData)
        .add(function (idx) {
            diffResult.push({cmd: '+', idx: idx});
        })
        .update(function (newIdx, oldIdx) {
            diffResult.push({cmd: '=', idx: oldIdx, idx1: newIdx});
        })
        .remove(function (idx) {
            diffResult.push({cmd: '-', idx: idx});
        })
        .execute();

    return diffResult;
}

var lineAnimationDiff = function (
    oldData, newData,
    oldStackedOnPoints, newStackedOnPoints,
    oldCoordSys, newCoordSys,
    oldValueOrigin, newValueOrigin
) {
    var diff = diffData(oldData, newData);

    // var newIdList = newData.mapArray(newData.getId);
    // var oldIdList = oldData.mapArray(oldData.getId);

    // convertToIntId(newIdList, oldIdList);

    // // FIXME One data ?
    // diff = arrayDiff(oldIdList, newIdList);

    var currPoints = [];
    var nextPoints = [];
    // Points for stacking base line
    var currStackedPoints = [];
    var nextStackedPoints = [];

    var status = [];
    var sortedIndices = [];
    var rawIndices = [];

    var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin);
    var oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin);

    for (var i = 0; i < diff.length; i++) {
        var diffItem = diff[i];
        var pointAdded = true;

        // FIXME, animation is not so perfect when dataZoom window moves fast
        // Which is in case remvoing or add more than one data in the tail or head
        switch (diffItem.cmd) {
            case '=':
                var currentPt = oldData.getItemLayout(diffItem.idx);
                var nextPt = newData.getItemLayout(diffItem.idx1);
                // If previous data is NaN, use next point directly
                if (isNaN(currentPt[0]) || isNaN(currentPt[1])) {
                    currentPt = nextPt.slice();
                }
                currPoints.push(currentPt);
                nextPoints.push(nextPt);

                currStackedPoints.push(oldStackedOnPoints[diffItem.idx]);
                nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]);

                rawIndices.push(newData.getRawIndex(diffItem.idx1));
                break;
            case '+':
                var idx = diffItem.idx;
                currPoints.push(
                    oldCoordSys.dataToPoint([
                        newData.get(newDataOldCoordInfo.dataDimsForPoint[0], idx),
                        newData.get(newDataOldCoordInfo.dataDimsForPoint[1], idx)
                    ])
                );

                nextPoints.push(newData.getItemLayout(idx).slice());

                currStackedPoints.push(
                    getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, idx)
                );
                nextStackedPoints.push(newStackedOnPoints[idx]);

                rawIndices.push(newData.getRawIndex(idx));
                break;
            case '-':
                var idx = diffItem.idx;
                var rawIndex = oldData.getRawIndex(idx);
                // Data is replaced. In the case of dynamic data queue
                // FIXME FIXME FIXME
                if (rawIndex !== idx) {
                    currPoints.push(oldData.getItemLayout(idx));
                    nextPoints.push(newCoordSys.dataToPoint([
                        oldData.get(oldDataNewCoordInfo.dataDimsForPoint[0], idx),
                        oldData.get(oldDataNewCoordInfo.dataDimsForPoint[1], idx)
                    ]));

                    currStackedPoints.push(oldStackedOnPoints[idx]);
                    nextStackedPoints.push(
                        getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, idx)
                    );

                    rawIndices.push(rawIndex);
                }
                else {
                    pointAdded = false;
                }
        }

        // Original indices
        if (pointAdded) {
            status.push(diffItem);
            sortedIndices.push(sortedIndices.length);
        }
    }

    // Diff result may be crossed if all items are changed
    // Sort by data index
    sortedIndices.sort(function (a, b) {
        return rawIndices[a] - rawIndices[b];
    });

    var sortedCurrPoints = [];
    var sortedNextPoints = [];

    var sortedCurrStackedPoints = [];
    var sortedNextStackedPoints = [];

    var sortedStatus = [];
    for (var i = 0; i < sortedIndices.length; i++) {
        var idx = sortedIndices[i];
        sortedCurrPoints[i] = currPoints[idx];
        sortedNextPoints[i] = nextPoints[idx];

        sortedCurrStackedPoints[i] = currStackedPoints[idx];
        sortedNextStackedPoints[i] = nextStackedPoints[idx];

        sortedStatus[i] = status[idx];
    }

    return {
        current: sortedCurrPoints,
        next: sortedNextPoints,

        stackedOnCurrent: sortedCurrStackedPoints,
        stackedOnNext: sortedNextStackedPoints,

        status: sortedStatus
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Poly path support NaN point

var vec2Min = min;
var vec2Max = max;

var scaleAndAdd$1 = scaleAndAdd;
var v2Copy = copy;

// Temporary variable
var v = [];
var cp0 = [];
var cp1 = [];

function isPointNull(p) {
    return isNaN(p[0]) || isNaN(p[1]);
}

function drawSegment(
    ctx, points, start, segLen, allLen,
    dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
) {
    // if (smoothMonotone == null) {
    //     if (isMono(points, 'x')) {
    //         return drawMono(ctx, points, start, segLen, allLen,
    //             dir, smoothMin, smoothMax, smooth, 'x', connectNulls);
    //     }
    //     else if (isMono(points, 'y')) {
    //         return drawMono(ctx, points, start, segLen, allLen,
    //             dir, smoothMin, smoothMax, smooth, 'y', connectNulls);
    //     }
    //     else {
    //         return drawNonMono.apply(this, arguments);
    //     }
    // }
    // else if (smoothMonotone !== 'none' && isMono(points, smoothMonotone)) {
    //     return drawMono.apply(this, arguments);
    // }
    // else {
    //     return drawNonMono.apply(this, arguments);
    // }
    if (smoothMonotone === 'none' || !smoothMonotone) {
        return drawNonMono.apply(this, arguments);
    }
    else {
        return drawMono.apply(this, arguments);
    }
}

/**
 * Check if points is in monotone.
 *
 * @param {number[][]} points         Array of points which is in [x, y] form
 * @param {string}     smoothMonotone 'x', 'y', or 'none', stating for which
 *                                    dimension that is checking.
 *                                    If is 'none', `drawNonMono` should be
 *                                    called.
 *                                    If is undefined, either being monotone
 *                                    in 'x' or 'y' will call `drawMono`.
 */
// function isMono(points, smoothMonotone) {
//     if (points.length <= 1) {
//         return true;
//     }

//     var dim = smoothMonotone === 'x' ? 0 : 1;
//     var last = points[0][dim];
//     var lastDiff = 0;
//     for (var i = 1; i < points.length; ++i) {
//         var diff = points[i][dim] - last;
//         if (!isNaN(diff) && !isNaN(lastDiff)
//             && diff !== 0 && lastDiff !== 0
//             && ((diff >= 0) !== (lastDiff >= 0))
//         ) {
//             return false;
//         }
//         if (!isNaN(diff) && diff !== 0) {
//             lastDiff = diff;
//             last = points[i][dim];
//         }
//     }
//     return true;
// }

/**
 * Draw smoothed line in monotone, in which only vertical or horizontal bezier
 * control points will be used. This should be used when points are monotone
 * either in x or y dimension.
 */
function drawMono(
    ctx, points, start, segLen, allLen,
    dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
) {
    var prevIdx = 0;
    var idx = start;
    for (var k = 0; k < segLen; k++) {
        var p = points[idx];
        if (idx >= allLen || idx < 0) {
            break;
        }
        if (isPointNull(p)) {
            if (connectNulls) {
                idx += dir;
                continue;
            }
            break;
        }

        if (idx === start) {
            ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
        }
        else {
            if (smooth > 0) {
                var prevP = points[prevIdx];
                var dim = smoothMonotone === 'y' ? 1 : 0;

                // Length of control point to p, either in x or y, but not both
                var ctrlLen = (p[dim] - prevP[dim]) * smooth;

                v2Copy(cp0, prevP);
                cp0[dim] = prevP[dim] + ctrlLen;

                v2Copy(cp1, p);
                cp1[dim] = p[dim] - ctrlLen;

                ctx.bezierCurveTo(
                    cp0[0], cp0[1],
                    cp1[0], cp1[1],
                    p[0], p[1]
                );
            }
            else {
                ctx.lineTo(p[0], p[1]);
            }
        }

        prevIdx = idx;
        idx += dir;
    }

    return k;
}

/**
 * Draw smoothed line in non-monotone, in may cause undesired curve in extreme
 * situations. This should be used when points are non-monotone neither in x or
 * y dimension.
 */
function drawNonMono(
    ctx, points, start, segLen, allLen,
    dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
) {
    var prevIdx = 0;
    var idx = start;
    for (var k = 0; k < segLen; k++) {
        var p = points[idx];
        if (idx >= allLen || idx < 0) {
            break;
        }
        if (isPointNull(p)) {
            if (connectNulls) {
                idx += dir;
                continue;
            }
            break;
        }

        if (idx === start) {
            ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
            v2Copy(cp0, p);
        }
        else {
            if (smooth > 0) {
                var nextIdx = idx + dir;
                var nextP = points[nextIdx];
                if (connectNulls) {
                    // Find next point not null
                    while (nextP && isPointNull(points[nextIdx])) {
                        nextIdx += dir;
                        nextP = points[nextIdx];
                    }
                }

                var ratioNextSeg = 0.5;
                var prevP = points[prevIdx];
                var nextP = points[nextIdx];
                // Last point
                if (!nextP || isPointNull(nextP)) {
                    v2Copy(cp1, p);
                }
                else {
                    // If next data is null in not connect case
                    if (isPointNull(nextP) && !connectNulls) {
                        nextP = p;
                    }

                    sub(v, nextP, prevP);

                    var lenPrevSeg;
                    var lenNextSeg;
                    if (smoothMonotone === 'x' || smoothMonotone === 'y') {
                        var dim = smoothMonotone === 'x' ? 0 : 1;
                        lenPrevSeg = Math.abs(p[dim] - prevP[dim]);
                        lenNextSeg = Math.abs(p[dim] - nextP[dim]);
                    }
                    else {
                        lenPrevSeg = dist(p, prevP);
                        lenNextSeg = dist(p, nextP);
                    }

                    // Use ratio of seg length
                    ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);

                    scaleAndAdd$1(cp1, p, v, -smooth * (1 - ratioNextSeg));
                }
                // Smooth constraint
                vec2Min(cp0, cp0, smoothMax);
                vec2Max(cp0, cp0, smoothMin);
                vec2Min(cp1, cp1, smoothMax);
                vec2Max(cp1, cp1, smoothMin);

                ctx.bezierCurveTo(
                    cp0[0], cp0[1],
                    cp1[0], cp1[1],
                    p[0], p[1]
                );
                // cp0 of next segment
                scaleAndAdd$1(cp0, p, v, smooth * ratioNextSeg);
            }
            else {
                ctx.lineTo(p[0], p[1]);
            }
        }

        prevIdx = idx;
        idx += dir;
    }

    return k;
}

function getBoundingBox(points, smoothConstraint) {
    var ptMin = [Infinity, Infinity];
    var ptMax = [-Infinity, -Infinity];
    if (smoothConstraint) {
        for (var i = 0; i < points.length; i++) {
            var pt = points[i];
            if (pt[0] < ptMin[0]) {
                ptMin[0] = pt[0];
            }
            if (pt[1] < ptMin[1]) {
                ptMin[1] = pt[1];
            }
            if (pt[0] > ptMax[0]) {
                ptMax[0] = pt[0];
            }
            if (pt[1] > ptMax[1]) {
                ptMax[1] = pt[1];
            }
        }
    }
    return {
        min: smoothConstraint ? ptMin : ptMax,
        max: smoothConstraint ? ptMax : ptMin
    };
}

var Polyline$1 = Path.extend({

    type: 'ec-polyline',

    shape: {
        points: [],

        smooth: 0,

        smoothConstraint: true,

        smoothMonotone: null,

        connectNulls: false
    },

    style: {
        fill: null,

        stroke: '#000'
    },

    brush: fixClipWithShadow(Path.prototype.brush),

    buildPath: function (ctx, shape) {
        var points = shape.points;

        var i = 0;
        var len$$1 = points.length;

        var result = getBoundingBox(points, shape.smoothConstraint);

        if (shape.connectNulls) {
            // Must remove first and last null values avoid draw error in polygon
            for (; len$$1 > 0; len$$1--) {
                if (!isPointNull(points[len$$1 - 1])) {
                    break;
                }
            }
            for (; i < len$$1; i++) {
                if (!isPointNull(points[i])) {
                    break;
                }
            }
        }
        while (i < len$$1) {
            i += drawSegment(
                ctx, points, i, len$$1, len$$1,
                1, result.min, result.max, shape.smooth,
                shape.smoothMonotone, shape.connectNulls
            ) + 1;
        }
    }
});

var Polygon$1 = Path.extend({

    type: 'ec-polygon',

    shape: {
        points: [],

        // Offset between stacked base points and points
        stackedOnPoints: [],

        smooth: 0,

        stackedOnSmooth: 0,

        smoothConstraint: true,

        smoothMonotone: null,

        connectNulls: false
    },

    brush: fixClipWithShadow(Path.prototype.brush),

    buildPath: function (ctx, shape) {
        var points = shape.points;
        var stackedOnPoints = shape.stackedOnPoints;

        var i = 0;
        var len$$1 = points.length;
        var smoothMonotone = shape.smoothMonotone;
        var bbox = getBoundingBox(points, shape.smoothConstraint);
        var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint);

        if (shape.connectNulls) {
            // Must remove first and last null values avoid draw error in polygon
            for (; len$$1 > 0; len$$1--) {
                if (!isPointNull(points[len$$1 - 1])) {
                    break;
                }
            }
            for (; i < len$$1; i++) {
                if (!isPointNull(points[i])) {
                    break;
                }
            }
        }
        while (i < len$$1) {
            var k = drawSegment(
                ctx, points, i, len$$1, len$$1,
                1, bbox.min, bbox.max, shape.smooth,
                smoothMonotone, shape.connectNulls
            );
            drawSegment(
                ctx, stackedOnPoints, i + k - 1, k, len$$1,
                -1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth,
                smoothMonotone, shape.connectNulls
            );
            i += k + 1;

            ctx.closePath();
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function createGridClipPath(cartesian, hasAnimation, seriesModel) {
    var rect = cartesian.getArea();
    var isHorizontal = cartesian.getBaseAxis().isHorizontal();

    var x = rect.x;
    var y = rect.y;
    var width = rect.width;
    var height = rect.height;

    var lineWidth = seriesModel.get('lineStyle.width') || 2;
    // Expand the clip path a bit to avoid the border is clipped and looks thinner
    x -= lineWidth / 2;
    y -= lineWidth / 2;
    width += lineWidth;
    height += lineWidth;

    var clipPath = new Rect({
        shape: {
            x: x,
            y: y,
            width: width,
            height: height
        }
    });

    if (hasAnimation) {
        clipPath.shape[isHorizontal ? 'width' : 'height'] = 0;
        initProps(clipPath, {
            shape: {
                width: width,
                height: height
            }
        }, seriesModel);
    }

    return clipPath;
}

function createPolarClipPath(polar, hasAnimation, seriesModel) {
    var sectorArea = polar.getArea();
    // Avoid float number rounding error for symbol on the edge of axis extent.

    var clipPath = new Sector({
        shape: {
            cx: round$1(polar.cx, 1),
            cy: round$1(polar.cy, 1),
            r0: round$1(sectorArea.r0, 1),
            r: round$1(sectorArea.r, 1),
            startAngle: sectorArea.startAngle,
            endAngle: sectorArea.endAngle,
            clockwise: sectorArea.clockwise
        }
    });

    if (hasAnimation) {
        clipPath.shape.endAngle = sectorArea.startAngle;
        initProps(clipPath, {
            shape: {
                endAngle: sectorArea.endAngle
            }
        }, seriesModel);
    }
    return clipPath;
}

function createClipPath(coordSys, hasAnimation, seriesModel) {
    if (!coordSys) {
        return null;
    }
    else if (coordSys.type === 'polar') {
        return createPolarClipPath(coordSys, hasAnimation, seriesModel);
    }
    else if (coordSys.type === 'cartesian2d') {
        return createGridClipPath(coordSys, hasAnimation, seriesModel);
    }
    return null;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME step not support polar

function isPointsSame(points1, points2) {
    if (points1.length !== points2.length) {
        return;
    }
    for (var i = 0; i < points1.length; i++) {
        var p1 = points1[i];
        var p2 = points2[i];
        if (p1[0] !== p2[0] || p1[1] !== p2[1]) {
            return;
        }
    }
    return true;
}

function getSmooth(smooth) {
    return typeof (smooth) === 'number' ? smooth : (smooth ? 0.5 : 0);
}

/**
 * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys
 * @param {module:echarts/data/List} data
 * @param {Object} dataCoordInfo
 * @param {Array.<Array.<number>>} points
 */
function getStackedOnPoints(coordSys, data, dataCoordInfo) {
    if (!dataCoordInfo.valueDim) {
        return [];
    }

    var points = [];
    for (var idx = 0, len = data.count(); idx < len; idx++) {
        points.push(getStackedOnPoint(dataCoordInfo, coordSys, data, idx));
    }

    return points;
}

function turnPointsIntoStep(points, coordSys, stepTurnAt) {
    var baseAxis = coordSys.getBaseAxis();
    var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;

    var stepPoints = [];
    for (var i = 0; i < points.length - 1; i++) {
        var nextPt = points[i + 1];
        var pt = points[i];
        stepPoints.push(pt);

        var stepPt = [];
        switch (stepTurnAt) {
            case 'end':
                stepPt[baseIndex] = nextPt[baseIndex];
                stepPt[1 - baseIndex] = pt[1 - baseIndex];
                // default is start
                stepPoints.push(stepPt);
                break;
            case 'middle':
                // default is start
                var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2;
                var stepPt2 = [];
                stepPt[baseIndex] = stepPt2[baseIndex] = middle;
                stepPt[1 - baseIndex] = pt[1 - baseIndex];
                stepPt2[1 - baseIndex] = nextPt[1 - baseIndex];
                stepPoints.push(stepPt);
                stepPoints.push(stepPt2);
                break;
            default:
                stepPt[baseIndex] = pt[baseIndex];
                stepPt[1 - baseIndex] = nextPt[1 - baseIndex];
                // default is start
                stepPoints.push(stepPt);
        }
    }
    // Last points
    points[i] && stepPoints.push(points[i]);
    return stepPoints;
}

function getVisualGradient(data, coordSys) {
    var visualMetaList = data.getVisual('visualMeta');
    if (!visualMetaList || !visualMetaList.length || !data.count()) {
        // When data.count() is 0, gradient range can not be calculated.
        return;
    }

    if (coordSys.type !== 'cartesian2d') {
        if (__DEV__) {
            console.warn('Visual map on line style is only supported on cartesian2d.');
        }
        return;
    }

    var coordDim;
    var visualMeta;

    for (var i = visualMetaList.length - 1; i >= 0; i--) {
        var dimIndex = visualMetaList[i].dimension;
        var dimName = data.dimensions[dimIndex];
        var dimInfo = data.getDimensionInfo(dimName);
        coordDim = dimInfo && dimInfo.coordDim;
        // Can only be x or y
        if (coordDim === 'x' || coordDim === 'y') {
            visualMeta = visualMetaList[i];
            break;
        }
    }

    if (!visualMeta) {
        if (__DEV__) {
            console.warn('Visual map on line style only support x or y dimension.');
        }
        return;
    }

    // If the area to be rendered is bigger than area defined by LinearGradient,
    // the canvas spec prescribes that the color of the first stop and the last
    // stop should be used. But if two stops are added at offset 0, in effect
    // browsers use the color of the second stop to render area outside
    // LinearGradient. So we can only infinitesimally extend area defined in
    // LinearGradient to render `outerColors`.

    var axis = coordSys.getAxis(coordDim);

    // dataToCoor mapping may not be linear, but must be monotonic.
    var colorStops = map(visualMeta.stops, function (stop) {
        return {
            coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
            color: stop.color
        };
    });
    var stopLen = colorStops.length;
    var outerColors = visualMeta.outerColors.slice();

    if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) {
        colorStops.reverse();
        outerColors.reverse();
    }

    var tinyExtent = 10; // Arbitrary value: 10px
    var minCoord = colorStops[0].coord - tinyExtent;
    var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
    var coordSpan = maxCoord - minCoord;

    if (coordSpan < 1e-3) {
        return 'transparent';
    }

    each$1(colorStops, function (stop) {
        stop.offset = (stop.coord - minCoord) / coordSpan;
    });
    colorStops.push({
        offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
        color: outerColors[1] || 'transparent'
    });
    colorStops.unshift({ // notice colorStops.length have been changed.
        offset: stopLen ? colorStops[0].offset : 0.5,
        color: outerColors[0] || 'transparent'
    });

    // zrUtil.each(colorStops, function (colorStop) {
    //     // Make sure each offset has rounded px to avoid not sharp edge
    //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
    // });

    var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true);
    gradient[coordDim] = minCoord;
    gradient[coordDim + '2'] = maxCoord;

    return gradient;
}

function getIsIgnoreFunc(seriesModel, data, coordSys) {
    var showAllSymbol = seriesModel.get('showAllSymbol');
    var isAuto = showAllSymbol === 'auto';

    if (showAllSymbol && !isAuto) {
        return;
    }

    var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
    if (!categoryAxis) {
        return;
    }

    // Note that category label interval strategy might bring some weird effect
    // in some scenario: users may wonder why some of the symbols are not
    // displayed. So we show all symbols as possible as we can.
    if (isAuto
        // Simplify the logic, do not determine label overlap here.
        && canShowAllSymbolForCategory(categoryAxis, data)
    ) {
        return;
    }

    // Otherwise follow the label interval strategy on category axis.
    var categoryDataDim = data.mapDimension(categoryAxis.dim);
    var labelMap = {};

    each$1(categoryAxis.getViewLabels(), function (labelItem) {
        labelMap[labelItem.tickValue] = 1;
    });

    return function (dataIndex) {
        return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex));
    };
}

function canShowAllSymbolForCategory(categoryAxis, data) {
    // In mose cases, line is monotonous on category axis, and the label size
    // is close with each other. So we check the symbol size and some of the
    // label size alone with the category axis to estimate whether all symbol
    // can be shown without overlap.
    var axisExtent = categoryAxis.getExtent();
    var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count();
    isNaN(availSize) && (availSize = 0); // 0/0 is NaN.

    // Sampling some points, max 5.
    var dataLen = data.count();
    var step = Math.max(1, Math.round(dataLen / 5));
    for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) {
        if (SymbolClz$1.getSymbolSize(
                data, dataIndex
            // Only for cartesian, where `isHorizontal` exists.
            )[categoryAxis.isHorizontal() ? 1 : 0]
            // Empirical number
            * 1.5 > availSize
        ) {
            return false;
        }
    }

    return true;
}

function createLineClipPath(coordSys, hasAnimation, seriesModel) {
    if (coordSys.type === 'cartesian2d') {
        var isHorizontal = coordSys.getBaseAxis().isHorizontal();
        var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel);
        // Expand clip shape to avoid clipping when line value exceeds axis
        if (!seriesModel.get('clip', true)) {
            var rectShape = clipPath.shape;
            var expandSize = Math.max(rectShape.width, rectShape.height);
            if (isHorizontal) {
                rectShape.y -= expandSize;
                rectShape.height += expandSize * 2;
            }
            else {
                rectShape.x -= expandSize;
                rectShape.width += expandSize * 2;
            }
        }
        return clipPath;
    }
    else {
        return createPolarClipPath(coordSys, hasAnimation, seriesModel);
    }

}

Chart.extend({

    type: 'line',

    init: function () {
        var lineGroup = new Group();

        var symbolDraw = new SymbolDraw();
        this.group.add(symbolDraw.group);

        this._symbolDraw = symbolDraw;
        this._lineGroup = lineGroup;
    },

    render: function (seriesModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;
        var group = this.group;
        var data = seriesModel.getData();
        var lineStyleModel = seriesModel.getModel('lineStyle');
        var areaStyleModel = seriesModel.getModel('areaStyle');

        var points = data.mapArray(data.getItemLayout);

        var isCoordSysPolar = coordSys.type === 'polar';
        var prevCoordSys = this._coordSys;

        var symbolDraw = this._symbolDraw;
        var polyline = this._polyline;
        var polygon = this._polygon;

        var lineGroup = this._lineGroup;

        var hasAnimation = seriesModel.get('animation');

        var isAreaChart = !areaStyleModel.isEmpty();

        var valueOrigin = areaStyleModel.get('origin');
        var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin);

        var stackedOnPoints = getStackedOnPoints(coordSys, data, dataCoordInfo);

        var showSymbol = seriesModel.get('showSymbol');

        var isIgnoreFunc = showSymbol && !isCoordSysPolar
            && getIsIgnoreFunc(seriesModel, data, coordSys);

        // Remove temporary symbols
        var oldData = this._data;
        oldData && oldData.eachItemGraphicEl(function (el, idx) {
            if (el.__temp) {
                group.remove(el);
                oldData.setItemGraphicEl(idx, null);
            }
        });

        // Remove previous created symbols if showSymbol changed to false
        if (!showSymbol) {
            symbolDraw.remove();
        }

        group.add(lineGroup);

        // FIXME step not support polar
        var step = !isCoordSysPolar && seriesModel.get('step');
        var clipShapeForSymbol;
        if (coordSys && coordSys.getArea) {
            clipShapeForSymbol = coordSys.getArea();
            // Avoid float number rounding error for symbol on the edge of axis extent.
            // See #7913 and `test/dataZoom-clip.html`.
            if (clipShapeForSymbol.width != null) {
                clipShapeForSymbol.x -= 0.1;
                clipShapeForSymbol.y -= 0.1;
                clipShapeForSymbol.width += 0.2;
                clipShapeForSymbol.height += 0.2;
            }
            else if (clipShapeForSymbol.r0) {
                clipShapeForSymbol.r0 -= 0.5;
                clipShapeForSymbol.r1 += 0.5;
            }
        }
        // Initialization animation or coordinate system changed
        if (
            !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
        ) {
            showSymbol && symbolDraw.updateData(data, {
                isIgnore: isIgnoreFunc,
                clipShape: clipShapeForSymbol
            });

            if (step) {
                // TODO If stacked series is not step
                points = turnPointsIntoStep(points, coordSys, step);
                stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
            }

            polyline = this._newPolyline(points, coordSys, hasAnimation);
            if (isAreaChart) {
                polygon = this._newPolygon(
                    points, stackedOnPoints,
                    coordSys, hasAnimation
                );
            }
            lineGroup.setClipPath(createLineClipPath(coordSys, true, seriesModel));
        }
        else {
            if (isAreaChart && !polygon) {
                // If areaStyle is added
                polygon = this._newPolygon(
                    points, stackedOnPoints,
                    coordSys, hasAnimation
                );
            }
            else if (polygon && !isAreaChart) {
                // If areaStyle is removed
                lineGroup.remove(polygon);
                polygon = this._polygon = null;
            }

            // Update clipPath
            lineGroup.setClipPath(createLineClipPath(coordSys, false, seriesModel));

            // Always update, or it is wrong in the case turning on legend
            // because points are not changed
            showSymbol && symbolDraw.updateData(data, {
                isIgnore: isIgnoreFunc,
                clipShape: clipShapeForSymbol
            });

            // Stop symbol animation and sync with line points
            // FIXME performance?
            data.eachItemGraphicEl(function (el) {
                el.stopAnimation(true);
            });

            // In the case data zoom triggerred refreshing frequently
            // Data may not change if line has a category axis. So it should animate nothing
            if (!isPointsSame(this._stackedOnPoints, stackedOnPoints)
                || !isPointsSame(this._points, points)
            ) {
                if (hasAnimation) {
                    this._updateAnimation(
                        data, stackedOnPoints, coordSys, api, step, valueOrigin
                    );
                }
                else {
                    // Not do it in update with animation
                    if (step) {
                        // TODO If stacked series is not step
                        points = turnPointsIntoStep(points, coordSys, step);
                        stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
                    }

                    polyline.setShape({
                        points: points
                    });
                    polygon && polygon.setShape({
                        points: points,
                        stackedOnPoints: stackedOnPoints
                    });
                }
            }
        }

        var visualColor = getVisualGradient(data, coordSys) || data.getVisual('color');

        polyline.useStyle(defaults(
            // Use color in lineStyle first
            lineStyleModel.getLineStyle(),
            {
                fill: 'none',
                stroke: visualColor,
                lineJoin: 'bevel'
            }
        ));

        var smooth = seriesModel.get('smooth');
        smooth = getSmooth(seriesModel.get('smooth'));
        polyline.setShape({
            smooth: smooth,
            smoothMonotone: seriesModel.get('smoothMonotone'),
            connectNulls: seriesModel.get('connectNulls')
        });

        if (polygon) {
            var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
            var stackedOnSmooth = 0;

            polygon.useStyle(defaults(
                areaStyleModel.getAreaStyle(),
                {
                    fill: visualColor,
                    opacity: 0.7,
                    lineJoin: 'bevel'
                }
            ));

            if (stackedOnSeries) {
                stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
            }

            polygon.setShape({
                smooth: smooth,
                stackedOnSmooth: stackedOnSmooth,
                smoothMonotone: seriesModel.get('smoothMonotone'),
                connectNulls: seriesModel.get('connectNulls')
            });
        }

        this._data = data;
        // Save the coordinate system for transition animation when data changed
        this._coordSys = coordSys;
        this._stackedOnPoints = stackedOnPoints;
        this._points = points;
        this._step = step;
        this._valueOrigin = valueOrigin;
    },

    dispose: function () {},

    highlight: function (seriesModel, ecModel, api, payload) {
        var data = seriesModel.getData();
        var dataIndex = queryDataIndex(data, payload);

        if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) {
            var symbol = data.getItemGraphicEl(dataIndex);
            if (!symbol) {
                // Create a temporary symbol if it is not exists
                var pt = data.getItemLayout(dataIndex);
                if (!pt) {
                    // Null data
                    return;
                }
                symbol = new SymbolClz$1(data, dataIndex);
                symbol.position = pt;
                symbol.setZ(
                    seriesModel.get('zlevel'),
                    seriesModel.get('z')
                );
                symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]);
                symbol.__temp = true;
                data.setItemGraphicEl(dataIndex, symbol);

                // Stop scale animation
                symbol.stopSymbolAnimation(true);

                this.group.add(symbol);
            }
            symbol.highlight();
        }
        else {
            // Highlight whole series
            Chart.prototype.highlight.call(
                this, seriesModel, ecModel, api, payload
            );
        }
    },

    downplay: function (seriesModel, ecModel, api, payload) {
        var data = seriesModel.getData();
        var dataIndex = queryDataIndex(data, payload);
        if (dataIndex != null && dataIndex >= 0) {
            var symbol = data.getItemGraphicEl(dataIndex);
            if (symbol) {
                if (symbol.__temp) {
                    data.setItemGraphicEl(dataIndex, null);
                    this.group.remove(symbol);
                }
                else {
                    symbol.downplay();
                }
            }
        }
        else {
            // FIXME
            // can not downplay completely.
            // Downplay whole series
            Chart.prototype.downplay.call(
                this, seriesModel, ecModel, api, payload
            );
        }
    },

    /**
     * @param {module:zrender/container/Group} group
     * @param {Array.<Array.<number>>} points
     * @private
     */
    _newPolyline: function (points) {
        var polyline = this._polyline;
        // Remove previous created polyline
        if (polyline) {
            this._lineGroup.remove(polyline);
        }

        polyline = new Polyline$1({
            shape: {
                points: points
            },
            silent: true,
            z2: 10
        });

        this._lineGroup.add(polyline);

        this._polyline = polyline;

        return polyline;
    },

    /**
     * @param {module:zrender/container/Group} group
     * @param {Array.<Array.<number>>} stackedOnPoints
     * @param {Array.<Array.<number>>} points
     * @private
     */
    _newPolygon: function (points, stackedOnPoints) {
        var polygon = this._polygon;
        // Remove previous created polygon
        if (polygon) {
            this._lineGroup.remove(polygon);
        }

        polygon = new Polygon$1({
            shape: {
                points: points,
                stackedOnPoints: stackedOnPoints
            },
            silent: true
        });

        this._lineGroup.add(polygon);

        this._polygon = polygon;
        return polygon;
    },

    /**
     * @private
     */
    // FIXME Two value axis
    _updateAnimation: function (data, stackedOnPoints, coordSys, api, step, valueOrigin) {
        var polyline = this._polyline;
        var polygon = this._polygon;
        var seriesModel = data.hostModel;

        var diff = lineAnimationDiff(
            this._data, data,
            this._stackedOnPoints, stackedOnPoints,
            this._coordSys, coordSys,
            this._valueOrigin, valueOrigin
        );

        var current = diff.current;
        var stackedOnCurrent = diff.stackedOnCurrent;
        var next = diff.next;
        var stackedOnNext = diff.stackedOnNext;
        if (step) {
            // TODO If stacked series is not step
            current = turnPointsIntoStep(diff.current, coordSys, step);
            stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step);
            next = turnPointsIntoStep(diff.next, coordSys, step);
            stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step);
        }
        // `diff.current` is subset of `current` (which should be ensured by
        // turnPointsIntoStep), so points in `__points` can be updated when
        // points in `current` are update during animation.
        polyline.shape.__points = diff.current;
        polyline.shape.points = current;

        updateProps(polyline, {
            shape: {
                points: next
            }
        }, seriesModel);

        if (polygon) {
            polygon.setShape({
                points: current,
                stackedOnPoints: stackedOnCurrent
            });
            updateProps(polygon, {
                shape: {
                    points: next,
                    stackedOnPoints: stackedOnNext
                }
            }, seriesModel);
        }

        var updatedDataInfo = [];
        var diffStatus = diff.status;

        for (var i = 0; i < diffStatus.length; i++) {
            var cmd = diffStatus[i].cmd;
            if (cmd === '=') {
                var el = data.getItemGraphicEl(diffStatus[i].idx1);
                if (el) {
                    updatedDataInfo.push({
                        el: el,
                        ptIdx: i    // Index of points
                    });
                }
            }
        }

        if (polyline.animators && polyline.animators.length) {
            polyline.animators[0].during(function () {
                for (var i = 0; i < updatedDataInfo.length; i++) {
                    var el = updatedDataInfo[i].el;
                    el.attr('position', polyline.shape.__points[updatedDataInfo[i].ptIdx]);
                }
            });
        }
    },

    remove: function (ecModel) {
        var group = this.group;
        var oldData = this._data;
        this._lineGroup.removeAll();
        this._symbolDraw.remove(true);
        // Remove temporary created elements when highlighting
        oldData && oldData.eachItemGraphicEl(function (el, idx) {
            if (el.__temp) {
                group.remove(el);
                oldData.setItemGraphicEl(idx, null);
            }
        });

        this._polyline =
            this._polygon =
            this._coordSys =
            this._points =
            this._stackedOnPoints =
            this._data = null;
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var visualSymbol = function (seriesType, defaultSymbolType, legendSymbol) {
    // Encoding visual for all series include which is filtered for legend drawing
    return {
        seriesType: seriesType,

        // For legend.
        performRawSeries: true,

        reset: function (seriesModel, ecModel, api) {
            var data = seriesModel.getData();

            var symbolType = seriesModel.get('symbol');
            var symbolSize = seriesModel.get('symbolSize');
            var keepAspect = seriesModel.get('symbolKeepAspect');

            var hasSymbolTypeCallback = isFunction$1(symbolType);
            var hasSymbolSizeCallback = isFunction$1(symbolSize);
            var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback;
            var seriesSymbol = (!hasSymbolTypeCallback && symbolType) ? symbolType : defaultSymbolType;
            var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;

            data.setVisual({
                legendSymbol: legendSymbol || seriesSymbol,
                // If seting callback functions on `symbol` or `symbolSize`, for simplicity and avoiding
                // to bring trouble, we do not pick a reuslt from one of its calling on data item here,
                // but just use the default value. Callback on `symbol` or `symbolSize` is convenient in
                // some cases but generally it is not recommanded.
                symbol: seriesSymbol,
                symbolSize: seriesSymbolSize,
                symbolKeepAspect: keepAspect
            });

            // Only visible series has each data be visual encoded
            if (ecModel.isSeriesFiltered(seriesModel)) {
                return;
            }

            function dataEach(data, idx) {
                if (hasCallback) {
                    var rawValue = seriesModel.getRawValue(idx);
                    var params = seriesModel.getDataParams(idx);
                    hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params));
                    hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
                }

                if (data.hasItemOption) {
                    var itemModel = data.getItemModel(idx);
                    var itemSymbolType = itemModel.getShallow('symbol', true);
                    var itemSymbolSize = itemModel.getShallow('symbolSize', true);
                    var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true);

                    // If has item symbol
                    if (itemSymbolType != null) {
                        data.setItemVisual(idx, 'symbol', itemSymbolType);
                    }
                    if (itemSymbolSize != null) {
                        // PENDING Transform symbolSize ?
                        data.setItemVisual(idx, 'symbolSize', itemSymbolSize);
                    }
                    if (itemSymbolKeepAspect != null) {
                        data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
                    }
                }
            }

            return { dataEach: (data.hasItemOption || hasCallback) ? dataEach : null };
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float32Array */

var pointsLayout = function (seriesType) {
    return {
        seriesType: seriesType,

        plan: createRenderPlanner(),

        reset: function (seriesModel) {
            var data = seriesModel.getData();
            var coordSys = seriesModel.coordinateSystem;
            var pipelineContext = seriesModel.pipelineContext;
            var isLargeRender = pipelineContext.large;

            if (!coordSys) {
                return;
            }

            var dims = map(coordSys.dimensions, function (dim) {
                return data.mapDimension(dim);
            }).slice(0, 2);
            var dimLen = dims.length;

            var stackResultDim = data.getCalculationInfo('stackResultDimension');
            if (isDimensionStacked(data, dims[0] /*, dims[1]*/)) {
                dims[0] = stackResultDim;
            }
            if (isDimensionStacked(data, dims[1] /*, dims[0]*/)) {
                dims[1] = stackResultDim;
            }

            function progress(params, data) {
                var segCount = params.end - params.start;
                var points = isLargeRender && new Float32Array(segCount * dimLen);

                for (var i = params.start, offset = 0, tmpIn = [], tmpOut = []; i < params.end; i++) {
                    var point;

                    if (dimLen === 1) {
                        var x = data.get(dims[0], i);
                        point = !isNaN(x) && coordSys.dataToPoint(x, null, tmpOut);
                    }
                    else {
                        var x = tmpIn[0] = data.get(dims[0], i);
                        var y = tmpIn[1] = data.get(dims[1], i);
                        // Also {Array.<number>}, not undefined to avoid if...else... statement
                        point = !isNaN(x) && !isNaN(y) && coordSys.dataToPoint(tmpIn, null, tmpOut);
                    }

                    if (isLargeRender) {
                        points[offset++] = point ? point[0] : NaN;
                        points[offset++] = point ? point[1] : NaN;
                    }
                    else {
                        data.setItemLayout(i, (point && point.slice()) || [NaN, NaN]);
                    }
                }

                isLargeRender && data.setLayout('symbolPoints', points);
            }

            return dimLen && {progress: progress};
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var samplers = {
    average: function (frame) {
        var sum = 0;
        var count = 0;
        for (var i = 0; i < frame.length; i++) {
            if (!isNaN(frame[i])) {
                sum += frame[i];
                count++;
            }
        }
        // Return NaN if count is 0
        return count === 0 ? NaN : sum / count;
    },
    sum: function (frame) {
        var sum = 0;
        for (var i = 0; i < frame.length; i++) {
            // Ignore NaN
            sum += frame[i] || 0;
        }
        return sum;
    },
    max: function (frame) {
        var max = -Infinity;
        for (var i = 0; i < frame.length; i++) {
            frame[i] > max && (max = frame[i]);
        }
        // NaN will cause illegal axis extent.
        return isFinite(max) ? max : NaN;
    },
    min: function (frame) {
        var min = Infinity;
        for (var i = 0; i < frame.length; i++) {
            frame[i] < min && (min = frame[i]);
        }
        // NaN will cause illegal axis extent.
        return isFinite(min) ? min : NaN;
    },
    // TODO
    // Median
    nearest: function (frame) {
        return frame[0];
    }
};

var indexSampler = function (frame, value) {
    return Math.round(frame.length / 2);
};

var dataSample = function (seriesType) {
    return {

        seriesType: seriesType,

        modifyOutputEnd: true,

        reset: function (seriesModel, ecModel, api) {
            var data = seriesModel.getData();
            var sampling = seriesModel.get('sampling');
            var coordSys = seriesModel.coordinateSystem;
            // Only cartesian2d support down sampling
            if (coordSys.type === 'cartesian2d' && sampling) {
                var baseAxis = coordSys.getBaseAxis();
                var valueAxis = coordSys.getOtherAxis(baseAxis);
                var extent = baseAxis.getExtent();
                // Coordinste system has been resized
                var size = extent[1] - extent[0];
                var rate = Math.round(data.count() / size);
                if (rate > 1) {
                    var sampler;
                    if (typeof sampling === 'string') {
                        sampler = samplers[sampling];
                    }
                    else if (typeof sampling === 'function') {
                        sampler = sampling;
                    }
                    if (sampler) {
                        // Only support sample the first dim mapped from value axis.
                        seriesModel.setData(data.downSample(
                            data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler
                        ));
                    }
                }
            }
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Cartesian coordinate system
 * @module  echarts/coord/Cartesian
 *
 */

function dimAxisMapper(dim) {
    return this._axes[dim];
}

/**
 * @alias module:echarts/coord/Cartesian
 * @constructor
 */
var Cartesian = function (name) {
    this._axes = {};

    this._dimList = [];

    /**
     * @type {string}
     */
    this.name = name || '';
};

Cartesian.prototype = {

    constructor: Cartesian,

    type: 'cartesian',

    /**
     * Get axis
     * @param  {number|string} dim
     * @return {module:echarts/coord/Cartesian~Axis}
     */
    getAxis: function (dim) {
        return this._axes[dim];
    },

    /**
     * Get axes list
     * @return {Array.<module:echarts/coord/Cartesian~Axis>}
     */
    getAxes: function () {
        return map(this._dimList, dimAxisMapper, this);
    },

    /**
     * Get axes list by given scale type
     */
    getAxesByScale: function (scaleType) {
        scaleType = scaleType.toLowerCase();
        return filter(
            this.getAxes(),
            function (axis) {
                return axis.scale.type === scaleType;
            }
        );
    },

    /**
     * Add axis
     * @param {module:echarts/coord/Cartesian.Axis}
     */
    addAxis: function (axis) {
        var dim = axis.dim;

        this._axes[dim] = axis;

        this._dimList.push(dim);
    },

    /**
     * Convert data to coord in nd space
     * @param {Array.<number>|Object.<string, number>} val
     * @return {Array.<number>|Object.<string, number>}
     */
    dataToCoord: function (val) {
        return this._dataCoordConvert(val, 'dataToCoord');
    },

    /**
     * Convert coord in nd space to data
     * @param  {Array.<number>|Object.<string, number>} val
     * @return {Array.<number>|Object.<string, number>}
     */
    coordToData: function (val) {
        return this._dataCoordConvert(val, 'coordToData');
    },

    _dataCoordConvert: function (input, method) {
        var dimList = this._dimList;

        var output = input instanceof Array ? [] : {};

        for (var i = 0; i < dimList.length; i++) {
            var dim = dimList[i];
            var axis = this._axes[dim];

            output[dim] = axis[method](input[dim]);
        }

        return output;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


function Cartesian2D(name) {

    Cartesian.call(this, name);
}

Cartesian2D.prototype = {

    constructor: Cartesian2D,

    type: 'cartesian2d',

    /**
     * @type {Array.<string>}
     * @readOnly
     */
    dimensions: ['x', 'y'],

    /**
     * Base axis will be used on stacking.
     *
     * @return {module:echarts/coord/cartesian/Axis2D}
     */
    getBaseAxis: function () {
        return this.getAxesByScale('ordinal')[0]
            || this.getAxesByScale('time')[0]
            || this.getAxis('x');
    },

    /**
     * If contain point
     * @param {Array.<number>} point
     * @return {boolean}
     */
    containPoint: function (point) {
        var axisX = this.getAxis('x');
        var axisY = this.getAxis('y');
        return axisX.contain(axisX.toLocalCoord(point[0]))
            && axisY.contain(axisY.toLocalCoord(point[1]));
    },

    /**
     * If contain data
     * @param {Array.<number>} data
     * @return {boolean}
     */
    containData: function (data) {
        return this.getAxis('x').containData(data[0])
            && this.getAxis('y').containData(data[1]);
    },

    /**
     * @param {Array.<number>} data
     * @param {Array.<number>} out
     * @return {Array.<number>}
     */
    dataToPoint: function (data, reserved, out) {
        var xAxis = this.getAxis('x');
        var yAxis = this.getAxis('y');
        out = out || [];
        out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(data[0]));
        out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(data[1]));
        return out;
    },

    /**
     * @param {Array.<number>} data
     * @param {Array.<number>} out
     * @return {Array.<number>}
     */
    clampData: function (data, out) {
        var xScale = this.getAxis('x').scale;
        var yScale = this.getAxis('y').scale;
        var xAxisExtent = xScale.getExtent();
        var yAxisExtent = yScale.getExtent();
        var x = xScale.parse(data[0]);
        var y = yScale.parse(data[1]);
        out = out || [];
        out[0] = Math.min(
            Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x),
            Math.max(xAxisExtent[0], xAxisExtent[1])
        );
        out[1] = Math.min(
            Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y),
            Math.max(yAxisExtent[0], yAxisExtent[1])
        );

        return out;
    },

    /**
     * @param {Array.<number>} point
     * @param {Array.<number>} out
     * @return {Array.<number>}
     */
    pointToData: function (point, out) {
        var xAxis = this.getAxis('x');
        var yAxis = this.getAxis('y');
        out = out || [];
        out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]));
        out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]));
        return out;
    },

    /**
     * Get other axis
     * @param {module:echarts/coord/cartesian/Axis2D} axis
     */
    getOtherAxis: function (axis) {
        return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
    },

    /**
     * Get rect area of cartesian.
     * Area will have a contain function to determine if a point is in the coordinate system.
     * @return {BoundingRect}
     */
    getArea: function () {
        var xExtent = this.getAxis('x').getGlobalExtent();
        var yExtent = this.getAxis('y').getGlobalExtent();
        var x = Math.min(xExtent[0], xExtent[1]);
        var y = Math.min(yExtent[0], yExtent[1]);
        var width = Math.max(xExtent[0], xExtent[1]) - x;
        var height = Math.max(yExtent[0], yExtent[1]) - y;

        var rect = new BoundingRect(x, y, width, height);
        return rect;
    }

};

inherits(Cartesian2D, Cartesian);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Extend axis 2d
 * @constructor module:echarts/coord/cartesian/Axis2D
 * @extends {module:echarts/coord/cartesian/Axis}
 * @param {string} dim
 * @param {*} scale
 * @param {Array.<number>} coordExtent
 * @param {string} axisType
 * @param {string} position
 */
var Axis2D = function (dim, scale, coordExtent, axisType, position) {
    Axis.call(this, dim, scale, coordExtent);
    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = axisType || 'value';

    /**
     * Axis position
     *  - 'top'
     *  - 'bottom'
     *  - 'left'
     *  - 'right'
     */
    this.position = position || 'bottom';
};

Axis2D.prototype = {

    constructor: Axis2D,

    /**
     * Index of axis, can be used as key
     */
    index: 0,

    /**
     * Implemented in <module:echarts/coord/cartesian/Grid>.
     * @return {Array.<module:echarts/coord/cartesian/Axis2D>}
     *         If not on zero of other axis, return null/undefined.
     *         If no axes, return an empty array.
     */
    getAxesOnZeroOf: null,

    /**
     * Axis model
     * @param {module:echarts/coord/cartesian/AxisModel}
     */
    model: null,

    isHorizontal: function () {
        var position = this.position;
        return position === 'top' || position === 'bottom';
    },

    /**
     * Each item cooresponds to this.getExtent(), which
     * means globalExtent[0] may greater than globalExtent[1],
     * unless `asc` is input.
     *
     * @param {boolean} [asc]
     * @return {Array.<number>}
     */
    getGlobalExtent: function (asc) {
        var ret = this.getExtent();
        ret[0] = this.toGlobalCoord(ret[0]);
        ret[1] = this.toGlobalCoord(ret[1]);
        asc && ret[0] > ret[1] && ret.reverse();
        return ret;
    },

    getOtherAxis: function () {
        this.grid.getOtherAxis();
    },

    /**
     * @override
     */
    pointToData: function (point, clamp) {
        return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp);
    },

    /**
     * Transform global coord to local coord,
     * i.e. var localCoord = axis.toLocalCoord(80);
     * designate by module:echarts/coord/cartesian/Grid.
     * @type {Function}
     */
    toLocalCoord: null,

    /**
     * Transform global coord to local coord,
     * i.e. var globalCoord = axis.toLocalCoord(40);
     * designate by module:echarts/coord/cartesian/Grid.
     * @type {Function}
     */
    toGlobalCoord: null

};

inherits(Axis2D, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var defaultOption = {
    show: true,
    zlevel: 0,
    z: 0,
    // Inverse the axis.
    inverse: false,

    // Axis name displayed.
    name: '',
    // 'start' | 'middle' | 'end'
    nameLocation: 'end',
    // By degree. By defualt auto rotate by nameLocation.
    nameRotate: null,
    nameTruncate: {
        maxWidth: null,
        ellipsis: '...',
        placeholder: '.'
    },
    // Use global text style by default.
    nameTextStyle: {},
    // The gap between axisName and axisLine.
    nameGap: 15,

    // Default `false` to support tooltip.
    silent: false,
    // Default `false` to avoid legacy user event listener fail.
    triggerEvent: false,

    tooltip: {
        show: false
    },

    axisPointer: {},

    axisLine: {
        show: true,
        onZero: true,
        onZeroAxisIndex: null,
        lineStyle: {
            color: '#333',
            width: 1,
            type: 'solid'
        },
        // The arrow at both ends the the axis.
        symbol: ['none', 'none'],
        symbolSize: [10, 15]
    },
    axisTick: {
        show: true,
        // Whether axisTick is inside the grid or outside the grid.
        inside: false,
        // The length of axisTick.
        length: 5,
        lineStyle: {
            width: 1
        }
    },
    axisLabel: {
        show: true,
        // Whether axisLabel is inside the grid or outside the grid.
        inside: false,
        rotate: 0,
        // true | false | null/undefined (auto)
        showMinLabel: null,
        // true | false | null/undefined (auto)
        showMaxLabel: null,
        margin: 8,
        // formatter: null,
        fontSize: 12
    },
    splitLine: {
        show: true,
        lineStyle: {
            color: ['#ccc'],
            width: 1,
            type: 'solid'
        }
    },
    splitArea: {
        show: false,
        areaStyle: {
            color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
        }
    }
};

var axisDefault = {};

axisDefault.categoryAxis = merge({
    // The gap at both ends of the axis. For categoryAxis, boolean.
    boundaryGap: true,
    // Set false to faster category collection.
    // Only usefull in the case like: category is
    // ['2012-01-01', '2012-01-02', ...], where the input
    // data has been ensured not duplicate and is large data.
    // null means "auto":
    // if axis.data provided, do not deduplication,
    // else do deduplication.
    deduplication: null,
    // splitArea: {
        // show: false
    // },
    splitLine: {
        show: false
    },
    axisTick: {
        // If tick is align with label when boundaryGap is true
        alignWithLabel: false,
        interval: 'auto'
    },
    axisLabel: {
        interval: 'auto'
    }
}, defaultOption);

axisDefault.valueAxis = merge({
    // The gap at both ends of the axis. For value axis, [GAP, GAP], where
    // `GAP` can be an absolute pixel number (like `35`), or percent (like `'30%'`)
    boundaryGap: [0, 0],

    // TODO
    // min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60]

    // Min value of the axis. can be:
    // + a number
    // + 'dataMin': use the min value in data.
    // + null/undefined: auto decide min value (consider pretty look and boundaryGap).
    // min: null,

    // Max value of the axis. can be:
    // + a number
    // + 'dataMax': use the max value in data.
    // + null/undefined: auto decide max value (consider pretty look and boundaryGap).
    // max: null,

    // Readonly prop, specifies start value of the range when using data zoom.
    // rangeStart: null

    // Readonly prop, specifies end value of the range when using data zoom.
    // rangeEnd: null

    // Optional value can be:
    // + `false`: always include value 0.
    // + `true`: the extent do not consider value 0.
    // scale: false,

    // AxisTick and axisLabel and splitLine are caculated based on splitNumber.
    splitNumber: 5

    // Interval specifies the span of the ticks is mandatorily.
    // interval: null

    // Specify min interval when auto calculate tick interval.
    // minInterval: null

    // Specify max interval when auto calculate tick interval.
    // maxInterval: null

}, defaultOption);

axisDefault.timeAxis = defaults({
    scale: true,
    min: 'dataMin',
    max: 'dataMax'
}, axisDefault.valueAxis);

axisDefault.logAxis = defaults({
    scale: true,
    logBase: 10
}, axisDefault.valueAxis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME axisType is fixed ?
var AXIS_TYPES = ['value', 'category', 'time', 'log'];

/**
 * Generate sub axis model class
 * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel'
 * @param {module:echarts/model/Component} BaseAxisModelClass
 * @param {Function} axisTypeDefaulter
 * @param {Object} [extraDefaultOption]
 */
var axisModelCreator = function (axisName, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) {

    each$1(AXIS_TYPES, function (axisType) {

        BaseAxisModelClass.extend({

            /**
             * @readOnly
             */
            type: axisName + 'Axis.' + axisType,

            mergeDefaultAndTheme: function (option, ecModel) {
                var layoutMode = this.layoutMode;
                var inputPositionParams = layoutMode
                    ? getLayoutParams(option) : {};

                var themeModel = ecModel.getTheme();
                merge(option, themeModel.get(axisType + 'Axis'));
                merge(option, this.getDefaultOption());

                option.type = axisTypeDefaulter(axisName, option);

                if (layoutMode) {
                    mergeLayoutParam(option, inputPositionParams, layoutMode);
                }
            },

            /**
             * @override
             */
            optionUpdated: function () {
                var thisOption = this.option;
                if (thisOption.type === 'category') {
                    this.__ordinalMeta = OrdinalMeta.createByAxisModel(this);
                }
            },

            /**
             * Should not be called before all of 'getInitailData' finished.
             * Because categories are collected during initializing data.
             */
            getCategories: function (rawData) {
                var option = this.option;
                // FIXME
                // warning if called before all of 'getInitailData' finished.
                if (option.type === 'category') {
                    if (rawData) {
                        return option.data;
                    }
                    return this.__ordinalMeta.categories;
                }
            },

            getOrdinalMeta: function () {
                return this.__ordinalMeta;
            },

            defaultOption: mergeAll(
                [
                    {},
                    axisDefault[axisType + 'Axis'],
                    extraDefaultOption
                ],
                true
            )
        });
    });

    ComponentModel.registerSubTypeDefaulter(
        axisName + 'Axis',
        curry(axisTypeDefaulter, axisName)
    );
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AxisModel = ComponentModel.extend({

    type: 'cartesian2dAxis',

    /**
     * @type {module:echarts/coord/cartesian/Axis2D}
     */
    axis: null,

    /**
     * @override
     */
    init: function () {
        AxisModel.superApply(this, 'init', arguments);
        this.resetRange();
    },

    /**
     * @override
     */
    mergeOption: function () {
        AxisModel.superApply(this, 'mergeOption', arguments);
        this.resetRange();
    },

    /**
     * @override
     */
    restoreData: function () {
        AxisModel.superApply(this, 'restoreData', arguments);
        this.resetRange();
    },

    /**
     * @override
     * @return {module:echarts/model/Component}
     */
    getCoordSysModel: function () {
        return this.ecModel.queryComponents({
            mainType: 'grid',
            index: this.option.gridIndex,
            id: this.option.gridId
        })[0];
    }

});

function getAxisType(axisDim, option) {
    // Default axis with data is category axis
    return option.type || (option.data ? 'category' : 'value');
}

merge(AxisModel.prototype, axisModelCommonMixin);

var extraOption = {
    // gridIndex: 0,
    // gridId: '',

    // Offset is for multiple axis on the same position
    offset: 0
};

axisModelCreator('x', AxisModel, getAxisType, extraOption);
axisModelCreator('y', AxisModel, getAxisType, extraOption);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Grid 是在有直角坐标系的时候必须要存在的
// 所以这里也要被 Cartesian2D 依赖

ComponentModel.extend({

    type: 'grid',

    dependencies: ['xAxis', 'yAxis'],

    layoutMode: 'box',

    /**
     * @type {module:echarts/coord/cartesian/Grid}
     */
    coordinateSystem: null,

    defaultOption: {
        show: false,
        zlevel: 0,
        z: 0,
        left: '10%',
        top: 60,
        right: '10%',
        bottom: 60,
        // If grid size contain label
        containLabel: false,
        // width: {totalWidth} - left - right,
        // height: {totalHeight} - top - bottom,
        backgroundColor: 'rgba(0,0,0,0)',
        borderWidth: 1,
        borderColor: '#ccc'
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Grid is a region which contains at most 4 cartesian systems
 *
 * TODO Default cartesian
 */

// Depends on GridModel, AxisModel, which performs preprocess.
/**
 * Check if the axis is used in the specified grid
 * @inner
 */
function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) {
    return axisModel.getCoordSysModel() === gridModel;
}

function Grid(gridModel, ecModel, api) {
    /**
     * @type {Object.<string, module:echarts/coord/cartesian/Cartesian2D>}
     * @private
     */
    this._coordsMap = {};

    /**
     * @type {Array.<module:echarts/coord/cartesian/Cartesian>}
     * @private
     */
    this._coordsList = [];

    /**
     * @type {Object.<string, Array.<module:echarts/coord/cartesian/Axis2D>>}
     * @private
     */
    this._axesMap = {};

    /**
     * @type {Array.<module:echarts/coord/cartesian/Axis2D>}
     * @private
     */
    this._axesList = [];

    this._initCartesian(gridModel, ecModel, api);

    this.model = gridModel;
}

var gridProto = Grid.prototype;

gridProto.type = 'grid';

gridProto.axisPointerEnabled = true;

gridProto.getRect = function () {
    return this._rect;
};

gridProto.update = function (ecModel, api) {

    var axesMap = this._axesMap;

    this._updateScale(ecModel, this.model);

    each$1(axesMap.x, function (xAxis) {
        niceScaleExtent(xAxis.scale, xAxis.model);
    });
    each$1(axesMap.y, function (yAxis) {
        niceScaleExtent(yAxis.scale, yAxis.model);
    });

    // Key: axisDim_axisIndex, value: boolean, whether onZero target.
    var onZeroRecords = {};

    each$1(axesMap.x, function (xAxis) {
        fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords);
    });
    each$1(axesMap.y, function (yAxis) {
        fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords);
    });

    // Resize again if containLabel is enabled
    // FIXME It may cause getting wrong grid size in data processing stage
    this.resize(this.model, api);
};

function fixAxisOnZero(axesMap, otherAxisDim, axis, onZeroRecords) {

    axis.getAxesOnZeroOf = function () {
        // TODO: onZero of multiple axes.
        return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : [];
    };

    // onZero can not be enabled in these two situations:
    // 1. When any other axis is a category axis.
    // 2. When no axis is cross 0 point.
    var otherAxes = axesMap[otherAxisDim];

    var otherAxisOnZeroOf;
    var axisModel = axis.model;
    var onZero = axisModel.get('axisLine.onZero');
    var onZeroAxisIndex = axisModel.get('axisLine.onZeroAxisIndex');

    if (!onZero) {
        return;
    }

    // If target axis is specified.
    if (onZeroAxisIndex != null) {
        if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) {
            otherAxisOnZeroOf = otherAxes[onZeroAxisIndex];
        }
    }
    else {
        // Find the first available other axis.
        for (var idx in otherAxes) {
            if (otherAxes.hasOwnProperty(idx)
                && canOnZeroToAxis(otherAxes[idx])
                // Consider that two Y axes on one value axis,
                // if both onZero, the two Y axes overlap.
                && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]
            ) {
                otherAxisOnZeroOf = otherAxes[idx];
                break;
            }
        }
    }

    if (otherAxisOnZeroOf) {
        onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true;
    }

    function getOnZeroRecordKey(axis) {
        return axis.dim + '_' + axis.index;
    }
}

function canOnZeroToAxis(axis) {
    return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis);
}

/**
 * Resize the grid
 * @param {module:echarts/coord/cartesian/GridModel} gridModel
 * @param {module:echarts/ExtensionAPI} api
 */
gridProto.resize = function (gridModel, api, ignoreContainLabel) {

    var gridRect = getLayoutRect(
        gridModel.getBoxLayoutParams(), {
            width: api.getWidth(),
            height: api.getHeight()
        });

    this._rect = gridRect;

    var axesList = this._axesList;

    adjustAxes();

    // Minus label size
    if (!ignoreContainLabel && gridModel.get('containLabel')) {
        each$1(axesList, function (axis) {
            if (!axis.model.get('axisLabel.inside')) {
                var labelUnionRect = estimateLabelUnionRect(axis);
                if (labelUnionRect) {
                    var dim = axis.isHorizontal() ? 'height' : 'width';
                    var margin = axis.model.get('axisLabel.margin');
                    gridRect[dim] -= labelUnionRect[dim] + margin;
                    if (axis.position === 'top') {
                        gridRect.y += labelUnionRect.height + margin;
                    }
                    else if (axis.position === 'left') {
                        gridRect.x += labelUnionRect.width + margin;
                    }
                }
            }
        });

        adjustAxes();
    }

    function adjustAxes() {
        each$1(axesList, function (axis) {
            var isHorizontal = axis.isHorizontal();
            var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height];
            var idx = axis.inverse ? 1 : 0;
            axis.setExtent(extent[idx], extent[1 - idx]);
            updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y);
        });
    }
};

/**
 * @param {string} axisType
 * @param {number} [axisIndex]
 */
gridProto.getAxis = function (axisType, axisIndex) {
    var axesMapOnDim = this._axesMap[axisType];
    if (axesMapOnDim != null) {
        if (axisIndex == null) {
            // Find first axis
            for (var name in axesMapOnDim) {
                if (axesMapOnDim.hasOwnProperty(name)) {
                    return axesMapOnDim[name];
                }
            }
        }
        return axesMapOnDim[axisIndex];
    }
};

/**
 * @return {Array.<module:echarts/coord/Axis>}
 */
gridProto.getAxes = function () {
    return this._axesList.slice();
};

/**
 * Usage:
 *      grid.getCartesian(xAxisIndex, yAxisIndex);
 *      grid.getCartesian(xAxisIndex);
 *      grid.getCartesian(null, yAxisIndex);
 *      grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...});
 *
 * @param {number|Object} [xAxisIndex]
 * @param {number} [yAxisIndex]
 */
gridProto.getCartesian = function (xAxisIndex, yAxisIndex) {
    if (xAxisIndex != null && yAxisIndex != null) {
        var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
        return this._coordsMap[key];
    }

    if (isObject$1(xAxisIndex)) {
        yAxisIndex = xAxisIndex.yAxisIndex;
        xAxisIndex = xAxisIndex.xAxisIndex;
    }
    // When only xAxisIndex or yAxisIndex given, find its first cartesian.
    for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) {
        if (coordList[i].getAxis('x').index === xAxisIndex
            || coordList[i].getAxis('y').index === yAxisIndex
        ) {
            return coordList[i];
        }
    }
};

gridProto.getCartesians = function () {
    return this._coordsList.slice();
};

/**
 * @implements
 * see {module:echarts/CoodinateSystem}
 */
gridProto.convertToPixel = function (ecModel, finder, value) {
    var target = this._findConvertTarget(ecModel, finder);

    return target.cartesian
        ? target.cartesian.dataToPoint(value)
        : target.axis
        ? target.axis.toGlobalCoord(target.axis.dataToCoord(value))
        : null;
};

/**
 * @implements
 * see {module:echarts/CoodinateSystem}
 */
gridProto.convertFromPixel = function (ecModel, finder, value) {
    var target = this._findConvertTarget(ecModel, finder);

    return target.cartesian
        ? target.cartesian.pointToData(value)
        : target.axis
        ? target.axis.coordToData(target.axis.toLocalCoord(value))
        : null;
};

/**
 * @inner
 */
gridProto._findConvertTarget = function (ecModel, finder) {
    var seriesModel = finder.seriesModel;
    var xAxisModel = finder.xAxisModel
        || (seriesModel && seriesModel.getReferringComponents('xAxis')[0]);
    var yAxisModel = finder.yAxisModel
        || (seriesModel && seriesModel.getReferringComponents('yAxis')[0]);
    var gridModel = finder.gridModel;
    var coordsList = this._coordsList;
    var cartesian;
    var axis;

    if (seriesModel) {
        cartesian = seriesModel.coordinateSystem;
        indexOf(coordsList, cartesian) < 0 && (cartesian = null);
    }
    else if (xAxisModel && yAxisModel) {
        cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
    }
    else if (xAxisModel) {
        axis = this.getAxis('x', xAxisModel.componentIndex);
    }
    else if (yAxisModel) {
        axis = this.getAxis('y', yAxisModel.componentIndex);
    }
    // Lowest priority.
    else if (gridModel) {
        var grid = gridModel.coordinateSystem;
        if (grid === this) {
            cartesian = this._coordsList[0];
        }
    }

    return {cartesian: cartesian, axis: axis};
};

/**
 * @implements
 * see {module:echarts/CoodinateSystem}
 */
gridProto.containPoint = function (point) {
    var coord = this._coordsList[0];
    if (coord) {
        return coord.containPoint(point);
    }
};

/**
 * Initialize cartesian coordinate systems
 * @private
 */
gridProto._initCartesian = function (gridModel, ecModel, api) {
    var axisPositionUsed = {
        left: false,
        right: false,
        top: false,
        bottom: false
    };

    var axesMap = {
        x: {},
        y: {}
    };
    var axesCount = {
        x: 0,
        y: 0
    };

    /// Create axis
    ecModel.eachComponent('xAxis', createAxisCreator('x'), this);
    ecModel.eachComponent('yAxis', createAxisCreator('y'), this);

    if (!axesCount.x || !axesCount.y) {
        // Roll back when there no either x or y axis
        this._axesMap = {};
        this._axesList = [];
        return;
    }

    this._axesMap = axesMap;

    /// Create cartesian2d
    each$1(axesMap.x, function (xAxis, xAxisIndex) {
        each$1(axesMap.y, function (yAxis, yAxisIndex) {
            var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
            var cartesian = new Cartesian2D(key);

            cartesian.grid = this;
            cartesian.model = gridModel;

            this._coordsMap[key] = cartesian;
            this._coordsList.push(cartesian);

            cartesian.addAxis(xAxis);
            cartesian.addAxis(yAxis);
        }, this);
    }, this);

    function createAxisCreator(axisType) {
        return function (axisModel, idx) {
            if (!isAxisUsedInTheGrid(axisModel, gridModel, ecModel)) {
                return;
            }

            var axisPosition = axisModel.get('position');
            if (axisType === 'x') {
                // Fix position
                if (axisPosition !== 'top' && axisPosition !== 'bottom') {
                    // Default bottom of X
                    axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom';
                }
            }
            else {
                // Fix position
                if (axisPosition !== 'left' && axisPosition !== 'right') {
                    // Default left of Y
                    axisPosition = axisPositionUsed.left ? 'right' : 'left';
                }
            }
            axisPositionUsed[axisPosition] = true;

            var axis = new Axis2D(
                axisType, createScaleByModel(axisModel),
                [0, 0],
                axisModel.get('type'),
                axisPosition
            );

            var isCategory = axis.type === 'category';
            axis.onBand = isCategory && axisModel.get('boundaryGap');
            axis.inverse = axisModel.get('inverse');

            // Inject axis into axisModel
            axisModel.axis = axis;

            // Inject axisModel into axis
            axis.model = axisModel;

            // Inject grid info axis
            axis.grid = this;

            // Index of axis, can be used as key
            axis.index = idx;

            this._axesList.push(axis);

            axesMap[axisType][idx] = axis;
            axesCount[axisType]++;
        };
    }
};

/**
 * Update cartesian properties from series
 * @param  {module:echarts/model/Option} option
 * @private
 */
gridProto._updateScale = function (ecModel, gridModel) {
    // Reset scale
    each$1(this._axesList, function (axis) {
        axis.scale.setExtent(Infinity, -Infinity);
    });
    ecModel.eachSeries(function (seriesModel) {
        if (isCartesian2D(seriesModel)) {
            var axesModels = findAxesModels(seriesModel, ecModel);
            var xAxisModel = axesModels[0];
            var yAxisModel = axesModels[1];

            if (!isAxisUsedInTheGrid(xAxisModel, gridModel, ecModel)
                || !isAxisUsedInTheGrid(yAxisModel, gridModel, ecModel)
            ) {
                return;
            }

            var cartesian = this.getCartesian(
                xAxisModel.componentIndex, yAxisModel.componentIndex
            );
            var data = seriesModel.getData();
            var xAxis = cartesian.getAxis('x');
            var yAxis = cartesian.getAxis('y');

            if (data.type === 'list') {
                unionExtent(data, xAxis, seriesModel);
                unionExtent(data, yAxis, seriesModel);
            }
        }
    }, this);

    function unionExtent(data, axis, seriesModel) {
        each$1(data.mapDimension(axis.dim, true), function (dim) {
            axis.scale.unionExtentFromData(
                // For example, the extent of the orginal dimension
                // is [0.1, 0.5], the extent of the `stackResultDimension`
                // is [7, 9], the final extent should not include [0.1, 0.5].
                data, getStackedDimension(data, dim)
            );
        });
    }
};

/**
 * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined
 * @return {Object} {baseAxes: [], otherAxes: []}
 */
gridProto.getTooltipAxes = function (dim) {
    var baseAxes = [];
    var otherAxes = [];

    each$1(this.getCartesians(), function (cartesian) {
        var baseAxis = (dim != null && dim !== 'auto')
            ? cartesian.getAxis(dim) : cartesian.getBaseAxis();
        var otherAxis = cartesian.getOtherAxis(baseAxis);
        indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
        indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
    });

    return {baseAxes: baseAxes, otherAxes: otherAxes};
};

/**
 * @inner
 */
function updateAxisTransform(axis, coordBase) {
    var axisExtent = axis.getExtent();
    var axisExtentSum = axisExtent[0] + axisExtent[1];

    // Fast transform
    axis.toGlobalCoord = axis.dim === 'x'
        ? function (coord) {
            return coord + coordBase;
        }
        : function (coord) {
            return axisExtentSum - coord + coordBase;
        };
    axis.toLocalCoord = axis.dim === 'x'
        ? function (coord) {
            return coord - coordBase;
        }
        : function (coord) {
            return axisExtentSum - coord + coordBase;
        };
}

var axesTypes = ['xAxis', 'yAxis'];
/**
 * @inner
 */
function findAxesModels(seriesModel, ecModel) {
    return map(axesTypes, function (axisType) {
        var axisModel = seriesModel.getReferringComponents(axisType)[0];

        if (__DEV__) {
            if (!axisModel) {
                throw new Error(axisType + ' "' + retrieve(
                    seriesModel.get(axisType + 'Index'),
                    seriesModel.get(axisType + 'Id'),
                    0
                ) + '" not found');
            }
        }
        return axisModel;
    });
}

/**
 * @inner
 */
function isCartesian2D(seriesModel) {
    return seriesModel.get('coordinateSystem') === 'cartesian2d';
}

Grid.create = function (ecModel, api) {
    var grids = [];
    ecModel.eachComponent('grid', function (gridModel, idx) {
        var grid = new Grid(gridModel, ecModel, api);
        grid.name = 'grid_' + idx;
        // dataSampling requires axis extent, so resize
        // should be performed in create stage.
        grid.resize(gridModel, api, true);

        gridModel.coordinateSystem = grid;

        grids.push(grid);
    });

    // Inject the coordinateSystems into seriesModel
    ecModel.eachSeries(function (seriesModel) {
        if (!isCartesian2D(seriesModel)) {
            return;
        }

        var axesModels = findAxesModels(seriesModel, ecModel);
        var xAxisModel = axesModels[0];
        var yAxisModel = axesModels[1];

        var gridModel = xAxisModel.getCoordSysModel();

        if (__DEV__) {
            if (!gridModel) {
                throw new Error(
                    'Grid "' + retrieve(
                        xAxisModel.get('gridIndex'),
                        xAxisModel.get('gridId'),
                        0
                    ) + '" not found'
                );
            }
            if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) {
                throw new Error('xAxis and yAxis must use the same grid');
            }
        }

        var grid = gridModel.coordinateSystem;

        seriesModel.coordinateSystem = grid.getCartesian(
            xAxisModel.componentIndex, yAxisModel.componentIndex
        );
    });

    return grids;
};

// For deciding which dimensions to use when creating list data
Grid.dimensions = Grid.prototype.dimensions = Cartesian2D.prototype.dimensions;

CoordinateSystemManager.register('cartesian2d', Grid);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PI$2 = Math.PI;

/**
 * A final axis is translated and rotated from a "standard axis".
 * So opt.position and opt.rotation is required.
 *
 * A standard axis is and axis from [0, 0] to [0, axisExtent[1]],
 * for example: (0, 0) ------------> (0, 50)
 *
 * nameDirection or tickDirection or labelDirection is 1 means tick
 * or label is below the standard axis, whereas is -1 means above
 * the standard axis. labelOffset means offset between label and axis,
 * which is useful when 'onZero', where axisLabel is in the grid and
 * label in outside grid.
 *
 * Tips: like always,
 * positive rotation represents anticlockwise, and negative rotation
 * represents clockwise.
 * The direction of position coordinate is the same as the direction
 * of screen coordinate.
 *
 * Do not need to consider axis 'inverse', which is auto processed by
 * axis extent.
 *
 * @param {module:zrender/container/Group} group
 * @param {Object} axisModel
 * @param {Object} opt Standard axis parameters.
 * @param {Array.<number>} opt.position [x, y]
 * @param {number} opt.rotation by radian
 * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle' or 'center'.
 * @param {number} [opt.tickDirection=1] 1 or -1
 * @param {number} [opt.labelDirection=1] 1 or -1
 * @param {number} [opt.labelOffset=0] Usefull when onZero.
 * @param {string} [opt.axisLabelShow] default get from axisModel.
 * @param {string} [opt.axisName] default get from axisModel.
 * @param {number} [opt.axisNameAvailableWidth]
 * @param {number} [opt.labelRotate] by degree, default get from axisModel.
 * @param {number} [opt.strokeContainThreshold] Default label interval when label
 * @param {number} [opt.nameTruncateMaxWidth]
 */
var AxisBuilder = function (axisModel, opt) {

    /**
     * @readOnly
     */
    this.opt = opt;

    /**
     * @readOnly
     */
    this.axisModel = axisModel;

    // Default value
    defaults(
        opt,
        {
            labelOffset: 0,
            nameDirection: 1,
            tickDirection: 1,
            labelDirection: 1,
            silent: true
        }
    );

    /**
     * @readOnly
     */
    this.group = new Group();

    // FIXME Not use a seperate text group?
    var dumbGroup = new Group({
        position: opt.position.slice(),
        rotation: opt.rotation
    });

    // this.group.add(dumbGroup);
    // this._dumbGroup = dumbGroup;

    dumbGroup.updateTransform();
    this._transform = dumbGroup.transform;

    this._dumbGroup = dumbGroup;
};

AxisBuilder.prototype = {

    constructor: AxisBuilder,

    hasBuilder: function (name) {
        return !!builders[name];
    },

    add: function (name) {
        builders[name].call(this);
    },

    getGroup: function () {
        return this.group;
    }

};

var builders = {

    /**
     * @private
     */
    axisLine: function () {
        var opt = this.opt;
        var axisModel = this.axisModel;

        if (!axisModel.get('axisLine.show')) {
            return;
        }

        var extent = this.axisModel.axis.getExtent();

        var matrix = this._transform;
        var pt1 = [extent[0], 0];
        var pt2 = [extent[1], 0];
        if (matrix) {
            applyTransform(pt1, pt1, matrix);
            applyTransform(pt2, pt2, matrix);
        }

        var lineStyle = extend(
            {
                lineCap: 'round'
            },
            axisModel.getModel('axisLine.lineStyle').getLineStyle()
        );

        this.group.add(new Line({
            // Id for animation
            anid: 'line',
            subPixelOptimize: true,
            shape: {
                x1: pt1[0],
                y1: pt1[1],
                x2: pt2[0],
                y2: pt2[1]
            },
            style: lineStyle,
            strokeContainThreshold: opt.strokeContainThreshold || 5,
            silent: true,
            z2: 1
        }));

        var arrows = axisModel.get('axisLine.symbol');
        var arrowSize = axisModel.get('axisLine.symbolSize');

        var arrowOffset = axisModel.get('axisLine.symbolOffset') || 0;
        if (typeof arrowOffset === 'number') {
            arrowOffset = [arrowOffset, arrowOffset];
        }

        if (arrows != null) {
            if (typeof arrows === 'string') {
                // Use the same arrow for start and end point
                arrows = [arrows, arrows];
            }
            if (typeof arrowSize === 'string'
                || typeof arrowSize === 'number'
            ) {
                // Use the same size for width and height
                arrowSize = [arrowSize, arrowSize];
            }

            var symbolWidth = arrowSize[0];
            var symbolHeight = arrowSize[1];

            each$1([{
                rotate: opt.rotation + Math.PI / 2,
                offset: arrowOffset[0],
                r: 0
            }, {
                rotate: opt.rotation - Math.PI / 2,
                offset: arrowOffset[1],
                r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0])
                    + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
            }], function (point, index) {
                if (arrows[index] !== 'none' && arrows[index] != null) {
                    var symbol = createSymbol(
                        arrows[index],
                        -symbolWidth / 2,
                        -symbolHeight / 2,
                        symbolWidth,
                        symbolHeight,
                        lineStyle.stroke,
                        true
                    );

                    // Calculate arrow position with offset
                    var r = point.r + point.offset;
                    var pos = [
                        pt1[0] + r * Math.cos(opt.rotation),
                        pt1[1] - r * Math.sin(opt.rotation)
                    ];

                    symbol.attr({
                        rotation: point.rotate,
                        position: pos,
                        silent: true,
                        z2: 11
                    });
                    this.group.add(symbol);
                }
            }, this);
        }
    },

    /**
     * @private
     */
    axisTickLabel: function () {
        var axisModel = this.axisModel;
        var opt = this.opt;

        var tickEls = buildAxisTick(this, axisModel, opt);
        var labelEls = buildAxisLabel(this, axisModel, opt);

        fixMinMaxLabelShow(axisModel, labelEls, tickEls);
    },

    /**
     * @private
     */
    axisName: function () {
        var opt = this.opt;
        var axisModel = this.axisModel;
        var name = retrieve(opt.axisName, axisModel.get('name'));

        if (!name) {
            return;
        }

        var nameLocation = axisModel.get('nameLocation');
        var nameDirection = opt.nameDirection;
        var textStyleModel = axisModel.getModel('nameTextStyle');
        var gap = axisModel.get('nameGap') || 0;

        var extent = this.axisModel.axis.getExtent();
        var gapSignal = extent[0] > extent[1] ? -1 : 1;
        var pos = [
            nameLocation === 'start'
                ? extent[0] - gapSignal * gap
                : nameLocation === 'end'
                ? extent[1] + gapSignal * gap
                : (extent[0] + extent[1]) / 2, // 'middle'
            // Reuse labelOffset.
            isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0
        ];

        var labelLayout;

        var nameRotation = axisModel.get('nameRotate');
        if (nameRotation != null) {
            nameRotation = nameRotation * PI$2 / 180; // To radian.
        }

        var axisNameAvailableWidth;

        if (isNameLocationCenter(nameLocation)) {
            labelLayout = innerTextLayout(
                opt.rotation,
                nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis.
                nameDirection
            );
        }
        else {
            labelLayout = endTextLayout(
                opt, nameLocation, nameRotation || 0, extent
            );

            axisNameAvailableWidth = opt.axisNameAvailableWidth;
            if (axisNameAvailableWidth != null) {
                axisNameAvailableWidth = Math.abs(
                    axisNameAvailableWidth / Math.sin(labelLayout.rotation)
                );
                !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null);
            }
        }

        var textFont = textStyleModel.getFont();

        var truncateOpt = axisModel.get('nameTruncate', true) || {};
        var ellipsis = truncateOpt.ellipsis;
        var maxWidth = retrieve(
            opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth
        );
        // FIXME
        // truncate rich text? (consider performance)
        var truncatedText = (ellipsis != null && maxWidth != null)
            ? truncateText$1(
                name, maxWidth, textFont, ellipsis,
                {minChar: 2, placeholder: truncateOpt.placeholder}
            )
            : name;

        var tooltipOpt = axisModel.get('tooltip', true);

        var mainType = axisModel.mainType;
        var formatterParams = {
            componentType: mainType,
            name: name,
            $vars: ['name']
        };
        formatterParams[mainType + 'Index'] = axisModel.componentIndex;

        var textEl = new Text({
            // Id for animation
            anid: 'name',

            __fullText: name,
            __truncatedText: truncatedText,

            position: pos,
            rotation: labelLayout.rotation,
            silent: isLabelSilent(axisModel),
            z2: 1,
            tooltip: (tooltipOpt && tooltipOpt.show)
                ? extend({
                    content: name,
                    formatter: function () {
                        return name;
                    },
                    formatterParams: formatterParams
                }, tooltipOpt)
                : null
        });

        setTextStyle(textEl.style, textStyleModel, {
            text: truncatedText,
            textFont: textFont,
            textFill: textStyleModel.getTextColor()
                || axisModel.get('axisLine.lineStyle.color'),
            textAlign: textStyleModel.get('align')
                || labelLayout.textAlign,
            textVerticalAlign: textStyleModel.get('verticalAlign')
                || labelLayout.textVerticalAlign
        });

        if (axisModel.get('triggerEvent')) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisName';
            textEl.eventData.name = name;
        }

        // FIXME
        this._dumbGroup.add(textEl);
        textEl.updateTransform();

        this.group.add(textEl);

        textEl.decomposeTransform();
    }

};

var makeAxisEventDataBase = AxisBuilder.makeAxisEventDataBase = function (axisModel) {
    var eventData = {
        componentType: axisModel.mainType,
        componentIndex: axisModel.componentIndex
    };
    eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
    return eventData;
};

/**
 * @public
 * @static
 * @param {Object} opt
 * @param {number} axisRotation in radian
 * @param {number} textRotation in radian
 * @param {number} direction
 * @return {Object} {
 *  rotation, // according to axis
 *  textAlign,
 *  textVerticalAlign
 * }
 */
var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
    var rotationDiff = remRadian(textRotation - axisRotation);
    var textAlign;
    var textVerticalAlign;

    if (isRadianAroundZero(rotationDiff)) { // Label is parallel with axis line.
        textVerticalAlign = direction > 0 ? 'top' : 'bottom';
        textAlign = 'center';
    }
    else if (isRadianAroundZero(rotationDiff - PI$2)) { // Label is inverse parallel with axis line.
        textVerticalAlign = direction > 0 ? 'bottom' : 'top';
        textAlign = 'center';
    }
    else {
        textVerticalAlign = 'middle';

        if (rotationDiff > 0 && rotationDiff < PI$2) {
            textAlign = direction > 0 ? 'right' : 'left';
        }
        else {
            textAlign = direction > 0 ? 'left' : 'right';
        }
    }

    return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
    };
};

function endTextLayout(opt, textPosition, textRotate, extent) {
    var rotationDiff = remRadian(textRotate - opt.rotation);
    var textAlign;
    var textVerticalAlign;
    var inverse = extent[0] > extent[1];
    var onLeft = (textPosition === 'start' && !inverse)
        || (textPosition !== 'start' && inverse);

    if (isRadianAroundZero(rotationDiff - PI$2 / 2)) {
        textVerticalAlign = onLeft ? 'bottom' : 'top';
        textAlign = 'center';
    }
    else if (isRadianAroundZero(rotationDiff - PI$2 * 1.5)) {
        textVerticalAlign = onLeft ? 'top' : 'bottom';
        textAlign = 'center';
    }
    else {
        textVerticalAlign = 'middle';
        if (rotationDiff < PI$2 * 1.5 && rotationDiff > PI$2 / 2) {
            textAlign = onLeft ? 'left' : 'right';
        }
        else {
            textAlign = onLeft ? 'right' : 'left';
        }
    }

    return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
    };
}

var isLabelSilent = AxisBuilder.isLabelSilent = function (axisModel) {
    var tooltipOpt = axisModel.get('tooltip');
    return axisModel.get('silent')
        // Consider mouse cursor, add these restrictions.
        || !(
            axisModel.get('triggerEvent') || (tooltipOpt && tooltipOpt.show)
        );
};

function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
    if (shouldShowAllLabels(axisModel.axis)) {
        return;
    }

    // If min or max are user set, we need to check
    // If the tick on min(max) are overlap on their neighbour tick
    // If they are overlapped, we need to hide the min(max) tick label
    var showMinLabel = axisModel.get('axisLabel.showMinLabel');
    var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');

    // FIXME
    // Have not consider onBand yet, where tick els is more than label els.

    labelEls = labelEls || [];
    tickEls = tickEls || [];

    var firstLabel = labelEls[0];
    var nextLabel = labelEls[1];
    var lastLabel = labelEls[labelEls.length - 1];
    var prevLabel = labelEls[labelEls.length - 2];

    var firstTick = tickEls[0];
    var nextTick = tickEls[1];
    var lastTick = tickEls[tickEls.length - 1];
    var prevTick = tickEls[tickEls.length - 2];

    if (showMinLabel === false) {
        ignoreEl(firstLabel);
        ignoreEl(firstTick);
    }
    else if (isTwoLabelOverlapped(firstLabel, nextLabel)) {
        if (showMinLabel) {
            ignoreEl(nextLabel);
            ignoreEl(nextTick);
        }
        else {
            ignoreEl(firstLabel);
            ignoreEl(firstTick);
        }
    }

    if (showMaxLabel === false) {
        ignoreEl(lastLabel);
        ignoreEl(lastTick);
    }
    else if (isTwoLabelOverlapped(prevLabel, lastLabel)) {
        if (showMaxLabel) {
            ignoreEl(prevLabel);
            ignoreEl(prevTick);
        }
        else {
            ignoreEl(lastLabel);
            ignoreEl(lastTick);
        }
    }
}

function ignoreEl(el) {
    el && (el.ignore = true);
}

function isTwoLabelOverlapped(current, next, labelLayout) {
    // current and next has the same rotation.
    var firstRect = current && current.getBoundingRect().clone();
    var nextRect = next && next.getBoundingRect().clone();

    if (!firstRect || !nextRect) {
        return;
    }

    // When checking intersect of two rotated labels, we use mRotationBack
    // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.
    var mRotationBack = identity([]);
    rotate(mRotationBack, mRotationBack, -current.rotation);

    firstRect.applyTransform(mul$1([], mRotationBack, current.getLocalTransform()));
    nextRect.applyTransform(mul$1([], mRotationBack, next.getLocalTransform()));

    return firstRect.intersect(nextRect);
}

function isNameLocationCenter(nameLocation) {
    return nameLocation === 'middle' || nameLocation === 'center';
}

function buildAxisTick(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;

    if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
        return;
    }

    var tickModel = axisModel.getModel('axisTick');

    var lineStyleModel = tickModel.getModel('lineStyle');
    var tickLen = tickModel.get('length');

    var ticksCoords = axis.getTicksCoords();

    var pt1 = [];
    var pt2 = [];
    var matrix = axisBuilder._transform;

    var tickEls = [];

    for (var i = 0; i < ticksCoords.length; i++) {
        var tickCoord = ticksCoords[i].coord;

        pt1[0] = tickCoord;
        pt1[1] = 0;
        pt2[0] = tickCoord;
        pt2[1] = opt.tickDirection * tickLen;

        if (matrix) {
            applyTransform(pt1, pt1, matrix);
            applyTransform(pt2, pt2, matrix);
        }
        // Tick line, Not use group transform to have better line draw
        var tickEl = new Line({
            // Id for animation
            anid: 'tick_' + ticksCoords[i].tickValue,
            subPixelOptimize: true,
            shape: {
                x1: pt1[0],
                y1: pt1[1],
                x2: pt2[0],
                y2: pt2[1]
            },
            style: defaults(
                lineStyleModel.getLineStyle(),
                {
                    stroke: axisModel.get('axisLine.lineStyle.color')
                }
            ),
            z2: 2,
            silent: true
        });
        axisBuilder.group.add(tickEl);
        tickEls.push(tickEl);
    }

    return tickEls;
}

function buildAxisLabel(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;
    var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));

    if (!show || axis.scale.isBlank()) {
        return;
    }

    var labelModel = axisModel.getModel('axisLabel');
    var labelMargin = labelModel.get('margin');
    var labels = axis.getViewLabels();

    // Special label rotate.
    var labelRotation = (
        retrieve(opt.labelRotate, labelModel.get('rotate')) || 0
    ) * PI$2 / 180;

    var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
    var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true);

    var labelEls = [];
    var silent = isLabelSilent(axisModel);
    var triggerEvent = axisModel.get('triggerEvent');

    each$1(labels, function (labelItem, index) {
        var tickValue = labelItem.tickValue;
        var formattedLabel = labelItem.formattedLabel;
        var rawLabel = labelItem.rawLabel;

        var itemLabelModel = labelModel;
        if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
            itemLabelModel = new Model(
                rawCategoryData[tickValue].textStyle, labelModel, axisModel.ecModel
            );
        }

        var textColor = itemLabelModel.getTextColor()
            || axisModel.get('axisLine.lineStyle.color');

        var tickCoord = axis.dataToCoord(tickValue);
        var pos = [
            tickCoord,
            opt.labelOffset + opt.labelDirection * labelMargin
        ];

        var textEl = new Text({
            // Id for animation
            anid: 'label_' + tickValue,
            position: pos,
            rotation: labelLayout.rotation,
            silent: silent,
            z2: 10
        });

        setTextStyle(textEl.style, itemLabelModel, {
            text: formattedLabel,
            textAlign: itemLabelModel.getShallow('align', true)
                || labelLayout.textAlign,
            textVerticalAlign: itemLabelModel.getShallow('verticalAlign', true)
                || itemLabelModel.getShallow('baseline', true)
                || labelLayout.textVerticalAlign,
            textFill: typeof textColor === 'function'
                ? textColor(
                    // (1) In category axis with data zoom, tick is not the original
                    // index of axis.data. So tick should not be exposed to user
                    // in category axis.
                    // (2) Compatible with previous version, which always use formatted label as
                    // input. But in interval scale the formatted label is like '223,445', which
                    // maked user repalce ','. So we modify it to return original val but remain
                    // it as 'string' to avoid error in replacing.
                    axis.type === 'category'
                        ? rawLabel
                        : axis.type === 'value'
                        ? tickValue + ''
                        : tickValue,
                    index
                )
                : textColor
        });

        // Pack data for mouse event
        if (triggerEvent) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisLabel';
            textEl.eventData.value = rawLabel;
        }

        // FIXME
        axisBuilder._dumbGroup.add(textEl);
        textEl.updateTransform();

        labelEls.push(textEl);
        axisBuilder.group.add(textEl);

        textEl.decomposeTransform();

    });

    return labelEls;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$6 = each$1;
var curry$1 = curry;

// Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
// allAxesInfo should be updated when setOption performed.
function collect(ecModel, api) {
    var result = {
        /**
         * key: makeKey(axis.model)
         * value: {
         *      axis,
         *      coordSys,
         *      axisPointerModel,
         *      triggerTooltip,
         *      involveSeries,
         *      snap,
         *      seriesModels,
         *      seriesDataCount
         * }
         */
        axesInfo: {},
        seriesInvolved: false,
        /**
         * key: makeKey(coordSys.model)
         * value: Object: key makeKey(axis.model), value: axisInfo
         */
        coordSysAxesInfo: {},
        coordSysMap: {}
    };

    collectAxesInfo(result, ecModel, api);

    // Check seriesInvolved for performance, in case too many series in some chart.
    result.seriesInvolved && collectSeriesInfo(result, ecModel);

    return result;
}

function collectAxesInfo(result, ecModel, api) {
    var globalTooltipModel = ecModel.getComponent('tooltip');
    var globalAxisPointerModel = ecModel.getComponent('axisPointer');
    // links can only be set on global.
    var linksOption = globalAxisPointerModel.get('link', true) || [];
    var linkGroups = [];

    // Collect axes info.
    each$6(api.getCoordinateSystems(), function (coordSys) {
        // Some coordinate system do not support axes, like geo.
        if (!coordSys.axisPointerEnabled) {
            return;
        }

        var coordSysKey = makeKey(coordSys.model);
        var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {};
        result.coordSysMap[coordSysKey] = coordSys;

        // Set tooltip (like 'cross') is a convienent way to show axisPointer
        // for user. So we enable seting tooltip on coordSys model.
        var coordSysModel = coordSys.model;
        var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel);

        each$6(coordSys.getAxes(), curry$1(saveTooltipAxisInfo, false, null));

        // If axis tooltip used, choose tooltip axis for each coordSys.
        // Notice this case: coordSys is `grid` but not `cartesian2D` here.
        if (coordSys.getTooltipAxes
            && globalTooltipModel
            // If tooltip.showContent is set as false, tooltip will not
            // show but axisPointer will show as normal.
            && baseTooltipModel.get('show')
        ) {
            // Compatible with previous logic. But series.tooltip.trigger: 'axis'
            // or series.data[n].tooltip.trigger: 'axis' are not support any more.
            var triggerAxis = baseTooltipModel.get('trigger') === 'axis';
            var cross = baseTooltipModel.get('axisPointer.type') === 'cross';
            var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get('axisPointer.axis'));
            if (triggerAxis || cross) {
                each$6(tooltipAxes.baseAxes, curry$1(
                    saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis
                ));
            }
            if (cross) {
                each$6(tooltipAxes.otherAxes, curry$1(saveTooltipAxisInfo, 'cross', false));
            }
        }

        // fromTooltip: true | false | 'cross'
        // triggerTooltip: true | false | null
        function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) {
            var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel);

            var axisPointerShow = axisPointerModel.get('show');
            if (!axisPointerShow || (
                axisPointerShow === 'auto'
                && !fromTooltip
                && !isHandleTrigger(axisPointerModel)
            )) {
                return;
            }

            if (triggerTooltip == null) {
                triggerTooltip = axisPointerModel.get('triggerTooltip');
            }

            axisPointerModel = fromTooltip
                ? makeAxisPointerModel(
                    axis, baseTooltipModel, globalAxisPointerModel, ecModel,
                    fromTooltip, triggerTooltip
                )
                : axisPointerModel;

            var snap = axisPointerModel.get('snap');
            var key = makeKey(axis.model);
            var involveSeries = triggerTooltip || snap || axis.type === 'category';

            // If result.axesInfo[key] exist, override it (tooltip has higher priority).
            var axisInfo = result.axesInfo[key] = {
                key: key,
                axis: axis,
                coordSys: coordSys,
                axisPointerModel: axisPointerModel,
                triggerTooltip: triggerTooltip,
                involveSeries: involveSeries,
                snap: snap,
                useHandle: isHandleTrigger(axisPointerModel),
                seriesModels: []
            };
            axesInfoInCoordSys[key] = axisInfo;
            result.seriesInvolved |= involveSeries;

            var groupIndex = getLinkGroupIndex(linksOption, axis);
            if (groupIndex != null) {
                var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {axesInfo: {}});
                linkGroup.axesInfo[key] = axisInfo;
                linkGroup.mapper = linksOption[groupIndex].mapper;
                axisInfo.linkGroup = linkGroup;
            }
        }
    });
}

function makeAxisPointerModel(
    axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip
) {
    var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer');
    var volatileOption = {};

    each$6(
        [
            'type', 'snap', 'lineStyle', 'shadowStyle', 'label',
            'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z'
        ],
        function (field) {
            volatileOption[field] = clone(tooltipAxisPointerModel.get(field));
        }
    );

    // category axis do not auto snap, otherwise some tick that do not
    // has value can not be hovered. value/time/log axis default snap if
    // triggered from tooltip and trigger tooltip.
    volatileOption.snap = axis.type !== 'category' && !!triggerTooltip;

    // Compatibel with previous behavior, tooltip axis do not show label by default.
    // Only these properties can be overrided from tooltip to axisPointer.
    if (tooltipAxisPointerModel.get('type') === 'cross') {
        volatileOption.type = 'line';
    }
    var labelOption = volatileOption.label || (volatileOption.label = {});
    // Follow the convention, do not show label when triggered by tooltip by default.
    labelOption.show == null && (labelOption.show = false);

    if (fromTooltip === 'cross') {
        // When 'cross', both axes show labels.
        var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get('label.show');
        labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true;
        // If triggerTooltip, this is a base axis, which should better not use cross style
        // (cross style is dashed by default)
        if (!triggerTooltip) {
            var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle');
            crossStyle && defaults(labelOption, crossStyle.textStyle);
        }
    }

    return axis.model.getModel(
        'axisPointer',
        new Model(volatileOption, globalAxisPointerModel, ecModel)
    );
}

function collectSeriesInfo(result, ecModel) {
    // Prepare data for axis trigger
    ecModel.eachSeries(function (seriesModel) {

        // Notice this case: this coordSys is `cartesian2D` but not `grid`.
        var coordSys = seriesModel.coordinateSystem;
        var seriesTooltipTrigger = seriesModel.get('tooltip.trigger', true);
        var seriesTooltipShow = seriesModel.get('tooltip.show', true);
        if (!coordSys
            || seriesTooltipTrigger === 'none'
            || seriesTooltipTrigger === false
            || seriesTooltipTrigger === 'item'
            || seriesTooltipShow === false
            || seriesModel.get('axisPointer.show', true) === false
        ) {
            return;
        }

        each$6(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) {
            var axis = axisInfo.axis;
            if (coordSys.getAxis(axis.dim) === axis) {
                axisInfo.seriesModels.push(seriesModel);
                axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0);
                axisInfo.seriesDataCount += seriesModel.getData().count();
            }
        });

    }, this);
}

/**
 * For example:
 * {
 *     axisPointer: {
 *         links: [{
 *             xAxisIndex: [2, 4],
 *             yAxisIndex: 'all'
 *         }, {
 *             xAxisId: ['a5', 'a7'],
 *             xAxisName: 'xxx'
 *         }]
 *     }
 * }
 */
function getLinkGroupIndex(linksOption, axis) {
    var axisModel = axis.model;
    var dim = axis.dim;
    for (var i = 0; i < linksOption.length; i++) {
        var linkOption = linksOption[i] || {};
        if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id)
            || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex)
            || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)
        ) {
            return i;
        }
    }
}

function checkPropInLink(linkPropValue, axisPropValue) {
    return linkPropValue === 'all'
        || (isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0)
        || linkPropValue === axisPropValue;
}

function fixValue(axisModel) {
    var axisInfo = getAxisInfo(axisModel);
    if (!axisInfo) {
        return;
    }

    var axisPointerModel = axisInfo.axisPointerModel;
    var scale = axisInfo.axis.scale;
    var option = axisPointerModel.option;
    var status = axisPointerModel.get('status');
    var value = axisPointerModel.get('value');

    // Parse init value for category and time axis.
    if (value != null) {
        value = scale.parse(value);
    }

    var useHandle = isHandleTrigger(axisPointerModel);
    // If `handle` used, `axisPointer` will always be displayed, so value
    // and status should be initialized.
    if (status == null) {
        option.status = useHandle ? 'show' : 'hide';
    }

    var extent = scale.getExtent().slice();
    extent[0] > extent[1] && extent.reverse();

    if (// Pick a value on axis when initializing.
        value == null
        // If both `handle` and `dataZoom` are used, value may be out of axis extent,
        // where we should re-pick a value to keep `handle` displaying normally.
        || value > extent[1]
    ) {
        // Make handle displayed on the end of the axis when init, which looks better.
        value = extent[1];
    }
    if (value < extent[0]) {
        value = extent[0];
    }

    option.value = value;

    if (useHandle) {
        option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show';
    }
}

function getAxisInfo(axisModel) {
    var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo;
    return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)];
}

function getAxisPointerModel(axisModel) {
    var axisInfo = getAxisInfo(axisModel);
    return axisInfo && axisInfo.axisPointerModel;
}

function isHandleTrigger(axisPointerModel) {
    return !!axisPointerModel.get('handle.show');
}

/**
 * @param {module:echarts/model/Model} model
 * @return {string} unique key
 */
function makeKey(model) {
    return model.type + '||' + model.id;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Base class of AxisView.
 */
var AxisView = extendComponentView({

    type: 'axis',

    /**
     * @private
     */
    _axisPointer: null,

    /**
     * @protected
     * @type {string}
     */
    axisPointerClass: null,

    /**
     * @override
     */
    render: function (axisModel, ecModel, api, payload) {
        // FIXME
        // This process should proformed after coordinate systems updated
        // (axis scale updated), and should be performed each time update.
        // So put it here temporarily, although it is not appropriate to
        // put a model-writing procedure in `view`.
        this.axisPointerClass && fixValue(axisModel);

        AxisView.superApply(this, 'render', arguments);

        updateAxisPointer(this, axisModel, ecModel, api, payload, true);
    },

    /**
     * Action handler.
     * @public
     * @param {module:echarts/coord/cartesian/AxisModel} axisModel
     * @param {module:echarts/model/Global} ecModel
     * @param {module:echarts/ExtensionAPI} api
     * @param {Object} payload
     */
    updateAxisPointer: function (axisModel, ecModel, api, payload, force) {
        updateAxisPointer(this, axisModel, ecModel, api, payload, false);
    },

    /**
     * @override
     */
    remove: function (ecModel, api) {
        var axisPointer = this._axisPointer;
        axisPointer && axisPointer.remove(api);
        AxisView.superApply(this, 'remove', arguments);
    },

    /**
     * @override
     */
    dispose: function (ecModel, api) {
        disposeAxisPointer(this, api);
        AxisView.superApply(this, 'dispose', arguments);
    }

});

function updateAxisPointer(axisView, axisModel, ecModel, api, payload, forceRender) {
    var Clazz = AxisView.getAxisPointerClass(axisView.axisPointerClass);
    if (!Clazz) {
        return;
    }
    var axisPointerModel = getAxisPointerModel(axisModel);
    axisPointerModel
        ? (axisView._axisPointer || (axisView._axisPointer = new Clazz()))
            .render(axisModel, axisPointerModel, api, forceRender)
        : disposeAxisPointer(axisView, api);
}

function disposeAxisPointer(axisView, ecModel, api) {
    var axisPointer = axisView._axisPointer;
    axisPointer && axisPointer.dispose(ecModel, api);
    axisView._axisPointer = null;
}

var axisPointerClazz = [];

AxisView.registerAxisPointerClass = function (type, clazz) {
    if (__DEV__) {
        if (axisPointerClazz[type]) {
            throw new Error('axisPointer ' + type + ' exists');
        }
    }
    axisPointerClazz[type] = clazz;
};

AxisView.getAxisPointerClass = function (type) {
    return type && axisPointerClazz[type];
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Can only be called after coordinate system creation stage.
 * (Can be called before coordinate system update stage).
 *
 * @param {Object} opt {labelInside}
 * @return {Object} {
 *  position, rotation, labelDirection, labelOffset,
 *  tickDirection, labelRotate, z2
 * }
 */
function layout$1(gridModel, axisModel, opt) {
    opt = opt || {};
    var grid = gridModel.coordinateSystem;
    var axis = axisModel.axis;
    var layout = {};
    var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0];

    var rawAxisPosition = axis.position;
    var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition;
    var axisDim = axis.dim;

    var rect = grid.getRect();
    var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
    var idx = {left: 0, right: 1, top: 0, bottom: 1, onZero: 2};
    var axisOffset = axisModel.get('offset') || 0;

    var posBound = axisDim === 'x'
        ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset]
        : [rectBound[0] - axisOffset, rectBound[1] + axisOffset];

    if (otherAxisOnZeroOf) {
        var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0));
        posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]);
    }

    // Axis position
    layout.position = [
        axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0],
        axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]
    ];

    // Axis rotation
    layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1);

    // Tick and label direction, x y is axisDim
    var dirMap = {top: -1, bottom: 1, left: -1, right: 1};

    layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition];
    layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0;

    if (axisModel.get('axisTick.inside')) {
        layout.tickDirection = -layout.tickDirection;
    }
    if (retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) {
        layout.labelDirection = -layout.labelDirection;
    }

    // Special label rotation
    var labelRotate = axisModel.get('axisLabel.rotate');
    layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate;

    // Over splitLine and splitArea
    layout.z2 = 1;

    return layout;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var axisBuilderAttrs = [
    'axisLine', 'axisTickLabel', 'axisName'
];
var selfBuilderAttrs = [
    'splitArea', 'splitLine'
];

// function getAlignWithLabel(model, axisModel) {
//     var alignWithLabel = model.get('alignWithLabel');
//     if (alignWithLabel === 'auto') {
//         alignWithLabel = axisModel.get('axisTick.alignWithLabel');
//     }
//     return alignWithLabel;
// }

var CartesianAxisView = AxisView.extend({

    type: 'cartesianAxis',

    axisPointerClass: 'CartesianAxisPointer',

    /**
     * @override
     */
    render: function (axisModel, ecModel, api, payload) {

        this.group.removeAll();

        var oldAxisGroup = this._axisGroup;
        this._axisGroup = new Group();

        this.group.add(this._axisGroup);

        if (!axisModel.get('show')) {
            return;
        }

        var gridModel = axisModel.getCoordSysModel();

        var layout = layout$1(gridModel, axisModel);

        var axisBuilder = new AxisBuilder(axisModel, layout);

        each$1(axisBuilderAttrs, axisBuilder.add, axisBuilder);

        this._axisGroup.add(axisBuilder.getGroup());

        each$1(selfBuilderAttrs, function (name) {
            if (axisModel.get(name + '.show')) {
                this['_' + name](axisModel, gridModel);
            }
        }, this);

        groupTransition(oldAxisGroup, this._axisGroup, axisModel);

        CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
    },

    remove: function () {
        this._splitAreaColors = null;
    },

    /**
     * @param {module:echarts/coord/cartesian/AxisModel} axisModel
     * @param {module:echarts/coord/cartesian/GridModel} gridModel
     * @private
     */
    _splitLine: function (axisModel, gridModel) {
        var axis = axisModel.axis;

        if (axis.scale.isBlank()) {
            return;
        }

        var splitLineModel = axisModel.getModel('splitLine');
        var lineStyleModel = splitLineModel.getModel('lineStyle');
        var lineColors = lineStyleModel.get('color');

        lineColors = isArray(lineColors) ? lineColors : [lineColors];

        var gridRect = gridModel.coordinateSystem.getRect();
        var isHorizontal = axis.isHorizontal();

        var lineCount = 0;

        var ticksCoords = axis.getTicksCoords({
            tickModel: splitLineModel
        });

        var p1 = [];
        var p2 = [];

        // Simple optimization
        // Batching the lines if color are the same
        var lineStyle = lineStyleModel.getLineStyle();
        for (var i = 0; i < ticksCoords.length; i++) {
            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);

            if (isHorizontal) {
                p1[0] = tickCoord;
                p1[1] = gridRect.y;
                p2[0] = tickCoord;
                p2[1] = gridRect.y + gridRect.height;
            }
            else {
                p1[0] = gridRect.x;
                p1[1] = tickCoord;
                p2[0] = gridRect.x + gridRect.width;
                p2[1] = tickCoord;
            }

            var colorIndex = (lineCount++) % lineColors.length;
            var tickValue = ticksCoords[i].tickValue;
            this._axisGroup.add(new Line({
                anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null,
                subPixelOptimize: true,
                shape: {
                    x1: p1[0],
                    y1: p1[1],
                    x2: p2[0],
                    y2: p2[1]
                },
                style: defaults({
                    stroke: lineColors[colorIndex]
                }, lineStyle),
                silent: true
            }));
        }
    },

    /**
     * @param {module:echarts/coord/cartesian/AxisModel} axisModel
     * @param {module:echarts/coord/cartesian/GridModel} gridModel
     * @private
     */
    _splitArea: function (axisModel, gridModel) {
        var axis = axisModel.axis;

        if (axis.scale.isBlank()) {
            return;
        }

        var splitAreaModel = axisModel.getModel('splitArea');
        var areaStyleModel = splitAreaModel.getModel('areaStyle');
        var areaColors = areaStyleModel.get('color');

        var gridRect = gridModel.coordinateSystem.getRect();

        var ticksCoords = axis.getTicksCoords({
            tickModel: splitAreaModel,
            clamp: true
        });

        if (!ticksCoords.length) {
            return;
        }

        // For Making appropriate splitArea animation, the color and anid
        // should be corresponding to previous one if possible.
        var areaColorsLen = areaColors.length;
        var lastSplitAreaColors = this._splitAreaColors;
        var newSplitAreaColors = createHashMap();
        var colorIndex = 0;
        if (lastSplitAreaColors) {
            for (var i = 0; i < ticksCoords.length; i++) {
                var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
                if (cIndex != null) {
                    colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
                    break;
                }
            }
        }

        var prev = axis.toGlobalCoord(ticksCoords[0].coord);

        var areaStyle = areaStyleModel.getAreaStyle();
        areaColors = isArray(areaColors) ? areaColors : [areaColors];

        for (var i = 1; i < ticksCoords.length; i++) {
            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);

            var x;
            var y;
            var width;
            var height;
            if (axis.isHorizontal()) {
                x = prev;
                y = gridRect.y;
                width = tickCoord - x;
                height = gridRect.height;
                prev = x + width;
            }
            else {
                x = gridRect.x;
                y = prev;
                width = gridRect.width;
                height = tickCoord - y;
                prev = y + height;
            }

            var tickValue = ticksCoords[i - 1].tickValue;
            tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);

            this._axisGroup.add(new Rect({
                anid: tickValue != null ? 'area_' + tickValue : null,
                shape: {
                    x: x,
                    y: y,
                    width: width,
                    height: height
                },
                style: defaults({
                    fill: areaColors[colorIndex]
                }, areaStyle),
                silent: true
            }));

            colorIndex = (colorIndex + 1) % areaColorsLen;
        }

        this._splitAreaColors = newSplitAreaColors;
    }
});

CartesianAxisView.extend({
    type: 'xAxis'
});
CartesianAxisView.extend({
    type: 'yAxis'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Grid view
extendComponentView({

    type: 'grid',

    render: function (gridModel, ecModel) {
        this.group.removeAll();
        if (gridModel.get('show')) {
            this.group.add(new Rect({
                shape: gridModel.coordinateSystem.getRect(),
                style: defaults({
                    fill: gridModel.get('backgroundColor')
                }, gridModel.getItemStyle()),
                silent: true,
                z2: -1
            }));
        }
    }

});

registerPreprocessor(function (option) {
    // Only create grid when need
    if (option.xAxis && option.yAxis && !option.grid) {
        option.grid = {};
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// In case developer forget to include grid component
registerVisual(visualSymbol('line', 'circle', 'line'));
registerLayout(pointsLayout('line'));

// Down sample after filter
registerProcessor(
    PRIORITY.PROCESSOR.STATISTIC,
    dataSample('line')
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var BaseBarSeries = SeriesModel.extend({

    type: 'series.__base_bar__',

    getInitialData: function (option, ecModel) {
        return createListFromArray(this.getSource(), this);
    },

    getMarkerPosition: function (value) {
        var coordSys = this.coordinateSystem;
        if (coordSys) {
            // PENDING if clamp ?
            var pt = coordSys.dataToPoint(coordSys.clampData(value));
            var data = this.getData();
            var offset = data.getLayout('offset');
            var size = data.getLayout('size');
            var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1;
            pt[offsetIndex] += offset + size / 2;
            return pt;
        }
        return [NaN, NaN];
    },

    defaultOption: {
        zlevel: 0,                  // 一级层叠
        z: 2,                       // 二级层叠
        coordinateSystem: 'cartesian2d',
        legendHoverLink: true,
        // stack: null

        // Cartesian coordinate system
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // 最小高度改为0
        barMinHeight: 0,
        // 最小角度为0，仅对极坐标系下的柱状图有效
        barMinAngle: 0,
        // cursor: null,

        large: false,
        largeThreshold: 400,
        progressive: 3e3,
        progressiveChunkMode: 'mod',

        // barMaxWidth: null,

        // In cartesian, the default value is 1. Otherwise null.
        // barMinWidth: null,

        // 默认自适应
        // barWidth: null,
        // 柱间距离，默认为柱形宽度的30%，可设固定值
        // barGap: '30%',
        // 类目间柱形距离，默认为类目间距的20%，可设固定值
        // barCategoryGap: '20%',
        // label: {
        //      show: false
        // },
        itemStyle: {},
        emphasis: {}
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

BaseBarSeries.extend({

    type: 'series.bar',

    dependencies: ['grid', 'polar'],

    brushSelector: 'rect',

    /**
     * @override
     */
    getProgressive: function () {
        // Do not support progressive in normal mode.
        return this.get('large')
            ? this.get('progressive')
            : false;
    },

    /**
     * @override
     */
    getProgressiveThreshold: function () {
        // Do not support progressive in normal mode.
        var progressiveThreshold = this.get('progressiveThreshold');
        var largeThreshold = this.get('largeThreshold');
        if (largeThreshold > progressiveThreshold) {
            progressiveThreshold = largeThreshold;
        }
        return progressiveThreshold;
    },

    defaultOption: {
        // If clipped
        // Only available on cartesian2d
        clip: true,

        // If use caps on two sides of bars
        // Only available on tangential polar bar
        roundCap: false
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function setLabel(
    normalStyle, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside
) {
    var labelModel = itemModel.getModel('label');
    var hoverLabelModel = itemModel.getModel('emphasis.label');

    setLabelStyle(
        normalStyle, hoverStyle, labelModel, hoverLabelModel,
        {
            labelFetcher: seriesModel,
            labelDataIndex: dataIndex,
            defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
            isRectText: true,
            autoColor: color
        }
    );

    fixPosition(normalStyle);
    fixPosition(hoverStyle);
}

function fixPosition(style, labelPositionOutside) {
    if (style.textPosition === 'outside') {
        style.textPosition = labelPositionOutside;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var getBarItemStyle = makeStyleMapper(
    [
        ['fill', 'color'],
        ['stroke', 'borderColor'],
        ['lineWidth', 'borderWidth'],
        // Compatitable with 2
        ['stroke', 'barBorderColor'],
        ['lineWidth', 'barBorderWidth'],
        ['opacity'],
        ['shadowBlur'],
        ['shadowOffsetX'],
        ['shadowOffsetY'],
        ['shadowColor']
    ]
);

var barItemStyle = {
    getBarItemStyle: function (excludes) {
        var style = getBarItemStyle(this, excludes);
        if (this.getBorderLineDash) {
            var lineDash = this.getBorderLineDash();
            lineDash && (style.lineDash = lineDash);
        }
        return style;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Sausage: similar to sector, but have half circle on both sides
 * @public
 */
var Sausage = extendShape({

    type: 'sausage',

    shape: {

        cx: 0,

        cy: 0,

        r0: 0,

        r: 0,

        startAngle: 0,

        endAngle: Math.PI * 2,

        clockwise: true
    },

    buildPath: function (ctx, shape) {
        var x = shape.cx;
        var y = shape.cy;
        var r0 = Math.max(shape.r0 || 0, 0);
        var r = Math.max(shape.r, 0);
        var dr = (r - r0) * 0.5;
        var rCenter = r0 + dr;
        var startAngle = shape.startAngle;
        var endAngle = shape.endAngle;
        var clockwise = shape.clockwise;

        var unitStartX = Math.cos(startAngle);
        var unitStartY = Math.sin(startAngle);
        var unitEndX = Math.cos(endAngle);
        var unitEndY = Math.sin(endAngle);

        var lessThanCircle = clockwise
            ? endAngle - startAngle < Math.PI * 2
            : startAngle - endAngle < Math.PI * 2;

        if (lessThanCircle) {
            ctx.moveTo(unitStartX * r0 + x, unitStartY * r0 + y);

            ctx.arc(
                unitStartX * rCenter + x, unitStartY * rCenter + y, dr,
                -Math.PI + startAngle, startAngle, !clockwise
            );
        }

        ctx.arc(x, y, r, startAngle, endAngle, !clockwise);

        ctx.moveTo(unitEndX * r + x, unitEndY * r + y);

        ctx.arc(
            unitEndX * rCenter + x, unitEndY * rCenter + y, dr,
            endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise
        );

        if (r0 !== 0) {
            ctx.arc(x, y, r0, endAngle, startAngle, clockwise);

            ctx.moveTo(unitStartX * r0 + x, unitEndY * r0 + y);
        }

        ctx.closePath();
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];
var _eventPos = [0, 0];

// FIXME
// Just for compatible with ec2.
extend(Model.prototype, barItemStyle);

function getClipArea(coord, data) {
    var coordSysClipArea = coord.getArea && coord.getArea();
    if (coord.type === 'cartesian2d') {
        var baseAxis = coord.getBaseAxis();
        // When boundaryGap is false or using time axis. bar may exceed the grid.
        // We should not clip this part.
        // See test/bar2.html
        if (baseAxis.type !== 'category' || !baseAxis.onBand) {
            var expandWidth = data.getLayout('bandWidth');
            if (baseAxis.isHorizontal()) {
                coordSysClipArea.x -= expandWidth;
                coordSysClipArea.width += expandWidth * 2;
            }
            else {
                coordSysClipArea.y -= expandWidth;
                coordSysClipArea.height += expandWidth * 2;
            }
        }
    }

    return coordSysClipArea;
}

extendChartView({

    type: 'bar',

    render: function (seriesModel, ecModel, api) {
        this._updateDrawMode(seriesModel);

        var coordinateSystemType = seriesModel.get('coordinateSystem');

        if (coordinateSystemType === 'cartesian2d'
            || coordinateSystemType === 'polar'
        ) {
            this._isLargeDraw
                ? this._renderLarge(seriesModel, ecModel, api)
                : this._renderNormal(seriesModel, ecModel, api);
        }
        else if (__DEV__) {
            console.warn('Only cartesian2d and polar supported for bar.');
        }

        return this.group;
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        this._clear();
        this._updateDrawMode(seriesModel);
    },

    incrementalRender: function (params, seriesModel, ecModel, api) {
        // Do not support progressive in normal mode.
        this._incrementalRenderLarge(params, seriesModel);
    },

    _updateDrawMode: function (seriesModel) {
        var isLargeDraw = seriesModel.pipelineContext.large;
        if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) {
            this._isLargeDraw = isLargeDraw;
            this._clear();
        }
    },

    _renderNormal: function (seriesModel, ecModel, api) {
        var group = this.group;
        var data = seriesModel.getData();
        var oldData = this._data;

        var coord = seriesModel.coordinateSystem;
        var baseAxis = coord.getBaseAxis();
        var isHorizontalOrRadial;

        if (coord.type === 'cartesian2d') {
            isHorizontalOrRadial = baseAxis.isHorizontal();
        }
        else if (coord.type === 'polar') {
            isHorizontalOrRadial = baseAxis.dim === 'angle';
        }

        var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;

        var needsClip = seriesModel.get('clip', true);
        var coordSysClipArea = getClipArea(coord, data);
        // If there is clipPath created in large mode. Remove it.
        group.removeClipPath();
        // We don't use clipPath in normal mode because we needs a perfect animation
        // And don't want the label are clipped.

        var roundCap = seriesModel.get('roundCap', true);

        data.diff(oldData)
            .add(function (dataIndex) {
                if (!data.hasValue(dataIndex)) {
                    return;
                }

                var itemModel = data.getItemModel(dataIndex);
                var layout = getLayout[coord.type](data, dataIndex, itemModel);

                if (needsClip) {
                    // Clip will modify the layout params.
                    // And return a boolean to determine if the shape are fully clipped.
                    var isClipped = clip[coord.type](coordSysClipArea, layout);
                    if (isClipped) {
                        group.remove(el);
                        return;
                    }
                }

                var el = elementCreator[coord.type](
                    dataIndex, layout, isHorizontalOrRadial, animationModel, false, roundCap
                );
                data.setItemGraphicEl(dataIndex, el);
                group.add(el);

                updateStyle(
                    el, data, dataIndex, itemModel, layout,
                    seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                );
            })
            .update(function (newIndex, oldIndex) {
                var el = oldData.getItemGraphicEl(oldIndex);

                if (!data.hasValue(newIndex)) {
                    group.remove(el);
                    return;
                }

                var itemModel = data.getItemModel(newIndex);
                var layout = getLayout[coord.type](data, newIndex, itemModel);

                if (needsClip) {
                    var isClipped = clip[coord.type](coordSysClipArea, layout);
                    if (isClipped) {
                        group.remove(el);
                        return;
                    }
                }

                if (el) {
                    updateProps(el, {shape: layout}, animationModel, newIndex);
                }
                else {
                    el = elementCreator[coord.type](
                        newIndex, layout, isHorizontalOrRadial, animationModel, true, roundCap
                    );
                }

                data.setItemGraphicEl(newIndex, el);
                // Add back
                group.add(el);

                updateStyle(
                    el, data, newIndex, itemModel, layout,
                    seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                );
            })
            .remove(function (dataIndex) {
                var el = oldData.getItemGraphicEl(dataIndex);
                if (coord.type === 'cartesian2d') {
                    el && removeRect(dataIndex, animationModel, el);
                }
                else {
                    el && removeSector(dataIndex, animationModel, el);
                }
            })
            .execute();

        this._data = data;
    },

    _renderLarge: function (seriesModel, ecModel, api) {
        this._clear();
        createLarge(seriesModel, this.group);

        // Use clipPath in large mode.
        var clipPath = seriesModel.get('clip', true)
            ? createClipPath(seriesModel.coordinateSystem, false, seriesModel)
            : null;
        if (clipPath) {
            this.group.setClipPath(clipPath);
        }
        else {
            this.group.removeClipPath();
        }
    },

    _incrementalRenderLarge: function (params, seriesModel) {
        createLarge(seriesModel, this.group, true);
    },

    dispose: noop,

    remove: function (ecModel) {
        this._clear(ecModel);
    },

    _clear: function (ecModel) {
        var group = this.group;
        var data = this._data;
        if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
            data.eachItemGraphicEl(function (el) {
                if (el.type === 'sector') {
                    removeSector(el.dataIndex, ecModel, el);
                }
                else {
                    removeRect(el.dataIndex, ecModel, el);
                }
            });
        }
        else {
            group.removeAll();
        }
        this._data = null;
    }

});

var mathMax$4 = Math.max;
var mathMin$4 = Math.min;

var clip = {
    cartesian2d: function (coordSysBoundingRect, layout) {
        var signWidth = layout.width < 0 ? -1 : 1;
        var signHeight = layout.height < 0 ? -1 : 1;
        // Needs positive width and height
        if (signWidth < 0) {
            layout.x += layout.width;
            layout.width = -layout.width;
        }
        if (signHeight < 0) {
            layout.y += layout.height;
            layout.height = -layout.height;
        }

        var x = mathMax$4(layout.x, coordSysBoundingRect.x);
        var x2 = mathMin$4(layout.x + layout.width, coordSysBoundingRect.x + coordSysBoundingRect.width);
        var y = mathMax$4(layout.y, coordSysBoundingRect.y);
        var y2 = mathMin$4(layout.y + layout.height, coordSysBoundingRect.y + coordSysBoundingRect.height);

        layout.x = x;
        layout.y = y;
        layout.width = x2 - x;
        layout.height = y2 - y;

        var clipped = layout.width < 0 || layout.height < 0;

        // Reverse back
        if (signWidth < 0) {
            layout.x += layout.width;
            layout.width = -layout.width;
        }
        if (signHeight < 0) {
            layout.y += layout.height;
            layout.height = -layout.height;
        }

        return clipped;
    },

    polar: function (coordSysClipArea) {
        return false;
    }
};

var elementCreator = {

    cartesian2d: function (
        dataIndex, layout, isHorizontal,
        animationModel, isUpdate
    ) {
        var rect = new Rect({shape: extend({}, layout)});

        // Animation
        if (animationModel) {
            var rectShape = rect.shape;
            var animateProperty = isHorizontal ? 'height' : 'width';
            var animateTarget = {};
            rectShape[animateProperty] = 0;
            animateTarget[animateProperty] = layout[animateProperty];
            graphic[isUpdate ? 'updateProps' : 'initProps'](rect, {
                shape: animateTarget
            }, animationModel, dataIndex);
        }

        return rect;
    },

    polar: function (
        dataIndex, layout, isRadial,
        animationModel, isUpdate, roundCap
    ) {
        // Keep the same logic with bar in catesion: use end value to control
        // direction. Notice that if clockwise is true (by default), the sector
        // will always draw clockwisely, no matter whether endAngle is greater
        // or less than startAngle.
        var clockwise = layout.startAngle < layout.endAngle;

        var ShapeClass = (!isRadial && roundCap) ? Sausage : Sector;

        var sector = new ShapeClass({
            shape: defaults({clockwise: clockwise}, layout)
        });

        // Animation
        if (animationModel) {
            var sectorShape = sector.shape;
            var animateProperty = isRadial ? 'r' : 'endAngle';
            var animateTarget = {};
            sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
            animateTarget[animateProperty] = layout[animateProperty];
            graphic[isUpdate ? 'updateProps' : 'initProps'](sector, {
                shape: animateTarget
            }, animationModel, dataIndex);
        }

        return sector;
    }
};

function removeRect(dataIndex, animationModel, el) {
    // Not show text when animating
    el.style.text = null;
    updateProps(el, {
        shape: {
            width: 0
        }
    }, animationModel, dataIndex, function () {
        el.parent && el.parent.remove(el);
    });
}

function removeSector(dataIndex, animationModel, el) {
    // Not show text when animating
    el.style.text = null;
    updateProps(el, {
        shape: {
            r: el.shape.r0
        }
    }, animationModel, dataIndex, function () {
        el.parent && el.parent.remove(el);
    });
}

var getLayout = {
    cartesian2d: function (data, dataIndex, itemModel) {
        var layout = data.getItemLayout(dataIndex);
        var fixedLineWidth = getLineWidth(itemModel, layout);

        // fix layout with lineWidth
        var signX = layout.width > 0 ? 1 : -1;
        var signY = layout.height > 0 ? 1 : -1;
        return {
            x: layout.x + signX * fixedLineWidth / 2,
            y: layout.y + signY * fixedLineWidth / 2,
            width: layout.width - signX * fixedLineWidth,
            height: layout.height - signY * fixedLineWidth
        };
    },

    polar: function (data, dataIndex, itemModel) {
        var layout = data.getItemLayout(dataIndex);
        return {
            cx: layout.cx,
            cy: layout.cy,
            r0: layout.r0,
            r: layout.r,
            startAngle: layout.startAngle,
            endAngle: layout.endAngle
        };
    }
};

function updateStyle(
    el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar
) {
    var color = data.getItemVisual(dataIndex, 'color');
    var opacity = data.getItemVisual(dataIndex, 'opacity');
    var itemStyleModel = itemModel.getModel('itemStyle');
    var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle();

    if (!isPolar) {
        el.setShape('r', itemStyleModel.get('barBorderRadius') || 0);
    }

    el.useStyle(defaults(
        {
            fill: color,
            opacity: opacity
        },
        itemStyleModel.getBarItemStyle()
    ));

    var cursorStyle = itemModel.getShallow('cursor');
    cursorStyle && el.attr('cursor', cursorStyle);

    var labelPositionOutside = isHorizontal
        ? (layout.height > 0 ? 'bottom' : 'top')
        : (layout.width > 0 ? 'left' : 'right');

    if (!isPolar) {
        setLabel(
            el.style, hoverStyle, itemModel, color,
            seriesModel, dataIndex, labelPositionOutside
        );
    }

    setHoverStyle(el, hoverStyle);
}

// In case width or height are too small.
function getLineWidth(itemModel, rawLayout) {
    var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
    return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
}


var LargePath = Path.extend({

    type: 'largeBar',

    shape: {points: []},

    buildPath: function (ctx, shape) {
        // Drawing lines is more efficient than drawing
        // a whole line or drawing rects.
        var points = shape.points;
        var startPoint = this.__startPoint;
        var baseDimIdx = this.__baseDimIdx;

        for (var i = 0; i < points.length; i += 2) {
            startPoint[baseDimIdx] = points[i + baseDimIdx];
            ctx.moveTo(startPoint[0], startPoint[1]);
            ctx.lineTo(points[i], points[i + 1]);
        }
    }
});

function createLarge(seriesModel, group, incremental) {
    // TODO support polar
    var data = seriesModel.getData();
    var startPoint = [];
    var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
    startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');

    var el = new LargePath({
        shape: {points: data.getLayout('largePoints')},
        incremental: !!incremental,
        __startPoint: startPoint,
        __baseDimIdx: baseDimIdx,
        __largeDataIndices: data.getLayout('largeDataIndices'),
        __barWidth: data.getLayout('barWidth')
    });
    group.add(el);
    setLargeStyle(el, seriesModel, data);

    // Enable tooltip and user mouse/touch event handlers.
    el.seriesIndex = seriesModel.seriesIndex;

    if (!seriesModel.get('silent')) {
        el.on('mousedown', largePathUpdateDataIndex);
        el.on('mousemove', largePathUpdateDataIndex);
    }
}

// Use throttle to avoid frequently traverse to find dataIndex.
var largePathUpdateDataIndex = throttle(function (event) {
    var largePath = this;
    var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
    largePath.dataIndex = dataIndex >= 0 ? dataIndex : null;
}, 30, false);

function largePathFindDataIndex(largePath, x, y) {
    var baseDimIdx = largePath.__baseDimIdx;
    var valueDimIdx = 1 - baseDimIdx;
    var points = largePath.shape.points;
    var largeDataIndices = largePath.__largeDataIndices;
    var barWidthHalf = Math.abs(largePath.__barWidth / 2);
    var startValueVal = largePath.__startPoint[valueDimIdx];

    _eventPos[0] = x;
    _eventPos[1] = y;
    var pointerBaseVal = _eventPos[baseDimIdx];
    var pointerValueVal = _eventPos[1 - baseDimIdx];
    var baseLowerBound = pointerBaseVal - barWidthHalf;
    var baseUpperBound = pointerBaseVal + barWidthHalf;

    for (var i = 0, len = points.length / 2; i < len; i++) {
        var ii = i * 2;
        var barBaseVal = points[ii + baseDimIdx];
        var barValueVal = points[ii + valueDimIdx];
        if (
            barBaseVal >= baseLowerBound && barBaseVal <= baseUpperBound
            && (
                startValueVal <= barValueVal
                    ? (pointerValueVal >= startValueVal && pointerValueVal <= barValueVal)
                    : (pointerValueVal >= barValueVal && pointerValueVal <= startValueVal)
            )
        ) {
            return largeDataIndices[i];
        }
    }

    return -1;
}

function setLargeStyle(el, seriesModel, data) {
    var borderColor = data.getVisual('borderColor') || data.getVisual('color');
    var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(['color', 'borderColor']);

    el.useStyle(itemStyle);
    el.style.fill = null;
    el.style.stroke = borderColor;
    el.style.lineWidth = data.getLayout('barWidth');
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// In case developer forget to include grid component
registerLayout(PRIORITY.VISUAL.LAYOUT, curry(layout, 'bar'));
// Use higher prority to avoid to be blocked by other overall layout, which do not
// only exist in this module, but probably also exist in other modules, like `barPolar`.
registerLayout(PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout);

registerVisual({
    seriesType: 'bar',
    reset: function (seriesModel) {
        // Visual coding for legend
        seriesModel.getData().setVisual('legendSymbol', 'roundRect');
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * [Usage]:
 * (1)
 * createListSimply(seriesModel, ['value']);
 * (2)
 * createListSimply(seriesModel, {
 *     coordDimensions: ['value'],
 *     dimensionsCount: 5
 * });
 *
 * @param {module:echarts/model/Series} seriesModel
 * @param {Object|Array.<string|Object>} opt opt or coordDimensions
 *        The options in opt, see `echarts/data/helper/createDimensions`
 * @param {Array.<string>} [nameList]
 * @return {module:echarts/data/List}
 */
var createListSimply = function (seriesModel, opt, nameList) {
    opt = isArray(opt) && {coordDimensions: opt} || extend({}, opt);

    var source = seriesModel.getSource();

    var dimensionsInfo = createDimensions(source, opt);

    var list = new List(dimensionsInfo, seriesModel);
    list.initData(source, nameList);

    return list;
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Data selectable mixin for chart series.
 * To eanble data select, option of series must have `selectedMode`.
 * And each data item will use `selected` to toggle itself selected status
 */

var selectableMixin = {

    /**
     * @param {Array.<Object>} targetList [{name, value, selected}, ...]
     *        If targetList is an array, it should like [{name: ..., value: ...}, ...].
     *        If targetList is a "List", it must have coordDim: 'value' dimension and name.
     */
    updateSelectedMap: function (targetList) {
        this._targetList = isArray(targetList) ? targetList.slice() : [];

        this._selectTargetMap = reduce(targetList || [], function (targetMap, target) {
            targetMap.set(target.name, target);
            return targetMap;
        }, createHashMap());
    },

    /**
     * Either name or id should be passed as input here.
     * If both of them are defined, id is used.
     *
     * @param {string|undefined} name name of data
     * @param {number|undefined} id dataIndex of data
     */
    // PENGING If selectedMode is null ?
    select: function (name, id) {
        var target = id != null
            ? this._targetList[id]
            : this._selectTargetMap.get(name);
        var selectedMode = this.get('selectedMode');
        if (selectedMode === 'single') {
            this._selectTargetMap.each(function (target) {
                target.selected = false;
            });
        }
        target && (target.selected = true);
    },

    /**
     * Either name or id should be passed as input here.
     * If both of them are defined, id is used.
     *
     * @param {string|undefined} name name of data
     * @param {number|undefined} id dataIndex of data
     */
    unSelect: function (name, id) {
        var target = id != null
            ? this._targetList[id]
            : this._selectTargetMap.get(name);
        // var selectedMode = this.get('selectedMode');
        // selectedMode !== 'single' && target && (target.selected = false);
        target && (target.selected = false);
    },

    /**
     * Either name or id should be passed as input here.
     * If both of them are defined, id is used.
     *
     * @param {string|undefined} name name of data
     * @param {number|undefined} id dataIndex of data
     */
    toggleSelected: function (name, id) {
        var target = id != null
            ? this._targetList[id]
            : this._selectTargetMap.get(name);
        if (target != null) {
            this[target.selected ? 'unSelect' : 'select'](name, id);
            return target.selected;
        }
    },

    /**
     * Either name or id should be passed as input here.
     * If both of them are defined, id is used.
     *
     * @param {string|undefined} name name of data
     * @param {number|undefined} id dataIndex of data
     */
    isSelected: function (name, id) {
        var target = id != null
            ? this._targetList[id]
            : this._selectTargetMap.get(name);
        return target && target.selected;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PieSeries = extendSeriesModel({

    type: 'series.pie',

    // Overwrite
    init: function (option) {
        PieSeries.superApply(this, 'init', arguments);

        // Enable legend selection for each data item
        // Use a function instead of direct access because data reference may changed
        this.legendDataProvider = function () {
            return this.getRawData();
        };

        this.updateSelectedMap(this._createSelectableList());

        this._defaultLabelLine(option);
    },

    // Overwrite
    mergeOption: function (newOption) {
        PieSeries.superCall(this, 'mergeOption', newOption);

        this.updateSelectedMap(this._createSelectableList());
    },

    getInitialData: function (option, ecModel) {
        return createListSimply(this, ['value']);
    },

    _createSelectableList: function () {
        var data = this.getRawData();
        var valueDim = data.mapDimension('value');
        var targetList = [];
        for (var i = 0, len = data.count(); i < len; i++) {
            targetList.push({
                name: data.getName(i),
                value: data.get(valueDim, i),
                selected: retrieveRawAttr(data, i, 'selected')
            });
        }
        return targetList;
    },

    // Overwrite
    getDataParams: function (dataIndex) {
        var data = this.getData();
        var params = PieSeries.superCall(this, 'getDataParams', dataIndex);
        // FIXME toFixed?

        var valueList = [];
        data.each(data.mapDimension('value'), function (value) {
            valueList.push(value);
        });

        params.percent = getPercentWithPrecision(
            valueList,
            dataIndex,
            data.hostModel.get('percentPrecision')
        );

        params.$vars.push('percent');
        return params;
    },

    _defaultLabelLine: function (option) {
        // Extend labelLine emphasis
        defaultEmphasis(option, 'labelLine', ['show']);

        var labelLineNormalOpt = option.labelLine;
        var labelLineEmphasisOpt = option.emphasis.labelLine;
        // Not show label line if `label.normal.show = false`
        labelLineNormalOpt.show = labelLineNormalOpt.show
            && option.label.show;
        labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
            && option.emphasis.label.show;
    },

    defaultOption: {
        zlevel: 0,
        z: 2,
        legendHoverLink: true,

        hoverAnimation: true,
        // 默认全局居中
        center: ['50%', '50%'],
        radius: [0, '75%'],
        // 默认顺时针
        clockwise: true,
        startAngle: 90,
        // 最小角度改为0
        minAngle: 0,

        // If the angle of a sector less than `minShowLabelAngle`,
        // the label will not be displayed.
        minShowLabelAngle: 0,

        // 选中时扇区偏移量
        selectedOffset: 10,
        // 高亮扇区偏移量
        hoverOffset: 10,

        // If use strategy to avoid label overlapping
        avoidLabelOverlap: true,
        // 选择模式，默认关闭，可选single，multiple
        // selectedMode: false,
        // 南丁格尔玫瑰图模式，'radius'（半径） | 'area'（面积）
        // roseType: null,

        percentPrecision: 2,

        // If still show when all data zero.
        stillShowZeroSum: true,

        // cursor: null,

        label: {
            // If rotate around circle
            rotate: false,
            show: true,
            // 'outer', 'inside', 'center'
            position: 'outer'
            // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
            // 默认使用全局文本样式，详见TEXTSTYLE
            // distance: 当position为inner时有效，为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
        },
        // Enabled when label.normal.position is 'outer'
        labelLine: {
            show: true,
            // 引导线两段中的第一段长度
            length: 15,
            // 引导线两段中的第二段长度
            length2: 15,
            smooth: false,
            lineStyle: {
                // color: 各异,
                width: 1,
                type: 'solid'
            }
        },
        itemStyle: {
            borderWidth: 1
        },

        // Animation type. Valid values: expansion, scale
        animationType: 'expansion',

        // Animation type when update. Valid values: transition, expansion
        animationTypeUpdate: 'transition',

        animationEasing: 'cubicOut'
    }
});

mixin(PieSeries, selectableMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/model/Series} seriesModel
 * @param {boolean} hasAnimation
 * @inner
 */
function updateDataSelected(uid, seriesModel, hasAnimation, api) {
    var data = seriesModel.getData();
    var dataIndex = this.dataIndex;
    var name = data.getName(dataIndex);
    var selectedOffset = seriesModel.get('selectedOffset');

    api.dispatchAction({
        type: 'pieToggleSelect',
        from: uid,
        name: name,
        seriesId: seriesModel.id
    });

    data.each(function (idx) {
        toggleItemSelected(
            data.getItemGraphicEl(idx),
            data.getItemLayout(idx),
            seriesModel.isSelected(data.getName(idx)),
            selectedOffset,
            hasAnimation
        );
    });
}

/**
 * @param {module:zrender/graphic/Sector} el
 * @param {Object} layout
 * @param {boolean} isSelected
 * @param {number} selectedOffset
 * @param {boolean} hasAnimation
 * @inner
 */
function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) {
    var midAngle = (layout.startAngle + layout.endAngle) / 2;

    var dx = Math.cos(midAngle);
    var dy = Math.sin(midAngle);

    var offset = isSelected ? selectedOffset : 0;
    var position = [dx * offset, dy * offset];

    hasAnimation
        // animateTo will stop revious animation like update transition
        ? el.animate()
            .when(200, {
                position: position
            })
            .start('bounceOut')
        : el.attr('position', position);
}

/**
 * Piece of pie including Sector, Label, LabelLine
 * @constructor
 * @extends {module:zrender/graphic/Group}
 */
function PiePiece(data, idx) {

    Group.call(this);

    var sector = new Sector({
        z2: 2
    });
    var polyline = new Polyline();
    var text = new Text();
    this.add(sector);
    this.add(polyline);
    this.add(text);

    this.updateData(data, idx, true);
}

var piePieceProto = PiePiece.prototype;

piePieceProto.updateData = function (data, idx, firstCreate) {

    var sector = this.childAt(0);
    var labelLine = this.childAt(1);
    var labelText = this.childAt(2);

    var seriesModel = data.hostModel;
    var itemModel = data.getItemModel(idx);
    var layout = data.getItemLayout(idx);
    var sectorShape = extend({}, layout);
    sectorShape.label = null;

    var animationTypeUpdate = seriesModel.getShallow('animationTypeUpdate');

    if (firstCreate) {
        sector.setShape(sectorShape);

        var animationType = seriesModel.getShallow('animationType');
        if (animationType === 'scale') {
            sector.shape.r = layout.r0;
            initProps(sector, {
                shape: {
                    r: layout.r
                }
            }, seriesModel, idx);
        }
        // Expansion
        else {
            sector.shape.endAngle = layout.startAngle;
            updateProps(sector, {
                shape: {
                    endAngle: layout.endAngle
                }
            }, seriesModel, idx);
        }

    }
    else {
        if (animationTypeUpdate === 'expansion') {
            // Sectors are set to be target shape and an overlaying clipPath is used for animation
            sector.setShape(sectorShape);
        }
        else {
            // Transition animation from the old shape
            updateProps(sector, {
                shape: sectorShape
            }, seriesModel, idx);
        }
    }

    // Update common style
    var visualColor = data.getItemVisual(idx, 'color');

    sector.useStyle(
        defaults(
            {
                lineJoin: 'bevel',
                fill: visualColor
            },
            itemModel.getModel('itemStyle').getItemStyle()
        )
    );
    sector.hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();

    var cursorStyle = itemModel.getShallow('cursor');
    cursorStyle && sector.attr('cursor', cursorStyle);

    // Toggle selected
    toggleItemSelected(
        this,
        data.getItemLayout(idx),
        seriesModel.isSelected(null, idx),
        seriesModel.get('selectedOffset'),
        seriesModel.get('animation')
    );

    // Label and text animation should be applied only for transition type animation when update
    var withAnimation = !firstCreate && animationTypeUpdate === 'transition';
    this._updateLabel(data, idx, withAnimation);

    this.highDownOnUpdate = (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled())
        ? function (fromState, toState) {
            if (toState === 'emphasis') {
                labelLine.ignore = labelLine.hoverIgnore;
                labelText.ignore = labelText.hoverIgnore;

                // Sector may has animation of updating data. Force to move to the last frame
                // Or it may stopped on the wrong shape
                sector.stopAnimation(true);
                sector.animateTo({
                    shape: {
                        r: layout.r + seriesModel.get('hoverOffset')
                    }
                }, 300, 'elasticOut');
            }
            else {
                labelLine.ignore = labelLine.normalIgnore;
                labelText.ignore = labelText.normalIgnore;

                sector.stopAnimation(true);
                sector.animateTo({
                    shape: {
                        r: layout.r
                    }
                }, 300, 'elasticOut');
            }
        }
        : null;

    setHoverStyle(this);
};

piePieceProto._updateLabel = function (data, idx, withAnimation) {

    var labelLine = this.childAt(1);
    var labelText = this.childAt(2);

    var seriesModel = data.hostModel;
    var itemModel = data.getItemModel(idx);
    var layout = data.getItemLayout(idx);
    var labelLayout = layout.label;
    var visualColor = data.getItemVisual(idx, 'color');

    if (!labelLayout || isNaN(labelLayout.x) || isNaN(labelLayout.y)) {
        labelText.ignore = labelText.normalIgnore = labelText.hoverIgnore =
        labelLine.ignore = labelLine.normalIgnore = labelLine.hoverIgnore = true;
        return;
    }

    var targetLineShape = {
        points: labelLayout.linePoints || [
            [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]
        ]
    };
    var targetTextStyle = {
        x: labelLayout.x,
        y: labelLayout.y
    };
    if (withAnimation) {
        updateProps(labelLine, {
            shape: targetLineShape
        }, seriesModel, idx);

        updateProps(labelText, {
            style: targetTextStyle
        }, seriesModel, idx);
    }
    else {
        labelLine.attr({
            shape: targetLineShape
        });
        labelText.attr({
            style: targetTextStyle
        });
    }

    labelText.attr({
        rotation: labelLayout.rotation,
        origin: [labelLayout.x, labelLayout.y],
        z2: 10
    });

    var labelModel = itemModel.getModel('label');
    var labelHoverModel = itemModel.getModel('emphasis.label');
    var labelLineModel = itemModel.getModel('labelLine');
    var labelLineHoverModel = itemModel.getModel('emphasis.labelLine');
    var visualColor = data.getItemVisual(idx, 'color');

    setLabelStyle(
        labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel,
        {
            labelFetcher: data.hostModel,
            labelDataIndex: idx,
            defaultText: data.getName(idx),
            autoColor: visualColor,
            useInsideStyle: !!labelLayout.inside
        },
        {
            textAlign: labelLayout.textAlign,
            textVerticalAlign: labelLayout.verticalAlign,
            opacity: data.getItemVisual(idx, 'opacity')
        }
    );

    labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
    labelText.hoverIgnore = !labelHoverModel.get('show');

    labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
    labelLine.hoverIgnore = !labelLineHoverModel.get('show');

    // Default use item visual color
    labelLine.setStyle({
        stroke: visualColor,
        opacity: data.getItemVisual(idx, 'opacity')
    });
    labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());

    labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();

    var smooth = labelLineModel.get('smooth');
    if (smooth && smooth === true) {
        smooth = 0.4;
    }
    labelLine.setShape({
        smooth: smooth
    });
};

inherits(PiePiece, Group);


// Pie view
var PieView = Chart.extend({

    type: 'pie',

    init: function () {
        var sectorGroup = new Group();
        this._sectorGroup = sectorGroup;
    },

    render: function (seriesModel, ecModel, api, payload) {
        if (payload && (payload.from === this.uid)) {
            return;
        }

        var data = seriesModel.getData();
        var oldData = this._data;
        var group = this.group;

        var hasAnimation = ecModel.get('animation');
        var isFirstRender = !oldData;
        var animationType = seriesModel.get('animationType');
        var animationTypeUpdate = seriesModel.get('animationTypeUpdate');

        var onSectorClick = curry(
            updateDataSelected, this.uid, seriesModel, hasAnimation, api
        );

        var selectedMode = seriesModel.get('selectedMode');
        data.diff(oldData)
            .add(function (idx) {
                var piePiece = new PiePiece(data, idx);
                // Default expansion animation
                if (isFirstRender && animationType !== 'scale') {
                    piePiece.eachChild(function (child) {
                        child.stopAnimation(true);
                    });
                }

                selectedMode && piePiece.on('click', onSectorClick);

                data.setItemGraphicEl(idx, piePiece);

                group.add(piePiece);
            })
            .update(function (newIdx, oldIdx) {
                var piePiece = oldData.getItemGraphicEl(oldIdx);

                if (!isFirstRender && animationTypeUpdate !== 'transition') {
                    piePiece.eachChild(function (child) {
                        child.stopAnimation(true);
                    });
                }

                piePiece.updateData(data, newIdx);

                piePiece.off('click');
                selectedMode && piePiece.on('click', onSectorClick);
                group.add(piePiece);
                data.setItemGraphicEl(newIdx, piePiece);
            })
            .remove(function (idx) {
                var piePiece = oldData.getItemGraphicEl(idx);
                group.remove(piePiece);
            })
            .execute();

        if (
            hasAnimation && data.count() > 0
            && (isFirstRender ? animationType !== 'scale' : animationTypeUpdate !== 'transition')
        ) {
            var shape = data.getItemLayout(0);
            for (var s = 1; isNaN(shape.startAngle) && s < data.count(); ++s) {
                shape = data.getItemLayout(s);
            }

            var r = Math.max(api.getWidth(), api.getHeight()) / 2;

            var removeClipPath = bind(group.removeClipPath, group);
            group.setClipPath(this._createClipPath(
                shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel, isFirstRender
            ));
        }
        else {
            // clipPath is used in first-time animation, so remove it when otherwise. See: #8994
            group.removeClipPath();
        }

        this._data = data;
    },

    dispose: function () {},

    _createClipPath: function (
        cx, cy, r, startAngle, clockwise, cb, seriesModel, isFirstRender
    ) {
        var clipPath = new Sector({
            shape: {
                cx: cx,
                cy: cy,
                r0: 0,
                r: r,
                startAngle: startAngle,
                endAngle: startAngle,
                clockwise: clockwise
            }
        });

        var initOrUpdate = isFirstRender ? initProps : updateProps;
        initOrUpdate(clipPath, {
            shape: {
                endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
            }
        }, seriesModel, cb);

        return clipPath;
    },

    /**
     * @implement
     */
    containPoint: function (point, seriesModel) {
        var data = seriesModel.getData();
        var itemLayout = data.getItemLayout(0);
        if (itemLayout) {
            var dx = point[0] - itemLayout.cx;
            var dy = point[1] - itemLayout.cy;
            var radius = Math.sqrt(dx * dx + dy * dy);
            return radius <= itemLayout.r && radius >= itemLayout.r0;
        }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var createDataSelectAction = function (seriesType, actionInfos) {
    each$1(actionInfos, function (actionInfo) {
        actionInfo.update = 'updateView';
        /**
         * @payload
         * @property {string} seriesName
         * @property {string} name
         */
        registerAction(actionInfo, function (payload, ecModel) {
            var selected = {};
            ecModel.eachComponent(
                {mainType: 'series', subType: seriesType, query: payload},
                function (seriesModel) {
                    if (seriesModel[actionInfo.method]) {
                        seriesModel[actionInfo.method](
                            payload.name,
                            payload.dataIndex
                        );
                    }
                    var data = seriesModel.getData();
                    // Create selected map
                    data.each(function (idx) {
                        var name = data.getName(idx);
                        selected[name] = seriesModel.isSelected(name)
                            || false;
                    });
                }
            );
            return {
                name: payload.name,
                selected: selected,
                seriesId: payload.seriesId
            };
        });
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Pick color from palette for each data item.
// Applicable for charts that require applying color palette
// in data level (like pie, funnel, chord).
var dataColor = function (seriesType) {
    return {
        getTargetSeries: function (ecModel) {
            // Pie and funnel may use diferrent scope
            var paletteScope = {};
            var seiresModelMap = createHashMap();

            ecModel.eachSeriesByType(seriesType, function (seriesModel) {
                seriesModel.__paletteScope = paletteScope;
                seiresModelMap.set(seriesModel.uid, seriesModel);
            });

            return seiresModelMap;
        },
        reset: function (seriesModel, ecModel) {
            var dataAll = seriesModel.getRawData();
            var idxMap = {};
            var data = seriesModel.getData();

            data.each(function (idx) {
                var rawIdx = data.getRawIndex(idx);
                idxMap[rawIdx] = idx;
            });

            dataAll.each(function (rawIdx) {
                var filteredIdx = idxMap[rawIdx];

                // If series.itemStyle.normal.color is a function. itemVisual may be encoded
                var singleDataColor = filteredIdx != null
                    && data.getItemVisual(filteredIdx, 'color', true);

                var singleDataBorderColor = filteredIdx != null
                    && data.getItemVisual(filteredIdx, 'borderColor', true);

                var itemModel;
                if (!singleDataColor || !singleDataBorderColor) {
                    // FIXME Performance
                    itemModel = dataAll.getItemModel(rawIdx);
                }

                if (!singleDataColor) {
                    var color = itemModel.get('itemStyle.color')
                        || seriesModel.getColorFromPalette(
                            dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope,
                            dataAll.count()
                        );
                    // Legend may use the visual info in data before processed
                    dataAll.setItemVisual(rawIdx, 'color', color);

                    // Data is not filtered
                    if (filteredIdx != null) {
                        data.setItemVisual(filteredIdx, 'color', color);
                    }
                }
                else {
                    // Set data all color for legend
                    dataAll.setItemVisual(rawIdx, 'color', singleDataColor);
                }

                if (!singleDataBorderColor) {
                    var borderColor = itemModel.get('itemStyle.borderColor');
                    // Legend may use the visual info in data before processed
                    dataAll.setItemVisual(rawIdx, 'borderColor', borderColor);

                    // Data is not filtered
                    if (filteredIdx != null) {
                        data.setItemVisual(filteredIdx, 'borderColor', borderColor);
                    }
                }
                else {
                    // Set data all borderColor for legend
                    dataAll.setItemVisual(rawIdx, 'borderColor', singleDataBorderColor);
                }
            });
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME emphasis label position is not same with normal label position

var RADIAN$1 = Math.PI / 180;

function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
    list.sort(function (a, b) {
        return a.y - b.y;
    });

    function shiftDown(start, end, delta, dir) {
        for (var j = start; j < end; j++) {
            list[j].y += delta;
            if (j > start
                && j + 1 < end
                && list[j + 1].y > list[j].y + list[j].height
            ) {
                shiftUp(j, delta / 2);
                return;
            }
        }

        shiftUp(end - 1, delta / 2);
    }

    function shiftUp(end, delta) {
        for (var j = end; j >= 0; j--) {
            list[j].y -= delta;
            if (j > 0
                && list[j].y > list[j - 1].y + list[j - 1].height
            ) {
                break;
            }
        }
    }

    function changeX(list, isDownList, cx, cy, r, dir) {
        var lastDeltaX = dir > 0
            ? isDownList                // right-side
                ? Number.MAX_VALUE      // down
                : 0                     // up
            : isDownList                // left-side
                ? Number.MAX_VALUE      // down
                : 0;                    // up

        for (var i = 0, l = list.length; i < l; i++) {
            var deltaY = Math.abs(list[i].y - cy);
            var length = list[i].len;
            var length2 = list[i].len2;
            var deltaX = (deltaY < r + length)
                ? Math.sqrt(
                        (r + length + length2) * (r + length + length2)
                        - deltaY * deltaY
                    )
                : Math.abs(list[i].x - cx);
            if (isDownList && deltaX >= lastDeltaX) {
                // right-down, left-down
                deltaX = lastDeltaX - 10;
            }
            if (!isDownList && deltaX <= lastDeltaX) {
                // right-up, left-up
                deltaX = lastDeltaX + 10;
            }

            list[i].x = cx + deltaX * dir;
            lastDeltaX = deltaX;
        }
    }

    var lastY = 0;
    var delta;
    var len = list.length;
    var upList = [];
    var downList = [];
    for (var i = 0; i < len; i++) {
        delta = list[i].y - lastY;
        if (delta < 0) {
            shiftDown(i, len, -delta, dir);
        }
        lastY = list[i].y + list[i].height;
    }
    if (viewHeight - lastY < 0) {
        shiftUp(len - 1, lastY - viewHeight);
    }
    for (var i = 0; i < len; i++) {
        if (list[i].y >= cy) {
            downList.push(list[i]);
        }
        else {
            upList.push(list[i]);
        }
    }
    changeX(upList, false, cx, cy, r, dir);
    changeX(downList, true, cx, cy, r, dir);
}

function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
    var leftList = [];
    var rightList = [];
    for (var i = 0; i < labelLayoutList.length; i++) {
        if (isPositionCenter(labelLayoutList[i])) {
            continue;
        }
        if (labelLayoutList[i].x < cx) {
            leftList.push(labelLayoutList[i]);
        }
        else {
            rightList.push(labelLayoutList[i]);
        }
    }

    adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
    adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);

    for (var i = 0; i < labelLayoutList.length; i++) {
        if (isPositionCenter(labelLayoutList[i])) {
            continue;
        }
        var linePoints = labelLayoutList[i].linePoints;
        if (linePoints) {
            var dist = linePoints[1][0] - linePoints[2][0];
            if (labelLayoutList[i].x < cx) {
                linePoints[2][0] = labelLayoutList[i].x + 3;
            }
            else {
                linePoints[2][0] = labelLayoutList[i].x - 3;
            }
            linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
            linePoints[1][0] = linePoints[2][0] + dist;
        }
    }
}

function isPositionCenter(layout) {
    // Not change x for center label
    return layout.position === 'center';
}

var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
    var data = seriesModel.getData();
    var labelLayoutList = [];
    var cx;
    var cy;
    var hasLabelRotate = false;
    var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN$1;

    data.each(function (idx) {
        var layout = data.getItemLayout(idx);

        var itemModel = data.getItemModel(idx);
        var labelModel = itemModel.getModel('label');
        // Use position in normal or emphasis
        var labelPosition = labelModel.get('position') || itemModel.get('emphasis.label.position');

        var labelLineModel = itemModel.getModel('labelLine');
        var labelLineLen = labelLineModel.get('length');
        var labelLineLen2 = labelLineModel.get('length2');

        if (layout.angle < minShowLabelRadian) {
            return;
        }

        var midAngle = (layout.startAngle + layout.endAngle) / 2;
        var dx = Math.cos(midAngle);
        var dy = Math.sin(midAngle);

        var textX;
        var textY;
        var linePoints;
        var textAlign;

        cx = layout.cx;
        cy = layout.cy;

        var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
        if (labelPosition === 'center') {
            textX = layout.cx;
            textY = layout.cy;
            textAlign = 'center';
        }
        else {
            var x1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dx : layout.r * dx) + cx;
            var y1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dy : layout.r * dy) + cy;

            textX = x1 + dx * 3;
            textY = y1 + dy * 3;

            if (!isLabelInside) {
                // For roseType
                var x2 = x1 + dx * (labelLineLen + r - layout.r);
                var y2 = y1 + dy * (labelLineLen + r - layout.r);
                var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2);
                var y3 = y2;

                textX = x3 + (dx < 0 ? -5 : 5);
                textY = y3;
                linePoints = [[x1, y1], [x2, y2], [x3, y3]];
            }

            textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right');
        }
        var font = labelModel.getFont();

        var labelRotate;
        var rotate = labelModel.get('rotate');
        if (typeof rotate === 'number') {
            labelRotate = rotate * (Math.PI / 180);
        }
        else {
            labelRotate = rotate
                ? (dx < 0 ? -midAngle + Math.PI : -midAngle)
                : 0;
        }
        var text = seriesModel.getFormattedLabel(idx, 'normal')
                    || data.getName(idx);
        var textRect = getBoundingRect(
            text, font, textAlign, 'top'
        );
        hasLabelRotate = !!labelRotate;
        layout.label = {
            x: textX,
            y: textY,
            position: labelPosition,
            height: textRect.height,
            len: labelLineLen,
            len2: labelLineLen2,
            linePoints: linePoints,
            textAlign: textAlign,
            verticalAlign: 'middle',
            rotation: labelRotate,
            inside: isLabelInside
        };

        // Not layout the inside label
        if (!isLabelInside) {
            labelLayoutList.push(layout.label);
        }
    });
    if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
        avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var PI2$4 = Math.PI * 2;
var RADIAN = Math.PI / 180;

var pieLayout = function (seriesType, ecModel, api, payload) {
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
        var data = seriesModel.getData();
        var valueDim = data.mapDimension('value');

        var center = seriesModel.get('center');
        var radius = seriesModel.get('radius');

        if (!isArray(radius)) {
            radius = [0, radius];
        }
        if (!isArray(center)) {
            center = [center, center];
        }

        var width = api.getWidth();
        var height = api.getHeight();
        var size = Math.min(width, height);
        var cx = parsePercent$1(center[0], width);
        var cy = parsePercent$1(center[1], height);
        var r0 = parsePercent$1(radius[0], size / 2);
        var r = parsePercent$1(radius[1], size / 2);

        var startAngle = -seriesModel.get('startAngle') * RADIAN;

        var minAngle = seriesModel.get('minAngle') * RADIAN;

        var validDataCount = 0;
        data.each(valueDim, function (value) {
            !isNaN(value) && validDataCount++;
        });

        var sum = data.getSum(valueDim);
        // Sum may be 0
        var unitRadian = Math.PI / (sum || validDataCount) * 2;

        var clockwise = seriesModel.get('clockwise');

        var roseType = seriesModel.get('roseType');
        var stillShowZeroSum = seriesModel.get('stillShowZeroSum');

        // [0...max]
        var extent = data.getDataExtent(valueDim);
        extent[0] = 0;

        // In the case some sector angle is smaller than minAngle
        var restAngle = PI2$4;
        var valueSumLargerThanMinAngle = 0;

        var currentAngle = startAngle;
        var dir = clockwise ? 1 : -1;

        data.each(valueDim, function (value, idx) {
            var angle;
            if (isNaN(value)) {
                data.setItemLayout(idx, {
                    angle: NaN,
                    startAngle: NaN,
                    endAngle: NaN,
                    clockwise: clockwise,
                    cx: cx,
                    cy: cy,
                    r0: r0,
                    r: roseType
                        ? NaN
                        : r
                });
                return;
            }

            // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样？
            if (roseType !== 'area') {
                angle = (sum === 0 && stillShowZeroSum)
                    ? unitRadian : (value * unitRadian);
            }
            else {
                angle = PI2$4 / validDataCount;
            }

            if (angle < minAngle) {
                angle = minAngle;
                restAngle -= minAngle;
            }
            else {
                valueSumLargerThanMinAngle += value;
            }

            var endAngle = currentAngle + dir * angle;
            data.setItemLayout(idx, {
                angle: angle,
                startAngle: currentAngle,
                endAngle: endAngle,
                clockwise: clockwise,
                cx: cx,
                cy: cy,
                r0: r0,
                r: roseType
                    ? linearMap(value, extent, [r0, r])
                    : r
            });

            currentAngle = endAngle;
        });

        // Some sector is constrained by minAngle
        // Rest sectors needs recalculate angle
        if (restAngle < PI2$4 && validDataCount) {
            // Average the angle if rest angle is not enough after all angles is
            // Constrained by minAngle
            if (restAngle <= 1e-3) {
                var angle = PI2$4 / validDataCount;
                data.each(valueDim, function (value, idx) {
                    if (!isNaN(value)) {
                        var layout = data.getItemLayout(idx);
                        layout.angle = angle;
                        layout.startAngle = startAngle + dir * idx * angle;
                        layout.endAngle = startAngle + dir * (idx + 1) * angle;
                    }
                });
            }
            else {
                unitRadian = restAngle / valueSumLargerThanMinAngle;
                currentAngle = startAngle;
                data.each(valueDim, function (value, idx) {
                    if (!isNaN(value)) {
                        var layout = data.getItemLayout(idx);
                        var angle = layout.angle === minAngle
                            ? minAngle : value * unitRadian;
                        layout.startAngle = currentAngle;
                        layout.endAngle = currentAngle + dir * angle;
                        currentAngle += dir * angle;
                    }
                });
            }
        }

        labelLayout(seriesModel, r, width, height);
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var dataFilter = function (seriesType) {
    return {
        seriesType: seriesType,
        reset: function (seriesModel, ecModel) {
            var legendModels = ecModel.findComponents({
                mainType: 'legend'
            });
            if (!legendModels || !legendModels.length) {
                return;
            }
            var data = seriesModel.getData();
            data.filterSelf(function (idx) {
                var name = data.getName(idx);
                // If in any legend component the status is not selected.
                for (var i = 0; i < legendModels.length; i++) {
                    if (!legendModels[i].isSelected(name)) {
                        return false;
                    }
                }
                return true;
            });
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

createDataSelectAction('pie', [{
    type: 'pieToggleSelect',
    event: 'pieselectchanged',
    method: 'toggleSelected'
}, {
    type: 'pieSelect',
    event: 'pieselected',
    method: 'select'
}, {
    type: 'pieUnSelect',
    event: 'pieunselected',
    method: 'unSelect'
}]);

registerVisual(dataColor('pie'));
registerLayout(curry(pieLayout, 'pie'));
registerProcessor(dataFilter('pie'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.scatter',

    dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],

    getInitialData: function (option, ecModel) {
        return createListFromArray(this.getSource(), this);
    },

    brushSelector: 'point',

    getProgressive: function () {
        var progressive = this.option.progressive;
        if (progressive == null) {
            // PENDING
            return this.option.large ? 5e3 : this.get('progressive');
        }
        return progressive;
    },

    getProgressiveThreshold: function () {
        var progressiveThreshold = this.option.progressiveThreshold;
        if (progressiveThreshold == null) {
            // PENDING
            return this.option.large ? 1e4 : this.get('progressiveThreshold');
        }
        return progressiveThreshold;
    },

    defaultOption: {
        coordinateSystem: 'cartesian2d',
        zlevel: 0,
        z: 2,
        legendHoverLink: true,

        hoverAnimation: true,
        // Cartesian coordinate system
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // Polar coordinate system
        // polarIndex: 0,

        // Geo coordinate system
        // geoIndex: 0,

        // symbol: null,        // 图形类型
        symbolSize: 10,          // 图形大小，半宽（半径）参数，当图形为方向或菱形则总宽度为symbolSize * 2
        // symbolRotate: null,  // 图形旋转控制

        large: false,
        // Available when large is true
        largeThreshold: 2000,
        // cursor: null,

        // label: {
            // show: false
            // distance: 5,
            // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
            // position: 默认自适应，水平布局为'top'，垂直布局为'right'，可选为
            //           'inside'|'left'|'right'|'top'|'bottom'
            // 默认使用全局文本样式，详见TEXTSTYLE
        // },
        itemStyle: {
            opacity: 0.8
            // color: 各异
        },

        // If clip the overflow graphics
        // Works on cartesian / polar series
        clip: true

        // progressive: null
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float32Array */

// TODO Batch by color

var BOOST_SIZE_THRESHOLD = 4;

var LargeSymbolPath = extendShape({

    shape: {
        points: null
    },

    symbolProxy: null,

    softClipShape: null,

    buildPath: function (path, shape) {
        var points = shape.points;
        var size = shape.size;

        var symbolProxy = this.symbolProxy;
        var symbolProxyShape = symbolProxy.shape;
        var ctx = path.getContext ? path.getContext() : path;
        var canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD;

        // Do draw in afterBrush.
        if (canBoost) {
            return;
        }

        for (var i = 0; i < points.length;) {
            var x = points[i++];
            var y = points[i++];

            if (isNaN(x) || isNaN(y)) {
                continue;
            }
            if (this.softClipShape && !this.softClipShape.contain(x, y)) {
                continue;
            }

            symbolProxyShape.x = x - size[0] / 2;
            symbolProxyShape.y = y - size[1] / 2;
            symbolProxyShape.width = size[0];
            symbolProxyShape.height = size[1];

            symbolProxy.buildPath(path, symbolProxyShape, true);
        }
    },

    afterBrush: function (ctx) {
        var shape = this.shape;
        var points = shape.points;
        var size = shape.size;
        var canBoost = size[0] < BOOST_SIZE_THRESHOLD;

        if (!canBoost) {
            return;
        }

        this.setTransform(ctx);
        // PENDING If style or other canvas status changed?
        for (var i = 0; i < points.length;) {
            var x = points[i++];
            var y = points[i++];
            if (isNaN(x) || isNaN(y)) {
                continue;
            }
            if (this.softClipShape && !this.softClipShape.contain(x, y)) {
                continue;
            }
            // fillRect is faster than building a rect path and draw.
            // And it support light globalCompositeOperation.
            ctx.fillRect(
                x - size[0] / 2, y - size[1] / 2,
                size[0], size[1]
            );
        }

        this.restoreTransform(ctx);
    },

    findDataIndex: function (x, y) {
        // TODO ???
        // Consider transform

        var shape = this.shape;
        var points = shape.points;
        var size = shape.size;

        var w = Math.max(size[0], 4);
        var h = Math.max(size[1], 4);

        // Not consider transform
        // Treat each element as a rect
        // top down traverse
        for (var idx = points.length / 2 - 1; idx >= 0; idx--) {
            var i = idx * 2;
            var x0 = points[i] - w / 2;
            var y0 = points[i + 1] - h / 2;
            if (x >= x0 && y >= y0 && x <= x0 + w && y <= y0 + h) {
                return idx;
            }
        }

        return -1;
    }
});

function LargeSymbolDraw() {
    this.group = new Group();
}

var largeSymbolProto = LargeSymbolDraw.prototype;

largeSymbolProto.isPersistent = function () {
    return !this._incremental;
};

/**
 * Update symbols draw by new data
 * @param {module:echarts/data/List} data
 * @param {Object} opt
 * @param {Object} [opt.clipShape]
 */
largeSymbolProto.updateData = function (data, opt) {
    this.group.removeAll();
    var symbolEl = new LargeSymbolPath({
        rectHover: true,
        cursor: 'default'
    });

    symbolEl.setShape({
        points: data.getLayout('symbolPoints')
    });
    this._setCommon(symbolEl, data, false, opt);
    this.group.add(symbolEl);

    this._incremental = null;
};

largeSymbolProto.updateLayout = function (data) {
    if (this._incremental) {
        return;
    }

    var points = data.getLayout('symbolPoints');
    this.group.eachChild(function (child) {
        if (child.startIndex != null) {
            var len = (child.endIndex - child.startIndex) * 2;
            var byteOffset = child.startIndex * 4 * 2;
            points = new Float32Array(points.buffer, byteOffset, len);
        }
        child.setShape('points', points);
    });
};

largeSymbolProto.incrementalPrepareUpdate = function (data) {
    this.group.removeAll();

    this._clearIncremental();
    // Only use incremental displayables when data amount is larger than 2 million.
    // PENDING Incremental data?
    if (data.count() > 2e6) {
        if (!this._incremental) {
            this._incremental = new IncrementalDisplayble({
                silent: true
            });
        }
        this.group.add(this._incremental);
    }
    else {
        this._incremental = null;
    }
};

largeSymbolProto.incrementalUpdate = function (taskParams, data, opt) {
    var symbolEl;
    if (this._incremental) {
        symbolEl = new LargeSymbolPath();
        this._incremental.addDisplayable(symbolEl, true);
    }
    else {
        symbolEl = new LargeSymbolPath({
            rectHover: true,
            cursor: 'default',
            startIndex: taskParams.start,
            endIndex: taskParams.end
        });
        symbolEl.incremental = true;
        this.group.add(symbolEl);
    }

    symbolEl.setShape({
        points: data.getLayout('symbolPoints')
    });
    this._setCommon(symbolEl, data, !!this._incremental, opt);
};

largeSymbolProto._setCommon = function (symbolEl, data, isIncremental, opt) {
    var hostModel = data.hostModel;

    opt = opt || {};
    // TODO
    // if (data.hasItemVisual.symbolSize) {
    //     // TODO typed array?
    //     symbolEl.setShape('sizes', data.mapArray(
    //         function (idx) {
    //             var size = data.getItemVisual(idx, 'symbolSize');
    //             return (size instanceof Array) ? size : [size, size];
    //         }
    //     ));
    // }
    // else {
    var size = data.getVisual('symbolSize');
    symbolEl.setShape('size', (size instanceof Array) ? size : [size, size]);
    // }

    symbolEl.softClipShape = opt.clipShape || null;
    // Create symbolProxy to build path for each data
    symbolEl.symbolProxy = createSymbol(
        data.getVisual('symbol'), 0, 0, 0, 0
    );
    // Use symbolProxy setColor method
    symbolEl.setColor = symbolEl.symbolProxy.setColor;

    var extrudeShadow = symbolEl.shape.size[0] < BOOST_SIZE_THRESHOLD;
    symbolEl.useStyle(
        // Draw shadow when doing fillRect is extremely slow.
        hostModel.getModel('itemStyle').getItemStyle(extrudeShadow ? ['color', 'shadowBlur', 'shadowColor'] : ['color'])
    );

    var visualColor = data.getVisual('color');
    if (visualColor) {
        symbolEl.setColor(visualColor);
    }

    if (!isIncremental) {
        // Enable tooltip
        // PENDING May have performance issue when path is extremely large
        symbolEl.seriesIndex = hostModel.seriesIndex;
        symbolEl.on('mousemove', function (e) {
            symbolEl.dataIndex = null;
            var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);
            if (dataIndex >= 0) {
                // Provide dataIndex for tooltip
                symbolEl.dataIndex = dataIndex + (symbolEl.startIndex || 0);
            }
        });
    }
};

largeSymbolProto.remove = function () {
    this._clearIncremental();
    this._incremental = null;
    this.group.removeAll();
};

largeSymbolProto._clearIncremental = function () {
    var incremental = this._incremental;
    if (incremental) {
        incremental.clearDisplaybles();
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendChartView({

    type: 'scatter',

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();

        var symbolDraw = this._updateSymbolDraw(data, seriesModel);

        symbolDraw.updateData(data, {
            // TODO
            // If this parameter should be a shape or a bounding volume
            // shape will be more general.
            // But bounding volume like bounding rect will be much faster in the contain calculation
            clipShape: this._getClipShape(seriesModel)
        });

        this._finished = true;
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var symbolDraw = this._updateSymbolDraw(data, seriesModel);

        symbolDraw.incrementalPrepareUpdate(data);

        this._finished = false;
    },

    incrementalRender: function (taskParams, seriesModel, ecModel) {
        this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData(), {
            clipShape: this._getClipShape(seriesModel)
        });

        this._finished = taskParams.end === seriesModel.getData().count();
    },

    updateTransform: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        // Must mark group dirty and make sure the incremental layer will be cleared
        // PENDING
        this.group.dirty();

        if (!this._finished || data.count() > 1e4 || !this._symbolDraw.isPersistent()) {
            return {
                update: true
            };
        }
        else {
            var res = pointsLayout().reset(seriesModel);
            if (res.progress) {
                res.progress({ start: 0, end: data.count() }, data);
            }

            this._symbolDraw.updateLayout(data);
        }
    },

    _getClipShape: function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;
        var clipArea = coordSys && coordSys.getArea && coordSys.getArea();
        return seriesModel.get('clip', true) ? clipArea : null;
    },

    _updateSymbolDraw: function (data, seriesModel) {
        var symbolDraw = this._symbolDraw;
        var pipelineContext = seriesModel.pipelineContext;
        var isLargeDraw = pipelineContext.large;

        if (!symbolDraw || isLargeDraw !== this._isLargeDraw) {
            symbolDraw && symbolDraw.remove();
            symbolDraw = this._symbolDraw = isLargeDraw
                ? new LargeSymbolDraw()
                : new SymbolDraw();
            this._isLargeDraw = isLargeDraw;
            this.group.removeAll();
        }

        this.group.add(symbolDraw.group);

        return symbolDraw;
    },

    remove: function (ecModel, api) {
        this._symbolDraw && this._symbolDraw.remove(true);
        this._symbolDraw = null;
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// import * as zrUtil from 'zrender/src/core/util';

// In case developer forget to include grid component
registerVisual(visualSymbol('scatter', 'circle'));
registerLayout(pointsLayout('scatter'));

// echarts.registerProcessor(function (ecModel, api) {
//     ecModel.eachSeriesByType('scatter', function (seriesModel) {
//         var data = seriesModel.getData();
//         var coordSys = seriesModel.coordinateSystem;
//         if (coordSys.type !== 'geo') {
//             return;
//         }
//         var startPt = coordSys.pointToData([0, 0]);
//         var endPt = coordSys.pointToData([api.getWidth(), api.getHeight()]);

//         var dims = zrUtil.map(coordSys.dimensions, function (dim) {
//             return data.mapDimension(dim);
//         });
//         var range = {};
//         range[dims[0]] = [Math.min(startPt[0], endPt[0]), Math.max(startPt[0], endPt[0])];
//         range[dims[1]] = [Math.min(startPt[1], endPt[1]), Math.max(startPt[1], endPt[1])];

//         data.selectRange(range);
//     });
// });

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function IndicatorAxis(dim, scale, radiusExtent) {
    Axis.call(this, dim, scale, radiusExtent);

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = 'value';

    this.angle = 0;

    /**
     * Indicator name
     * @type {string}
     */
    this.name = '';
    /**
     * @type {module:echarts/model/Model}
     */
    this.model;
}

inherits(IndicatorAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO clockwise

function Radar(radarModel, ecModel, api) {

    this._model = radarModel;
    /**
     * Radar dimensions
     * @type {Array.<string>}
     */
    this.dimensions = [];

    this._indicatorAxes = map(radarModel.getIndicatorModels(), function (indicatorModel, idx) {
        var dim = 'indicator_' + idx;
        var indicatorAxis = new IndicatorAxis(dim,
            (indicatorModel.get('axisType') === 'log') ? new LogScale() : new IntervalScale());
        indicatorAxis.name = indicatorModel.get('name');
        // Inject model and axis
        indicatorAxis.model = indicatorModel;
        indicatorModel.axis = indicatorAxis;
        this.dimensions.push(dim);
        return indicatorAxis;
    }, this);

    this.resize(radarModel, api);

    /**
     * @type {number}
     * @readOnly
     */
    this.cx;
    /**
     * @type {number}
     * @readOnly
     */
    this.cy;
    /**
     * @type {number}
     * @readOnly
     */
    this.r;
    /**
     * @type {number}
     * @readOnly
     */
    this.r0;
    /**
     * @type {number}
     * @readOnly
     */
    this.startAngle;
}

Radar.prototype.getIndicatorAxes = function () {
    return this._indicatorAxes;
};

Radar.prototype.dataToPoint = function (value, indicatorIndex) {
    var indicatorAxis = this._indicatorAxes[indicatorIndex];

    return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex);
};

Radar.prototype.coordToPoint = function (coord, indicatorIndex) {
    var indicatorAxis = this._indicatorAxes[indicatorIndex];
    var angle = indicatorAxis.angle;
    var x = this.cx + coord * Math.cos(angle);
    var y = this.cy - coord * Math.sin(angle);
    return [x, y];
};

Radar.prototype.pointToData = function (pt) {
    var dx = pt[0] - this.cx;
    var dy = pt[1] - this.cy;
    var radius = Math.sqrt(dx * dx + dy * dy);
    dx /= radius;
    dy /= radius;

    var radian = Math.atan2(-dy, dx);

    // Find the closest angle
    // FIXME index can calculated directly
    var minRadianDiff = Infinity;
    var closestAxis;
    var closestAxisIdx = -1;
    for (var i = 0; i < this._indicatorAxes.length; i++) {
        var indicatorAxis = this._indicatorAxes[i];
        var diff = Math.abs(radian - indicatorAxis.angle);
        if (diff < minRadianDiff) {
            closestAxis = indicatorAxis;
            closestAxisIdx = i;
            minRadianDiff = diff;
        }
    }

    return [closestAxisIdx, +(closestAxis && closestAxis.coordToData(radius))];
};

Radar.prototype.resize = function (radarModel, api) {
    var center = radarModel.get('center');
    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();
    var viewSize = Math.min(viewWidth, viewHeight) / 2;
    this.cx = parsePercent$1(center[0], viewWidth);
    this.cy = parsePercent$1(center[1], viewHeight);

    this.startAngle = radarModel.get('startAngle') * Math.PI / 180;

    // radius may be single value like `20`, `'80%'`, or array like `[10, '80%']`
    var radius = radarModel.get('radius');
    if (typeof radius === 'string' || typeof radius === 'number') {
        radius = [0, radius];
    }
    this.r0 = parsePercent$1(radius[0], viewSize);
    this.r = parsePercent$1(radius[1], viewSize);

    each$1(this._indicatorAxes, function (indicatorAxis, idx) {
        indicatorAxis.setExtent(this.r0, this.r);
        var angle = (this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length);
        // Normalize to [-PI, PI]
        angle = Math.atan2(Math.sin(angle), Math.cos(angle));
        indicatorAxis.angle = angle;
    }, this);
};

Radar.prototype.update = function (ecModel, api) {
    var indicatorAxes = this._indicatorAxes;
    var radarModel = this._model;
    each$1(indicatorAxes, function (indicatorAxis) {
        indicatorAxis.scale.setExtent(Infinity, -Infinity);
    });
    ecModel.eachSeriesByType('radar', function (radarSeries, idx) {
        if (radarSeries.get('coordinateSystem') !== 'radar'
            || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel
        ) {
            return;
        }
        var data = radarSeries.getData();
        each$1(indicatorAxes, function (indicatorAxis) {
            indicatorAxis.scale.unionExtentFromData(data, data.mapDimension(indicatorAxis.dim));
        });
    }, this);

    var splitNumber = radarModel.get('splitNumber');

    function increaseInterval(interval) {
        var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10));
        // Increase interval
        var f = interval / exp10;
        if (f === 2) {
            f = 5;
        }
        else { // f is 2 or 5
            f *= 2;
        }
        return f * exp10;
    }
    // Force all the axis fixing the maxSplitNumber.
    each$1(indicatorAxes, function (indicatorAxis, idx) {
        var rawExtent = getScaleExtent(indicatorAxis.scale, indicatorAxis.model);
        niceScaleExtent(indicatorAxis.scale, indicatorAxis.model);

        var axisModel = indicatorAxis.model;
        var scale = indicatorAxis.scale;
        var fixedMin = axisModel.getMin();
        var fixedMax = axisModel.getMax();
        var interval = scale.getInterval();

        if (fixedMin != null && fixedMax != null) {
            // User set min, max, divide to get new interval
            scale.setExtent(+fixedMin, +fixedMax);
            scale.setInterval(
                (fixedMax - fixedMin) / splitNumber
            );
        }
        else if (fixedMin != null) {
            var max;
            // User set min, expand extent on the other side
            do {
                max = fixedMin + interval * splitNumber;
                scale.setExtent(+fixedMin, max);
                // Interval must been set after extent
                // FIXME
                scale.setInterval(interval);

                interval = increaseInterval(interval);
            } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1]));
        }
        else if (fixedMax != null) {
            var min;
            // User set min, expand extent on the other side
            do {
                min = fixedMax - interval * splitNumber;
                scale.setExtent(min, +fixedMax);
                scale.setInterval(interval);
                interval = increaseInterval(interval);
            } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0]));
        }
        else {
            var nicedSplitNumber = scale.getTicks().length - 1;
            if (nicedSplitNumber > splitNumber) {
                interval = increaseInterval(interval);
            }
            // PENDING
            var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval;
            var halfSplitNumber = Math.round(splitNumber / 2);
            scale.setExtent(
                round$1(center - halfSplitNumber * interval),
                round$1(center + (splitNumber - halfSplitNumber) * interval)
            );
            scale.setInterval(interval);
        }
    });
};

/**
 * Radar dimensions is based on the data
 * @type {Array}
 */
Radar.dimensions = [];

Radar.create = function (ecModel, api) {
    var radarList = [];
    ecModel.eachComponent('radar', function (radarModel) {
        var radar = new Radar(radarModel, ecModel, api);
        radarList.push(radar);
        radarModel.coordinateSystem = radar;
    });
    ecModel.eachSeriesByType('radar', function (radarSeries) {
        if (radarSeries.get('coordinateSystem') === 'radar') {
            // Inject coordinate system
            radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0];
        }
    });
    return radarList;
};

CoordinateSystemManager.register('radar', Radar);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var valueAxisDefault = axisDefault.valueAxis;

function defaultsShow(opt, show) {
    return defaults({
        show: show
    }, opt);
}

var RadarModel = extendComponentModel({

    type: 'radar',

    optionUpdated: function () {
        var boundaryGap = this.get('boundaryGap');
        var splitNumber = this.get('splitNumber');
        var scale = this.get('scale');
        var axisLine = this.get('axisLine');
        var axisTick = this.get('axisTick');
        var axisType = this.get('axisType');
        var axisLabel = this.get('axisLabel');
        var nameTextStyle = this.get('name');
        var showName = this.get('name.show');
        var nameFormatter = this.get('name.formatter');
        var nameGap = this.get('nameGap');
        var triggerEvent = this.get('triggerEvent');

        var indicatorModels = map(this.get('indicator') || [], function (indicatorOpt) {
            // PENDING
            if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) {
                indicatorOpt.min = 0;
            }
            else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) {
                indicatorOpt.max = 0;
            }
            var iNameTextStyle = nameTextStyle;
            if (indicatorOpt.color != null) {
                iNameTextStyle = defaults({color: indicatorOpt.color}, nameTextStyle);
            }
            // Use same configuration
            indicatorOpt = merge(clone(indicatorOpt), {
                boundaryGap: boundaryGap,
                splitNumber: splitNumber,
                scale: scale,
                axisLine: axisLine,
                axisTick: axisTick,
                axisType: axisType,
                axisLabel: axisLabel,
                // Compatible with 2 and use text
                name: indicatorOpt.text,
                nameLocation: 'end',
                nameGap: nameGap,
                // min: 0,
                nameTextStyle: iNameTextStyle,
                triggerEvent: triggerEvent
            }, false);
            if (!showName) {
                indicatorOpt.name = '';
            }
            if (typeof nameFormatter === 'string') {
                var indName = indicatorOpt.name;
                indicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : '');
            }
            else if (typeof nameFormatter === 'function') {
                indicatorOpt.name = nameFormatter(
                    indicatorOpt.name, indicatorOpt
                );
            }
            var model = extend(
                new Model(indicatorOpt, null, this.ecModel),
                axisModelCommonMixin
            );

            // For triggerEvent.
            model.mainType = 'radar';
            model.componentIndex = this.componentIndex;

            return model;
        }, this);

        this.getIndicatorModels = function () {
            return indicatorModels;
        };
    },

    defaultOption: {

        zlevel: 0,

        z: 0,

        center: ['50%', '50%'],

        radius: '75%',

        startAngle: 90,

        name: {
            show: true
            // formatter: null
            // textStyle: {}
        },

        boundaryGap: [0, 0],

        splitNumber: 5,

        nameGap: 15,

        scale: false,

        // Polygon or circle
        shape: 'polygon',

        axisLine: merge(
            {
                lineStyle: {
                    color: '#bbb'
                }
            },
            valueAxisDefault.axisLine
        ),
        axisLabel: defaultsShow(valueAxisDefault.axisLabel, false),
        axisTick: defaultsShow(valueAxisDefault.axisTick, false),
        axisType: 'interval',
        splitLine: defaultsShow(valueAxisDefault.splitLine, true),
        splitArea: defaultsShow(valueAxisDefault.splitArea, true),

        // {text, min, max}
        indicator: []
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var axisBuilderAttrs$1 = [
    'axisLine', 'axisTickLabel', 'axisName'
];

extendComponentView({

    type: 'radar',

    render: function (radarModel, ecModel, api) {
        var group = this.group;
        group.removeAll();

        this._buildAxes(radarModel);
        this._buildSplitLineAndArea(radarModel);
    },

    _buildAxes: function (radarModel) {
        var radar = radarModel.coordinateSystem;
        var indicatorAxes = radar.getIndicatorAxes();
        var axisBuilders = map(indicatorAxes, function (indicatorAxis) {
            var axisBuilder = new AxisBuilder(indicatorAxis.model, {
                position: [radar.cx, radar.cy],
                rotation: indicatorAxis.angle,
                labelDirection: -1,
                tickDirection: -1,
                nameDirection: 1
            });
            return axisBuilder;
        });

        each$1(axisBuilders, function (axisBuilder) {
            each$1(axisBuilderAttrs$1, axisBuilder.add, axisBuilder);
            this.group.add(axisBuilder.getGroup());
        }, this);
    },

    _buildSplitLineAndArea: function (radarModel) {
        var radar = radarModel.coordinateSystem;
        var indicatorAxes = radar.getIndicatorAxes();
        if (!indicatorAxes.length) {
            return;
        }
        var shape = radarModel.get('shape');
        var splitLineModel = radarModel.getModel('splitLine');
        var splitAreaModel = radarModel.getModel('splitArea');
        var lineStyleModel = splitLineModel.getModel('lineStyle');
        var areaStyleModel = splitAreaModel.getModel('areaStyle');

        var showSplitLine = splitLineModel.get('show');
        var showSplitArea = splitAreaModel.get('show');
        var splitLineColors = lineStyleModel.get('color');
        var splitAreaColors = areaStyleModel.get('color');

        splitLineColors = isArray(splitLineColors) ? splitLineColors : [splitLineColors];
        splitAreaColors = isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors];

        var splitLines = [];
        var splitAreas = [];

        function getColorIndex(areaOrLine, areaOrLineColorList, idx) {
            var colorIndex = idx % areaOrLineColorList.length;
            areaOrLine[colorIndex] = areaOrLine[colorIndex] || [];
            return colorIndex;
        }

        if (shape === 'circle') {
            var ticksRadius = indicatorAxes[0].getTicksCoords();
            var cx = radar.cx;
            var cy = radar.cy;
            for (var i = 0; i < ticksRadius.length; i++) {
                if (showSplitLine) {
                    var colorIndex = getColorIndex(splitLines, splitLineColors, i);
                    splitLines[colorIndex].push(new Circle({
                        shape: {
                            cx: cx,
                            cy: cy,
                            r: ticksRadius[i].coord
                        }
                    }));
                }
                if (showSplitArea && i < ticksRadius.length - 1) {
                    var colorIndex = getColorIndex(splitAreas, splitAreaColors, i);
                    splitAreas[colorIndex].push(new Ring({
                        shape: {
                            cx: cx,
                            cy: cy,
                            r0: ticksRadius[i].coord,
                            r: ticksRadius[i + 1].coord
                        }
                    }));
                }
            }
        }
        // Polyyon
        else {
            var realSplitNumber;
            var axesTicksPoints = map(indicatorAxes, function (indicatorAxis, idx) {
                var ticksCoords = indicatorAxis.getTicksCoords();
                realSplitNumber = realSplitNumber == null
                    ? ticksCoords.length - 1
                    : Math.min(ticksCoords.length - 1, realSplitNumber);
                return map(ticksCoords, function (tickCoord) {
                    return radar.coordToPoint(tickCoord.coord, idx);
                });
            });

            var prevPoints = [];
            for (var i = 0; i <= realSplitNumber; i++) {
                var points = [];
                for (var j = 0; j < indicatorAxes.length; j++) {
                    points.push(axesTicksPoints[j][i]);
                }
                // Close
                if (points[0]) {
                    points.push(points[0].slice());
                }
                else {
                    if (__DEV__) {
                        console.error('Can\'t draw value axis ' + i);
                    }
                }

                if (showSplitLine) {
                    var colorIndex = getColorIndex(splitLines, splitLineColors, i);
                    splitLines[colorIndex].push(new Polyline({
                        shape: {
                            points: points
                        }
                    }));
                }
                if (showSplitArea && prevPoints) {
                    var colorIndex = getColorIndex(splitAreas, splitAreaColors, i - 1);
                    splitAreas[colorIndex].push(new Polygon({
                        shape: {
                            points: points.concat(prevPoints)
                        }
                    }));
                }
                prevPoints = points.slice().reverse();
            }
        }

        var lineStyle = lineStyleModel.getLineStyle();
        var areaStyle = areaStyleModel.getAreaStyle();
        // Add splitArea before splitLine
        each$1(splitAreas, function (splitAreas, idx) {
            this.group.add(mergePath(
                splitAreas, {
                    style: defaults({
                        stroke: 'none',
                        fill: splitAreaColors[idx % splitAreaColors.length]
                    }, areaStyle),
                    silent: true
                }
            ));
        }, this);

        each$1(splitLines, function (splitLines, idx) {
            this.group.add(mergePath(
                splitLines, {
                    style: defaults({
                        fill: 'none',
                        stroke: splitLineColors[idx % splitLineColors.length]
                    }, lineStyle),
                    silent: true
                }
            ));
        }, this);

    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var RadarSeries = SeriesModel.extend({

    type: 'series.radar',

    dependencies: ['radar'],


    // Overwrite
    init: function (option) {
        RadarSeries.superApply(this, 'init', arguments);

        // Enable legend selection for each data item
        // Use a function instead of direct access because data reference may changed
        this.legendDataProvider = function () {
            return this.getRawData();
        };
    },

    getInitialData: function (option, ecModel) {
        return createListSimply(this, {
            generateCoord: 'indicator_',
            generateCoordCount: Infinity
        });
    },

    formatTooltip: function (dataIndex) {
        var data = this.getData();
        var coordSys = this.coordinateSystem;
        var indicatorAxes = coordSys.getIndicatorAxes();
        var name = this.getData().getName(dataIndex);
        return encodeHTML(name === '' ? this.name : name) + '<br/>'
            + map(indicatorAxes, function (axis, idx) {
                var val = data.get(data.mapDimension(axis.dim), dataIndex);
                return encodeHTML(axis.name + ' : ' + val);
            }).join('<br />');
    },

    defaultOption: {
        zlevel: 0,
        z: 2,
        coordinateSystem: 'radar',
        legendHoverLink: true,
        radarIndex: 0,
        lineStyle: {
            width: 2,
            type: 'solid'
        },
        label: {
            position: 'top'
        },
        // areaStyle: {
        // },
        // itemStyle: {}
        symbol: 'emptyCircle',
        symbolSize: 4
        // symbolRotate: null
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function normalizeSymbolSize(symbolSize) {
    if (!isArray(symbolSize)) {
        symbolSize = [+symbolSize, +symbolSize];
    }
    return symbolSize;
}

extendChartView({

    type: 'radar',

    render: function (seriesModel, ecModel, api) {
        var polar = seriesModel.coordinateSystem;
        var group = this.group;

        var data = seriesModel.getData();
        var oldData = this._data;

        function createSymbol$$1(data, idx) {
            var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
            var color = data.getItemVisual(idx, 'color');
            if (symbolType === 'none') {
                return;
            }
            var symbolSize = normalizeSymbolSize(
                data.getItemVisual(idx, 'symbolSize')
            );
            var symbolPath = createSymbol(
                symbolType, -1, -1, 2, 2, color
            );
            symbolPath.attr({
                style: {
                    strokeNoScale: true
                },
                z2: 100,
                scale: [symbolSize[0] / 2, symbolSize[1] / 2]
            });
            return symbolPath;
        }

        function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) {
            // Simply rerender all
            symbolGroup.removeAll();
            for (var i = 0; i < newPoints.length - 1; i++) {
                var symbolPath = createSymbol$$1(data, idx);
                if (symbolPath) {
                    symbolPath.__dimIdx = i;
                    if (oldPoints[i]) {
                        symbolPath.attr('position', oldPoints[i]);
                        graphic[isInit ? 'initProps' : 'updateProps'](
                            symbolPath, {
                                position: newPoints[i]
                            }, seriesModel, idx
                        );
                    }
                    else {
                        symbolPath.attr('position', newPoints[i]);
                    }
                    symbolGroup.add(symbolPath);
                }
            }
        }

        function getInitialPoints(points) {
            return map(points, function (pt) {
                return [polar.cx, polar.cy];
            });
        }
        data.diff(oldData)
            .add(function (idx) {
                var points = data.getItemLayout(idx);
                if (!points) {
                    return;
                }
                var polygon = new Polygon();
                var polyline = new Polyline();
                var target = {
                    shape: {
                        points: points
                    }
                };

                polygon.shape.points = getInitialPoints(points);
                polyline.shape.points = getInitialPoints(points);
                initProps(polygon, target, seriesModel, idx);
                initProps(polyline, target, seriesModel, idx);

                var itemGroup = new Group();
                var symbolGroup = new Group();
                itemGroup.add(polyline);
                itemGroup.add(polygon);
                itemGroup.add(symbolGroup);

                updateSymbols(
                    polyline.shape.points, points, symbolGroup, data, idx, true
                );

                data.setItemGraphicEl(idx, itemGroup);
            })
            .update(function (newIdx, oldIdx) {
                var itemGroup = oldData.getItemGraphicEl(oldIdx);
                var polyline = itemGroup.childAt(0);
                var polygon = itemGroup.childAt(1);
                var symbolGroup = itemGroup.childAt(2);
                var target = {
                    shape: {
                        points: data.getItemLayout(newIdx)
                    }
                };

                if (!target.shape.points) {
                    return;
                }
                updateSymbols(
                    polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false
                );

                updateProps(polyline, target, seriesModel);
                updateProps(polygon, target, seriesModel);

                data.setItemGraphicEl(newIdx, itemGroup);
            })
            .remove(function (idx) {
                group.remove(oldData.getItemGraphicEl(idx));
            })
            .execute();

        data.eachItemGraphicEl(function (itemGroup, idx) {
            var itemModel = data.getItemModel(idx);
            var polyline = itemGroup.childAt(0);
            var polygon = itemGroup.childAt(1);
            var symbolGroup = itemGroup.childAt(2);
            var color = data.getItemVisual(idx, 'color');

            group.add(itemGroup);

            polyline.useStyle(
                defaults(
                    itemModel.getModel('lineStyle').getLineStyle(),
                    {
                        fill: 'none',
                        stroke: color
                    }
                )
            );
            polyline.hoverStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle();

            var areaStyleModel = itemModel.getModel('areaStyle');
            var hoverAreaStyleModel = itemModel.getModel('emphasis.areaStyle');
            var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty();
            var hoverPolygonIgnore = hoverAreaStyleModel.isEmpty() && hoverAreaStyleModel.parentModel.isEmpty();

            hoverPolygonIgnore = hoverPolygonIgnore && polygonIgnore;
            polygon.ignore = polygonIgnore;

            polygon.useStyle(
                defaults(
                    areaStyleModel.getAreaStyle(),
                    {
                        fill: color,
                        opacity: 0.7
                    }
                )
            );
            polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle();

            var itemStyle = itemModel.getModel('itemStyle').getItemStyle(['color']);
            var itemHoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();
            var labelModel = itemModel.getModel('label');
            var labelHoverModel = itemModel.getModel('emphasis.label');
            symbolGroup.eachChild(function (symbolPath) {
                symbolPath.setStyle(itemStyle);
                symbolPath.hoverStyle = clone(itemHoverStyle);
                var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
                (defaultText == null || isNaN(defaultText)) && (defaultText = '');

                setLabelStyle(
                    symbolPath.style, symbolPath.hoverStyle, labelModel, labelHoverModel,
                    {
                        labelFetcher: data.hostModel,
                        labelDataIndex: idx,
                        labelDimIndex: symbolPath.__dimIdx,
                        defaultText: defaultText,
                        autoColor: color,
                        isRectText: true
                    }
                );
            });

            itemGroup.highDownOnUpdate = function (fromState, toState) {
                polygon.attr('ignore', toState === 'emphasis' ? hoverPolygonIgnore : polygonIgnore);
            };
            setHoverStyle(itemGroup);
        });

        this._data = data;
    },

    remove: function () {
        this.group.removeAll();
        this._data = null;
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var radarLayout = function (ecModel) {
    ecModel.eachSeriesByType('radar', function (seriesModel) {
        var data = seriesModel.getData();
        var points = [];
        var coordSys = seriesModel.coordinateSystem;
        if (!coordSys) {
            return;
        }

        var axes = coordSys.getIndicatorAxes();

        each$1(axes, function (axis, axisIndex) {
            data.each(data.mapDimension(axes[axisIndex].dim), function (val, dataIndex) {
                points[dataIndex] = points[dataIndex] || [];
                var point = coordSys.dataToPoint(val, axisIndex);
                points[dataIndex][axisIndex] = isValidPoint(point)
                    ? point : getValueMissingPoint(coordSys);
            });
        });

        // Close polygon
        data.each(function (idx) {
            // TODO
            // Is it appropriate to connect to the next data when some data is missing?
            // Or, should trade it like `connectNull` in line chart?
            var firstPoint = find(points[idx], function (point) {
                return isValidPoint(point);
            }) || getValueMissingPoint(coordSys);

            // Copy the first actual point to the end of the array
            points[idx].push(firstPoint.slice());
            data.setItemLayout(idx, points[idx]);
        });
    });
};

function isValidPoint(point) {
    return !isNaN(point[0]) && !isNaN(point[1]);
}

function getValueMissingPoint(coordSys) {
    // It is error-prone to input [NaN, NaN] into polygon, polygon.
    // (probably cause problem when refreshing or animating)
    return [coordSys.cx, coordSys.cy];
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Backward compat for radar chart in 2
var backwardCompat$1 = function (option) {
    var polarOptArr = option.polar;
    if (polarOptArr) {
        if (!isArray(polarOptArr)) {
            polarOptArr = [polarOptArr];
        }
        var polarNotRadar = [];
        each$1(polarOptArr, function (polarOpt, idx) {
            if (polarOpt.indicator) {
                if (polarOpt.type && !polarOpt.shape) {
                    polarOpt.shape = polarOpt.type;
                }
                option.radar = option.radar || [];
                if (!isArray(option.radar)) {
                    option.radar = [option.radar];
                }
                option.radar.push(polarOpt);
            }
            else {
                polarNotRadar.push(polarOpt);
            }
        });
        option.polar = polarNotRadar;
    }
    each$1(option.series, function (seriesOpt) {
        if (seriesOpt && seriesOpt.type === 'radar' && seriesOpt.polarIndex) {
            seriesOpt.radarIndex = seriesOpt.polarIndex;
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


// Must use radar component
registerVisual(dataColor('radar'));
registerVisual(visualSymbol('radar', 'circle'));
registerLayout(radarLayout);
registerProcessor(dataFilter('radar'));
registerPreprocessor(backwardCompat$1);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Fix for 南海诸岛

var geoCoord = [126, 25];

var points$1 = [
    [[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7],
        [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]],
    [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]],
    [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]],
    [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]],
    [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]],
    [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]],
    [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7], [37, 70.7]],
    [[48, 51.1], [51, 45.5], [53, 45.5], [50, 51.1], [48, 51.1]],
    [[51, 35], [51, 28.7], [53, 28.7], [53, 35], [51, 35]],
    [[52, 22.4], [55, 17.5], [56, 17.5], [53, 22.4], [52, 22.4]],
    [[58, 12.6], [62, 7], [63, 7], [60, 12.6], [58, 12.6]],
    [[0, 3.5], [0, 93.1], [64, 93.1], [64, 0], [63, 0], [63, 92.4],
        [1, 92.4], [1, 3.5], [0, 3.5]]
];

for (var i$1 = 0; i$1 < points$1.length; i$1++) {
    for (var k = 0; k < points$1[i$1].length; k++) {
        points$1[i$1][k][0] /= 10.5;
        points$1[i$1][k][1] /= -10.5 / 0.75;

        points$1[i$1][k][0] += geoCoord[0];
        points$1[i$1][k][1] += geoCoord[1];
    }
}

var fixNanhai = function (mapType, regions) {
    if (mapType === 'china') {
        regions.push(new Region(
            '南海诸岛',
            map(points$1, function (exterior) {
                return {
                    type: 'polygon',
                    exterior: exterior
                };
            }), geoCoord
        ));
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var coordsOffsetMap = {
    '南海诸岛': [32, 80],
    // 全国
    '广东': [0, -10],
    '香港': [10, 5],
    '澳门': [-10, 10],
    //'北京': [-10, 0],
    '天津': [5, 5]
};

var fixTextCoord = function (mapType, region) {
    if (mapType === 'china') {
        var coordFix = coordsOffsetMap[region.name];
        if (coordFix) {
            var cp = region.center;
            cp[0] += coordFix[0] / 10.5;
            cp[1] += -coordFix[1] / (10.5 / 0.75);
        }
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var geoCoordMap = {
    'Russia': [100, 60],
    'United States': [-99, 38],
    'United States of America': [-99, 38]
};

var fixGeoCoord = function (mapType, region) {
    if (mapType === 'world') {
        var geoCoord = geoCoordMap[region.name];
        if (geoCoord) {
            var cp = region.center;
            cp[0] = geoCoord[0];
            cp[1] = geoCoord[1];
        }
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Fix for 钓鱼岛

// var Region = require('../Region');
// var zrUtil = require('zrender/src/core/util');

// var geoCoord = [126, 25];

var points$2 = [
    [
        [123.45165252685547, 25.73527164402261],
        [123.49731445312499, 25.73527164402261],
        [123.49731445312499, 25.750734064600884],
        [123.45165252685547, 25.750734064600884],
        [123.45165252685547, 25.73527164402261]
    ]
];

var fixDiaoyuIsland = function (mapType, region) {
    if (mapType === 'china' && region.name === '台湾') {
        region.geometries.push({
            type: 'polygon',
            exterior: points$2[0]
        });
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Built-in GEO fixer.
var inner$7 = makeInner();

var geoJSONLoader = {

    /**
     * @param {string} mapName
     * @param {Object} mapRecord {specialAreas, geoJSON}
     * @return {Object} {regions, boundingRect}
     */
    load: function (mapName, mapRecord) {

        var parsed = inner$7(mapRecord).parsed;

        if (parsed) {
            return parsed;
        }

        var specialAreas = mapRecord.specialAreas || {};
        var geoJSON = mapRecord.geoJSON;
        var regions;

        // https://jsperf.com/try-catch-performance-overhead
        try {
            regions = geoJSON ? parseGeoJson$1(geoJSON) : [];
        }
        catch (e) {
            throw new Error('Invalid geoJson format\n' + e.message);
        }

        fixNanhai(mapName, regions);

        each$1(regions, function (region) {
            var regionName = region.name;

            fixTextCoord(mapName, region);
            fixGeoCoord(mapName, region);
            fixDiaoyuIsland(mapName, region);

            // Some area like Alaska in USA map needs to be tansformed
            // to look better
            var specialArea = specialAreas[regionName];
            if (specialArea) {
                region.transformTo(
                    specialArea.left, specialArea.top, specialArea.width, specialArea.height
                );
            }
        });

        return (inner$7(mapRecord).parsed = {
            regions: regions,
            boundingRect: getBoundingRect$1(regions)
        });
    }
};

function getBoundingRect$1(regions) {
    var rect;
    for (var i = 0; i < regions.length; i++) {
        var regionRect = regions[i].getBoundingRect();
        rect = rect || regionRect.clone();
        rect.union(regionRect);
    }
    return rect;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$8 = makeInner();

var geoSVGLoader = {

    /**
     * @param {string} mapName
     * @param {Object} mapRecord {specialAreas, geoJSON}
     * @return {Object} {root, boundingRect}
     */
    load: function (mapName, mapRecord) {
        var originRoot = inner$8(mapRecord).originRoot;
        if (originRoot) {
            return {
                root: originRoot,
                boundingRect: inner$8(mapRecord).boundingRect
            };
        }

        var graphic = buildGraphic(mapRecord);

        inner$8(mapRecord).originRoot = graphic.root;
        inner$8(mapRecord).boundingRect = graphic.boundingRect;

        return graphic;
    },

    makeGraphic: function (mapName, mapRecord, hostKey) {
        // For performance consideration (in large SVG), graphic only maked
        // when necessary and reuse them according to hostKey.
        var field = inner$8(mapRecord);
        var rootMap = field.rootMap || (field.rootMap = createHashMap());

        var root = rootMap.get(hostKey);
        if (root) {
            return root;
        }

        var originRoot = field.originRoot;
        var boundingRect = field.boundingRect;

        // For performance, if originRoot is not used by a view,
        // assign it to a view, but not reproduce graphic elements.
        if (!field.originRootHostKey) {
            field.originRootHostKey = hostKey;
            root = originRoot;
        }
        else {
            root = buildGraphic(mapRecord, boundingRect).root;
        }

        return rootMap.set(hostKey, root);
    },

    removeGraphic: function (mapName, mapRecord, hostKey) {
        var field = inner$8(mapRecord);
        var rootMap = field.rootMap;
        rootMap && rootMap.removeKey(hostKey);
        if (hostKey === field.originRootHostKey) {
            field.originRootHostKey = null;
        }
    }
};

function buildGraphic(mapRecord, boundingRect) {
    var svgXML = mapRecord.svgXML;
    var result;
    var root;

    try {
        result = svgXML && parseSVG(svgXML, {
            ignoreViewBox: true,
            ignoreRootClip: true
        }) || {};
        root = result.root;
        assert$1(root != null);
    }
    catch (e) {
        throw new Error('Invalid svg format\n' + e.message);
    }

    var svgWidth = result.width;
    var svgHeight = result.height;
    var viewBoxRect = result.viewBoxRect;

    if (!boundingRect) {
        boundingRect = (svgWidth == null || svgHeight == null)
            // If svg width / height not specified, calculate
            // bounding rect as the width / height
            ? root.getBoundingRect()
            : new BoundingRect(0, 0, 0, 0);

        if (svgWidth != null) {
            boundingRect.width = svgWidth;
        }
        if (svgHeight != null) {
            boundingRect.height = svgHeight;
        }
    }

    if (viewBoxRect) {
        var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect.width, boundingRect.height);
        var elRoot = root;
        root = new Group();
        root.add(elRoot);
        elRoot.scale = viewBoxTransform.scale;
        elRoot.position = viewBoxTransform.position;
    }

    root.setClipPath(new Rect({
        shape: boundingRect.plain()
    }));

    return {
        root: root,
        boundingRect: boundingRect
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var loaders = {
    geoJSON: geoJSONLoader,
    svg: geoSVGLoader
};

var geoSourceManager = {

    /**
     * @param {string} mapName
     * @param {Object} nameMap
     * @return {Object} source {regions, regionsMap, nameCoordMap, boundingRect}
     */
    load: function (mapName, nameMap) {
        var regions = [];
        var regionsMap = createHashMap();
        var nameCoordMap = createHashMap();
        var boundingRect;
        var mapRecords = retrieveMap(mapName);

        each$1(mapRecords, function (record) {
            var singleSource = loaders[record.type].load(mapName, record);

            each$1(singleSource.regions, function (region) {
                var regionName = region.name;

                // Try use the alias in geoNameMap
                if (nameMap && nameMap.hasOwnProperty(regionName)) {
                    region = region.cloneShallow(regionName = nameMap[regionName]);
                }

                regions.push(region);
                regionsMap.set(regionName, region);
                nameCoordMap.set(regionName, region.center);
            });

            var rect = singleSource.boundingRect;
            if (rect) {
                boundingRect
                    ? boundingRect.union(rect)
                    : (boundingRect = rect.clone());
            }
        });

        return {
            regions: regions,
            regionsMap: regionsMap,
            nameCoordMap: nameCoordMap,
            // FIXME Always return new ?
            boundingRect: boundingRect || new BoundingRect(0, 0, 0, 0)
        };
    },

    /**
     * @param {string} mapName
     * @param {string} hostKey For cache.
     * @return {Array.<module:zrender/Element>} Roots.
     */
    makeGraphic: makeInvoker('makeGraphic'),

    /**
     * @param {string} mapName
     * @param {string} hostKey For cache.
     */
    removeGraphic: makeInvoker('removeGraphic')
};

function makeInvoker(methodName) {
    return function (mapName, hostKey) {
        var mapRecords = retrieveMap(mapName);
        var results = [];

        each$1(mapRecords, function (record) {
            var method = loaders[record.type][methodName];
            method && results.push(method(mapName, record, hostKey));
        });

        return results;
    };
}

function mapNotExistsError(mapName) {
    if (__DEV__) {
        console.error(
            'Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.'
        );
    }
}

function retrieveMap(mapName) {
    var mapRecords = mapDataStorage.retrieveMap(mapName) || [];

    if (__DEV__) {
        if (!mapRecords.length) {
            mapNotExistsError(mapName);
        }
    }

    return mapRecords;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var MapSeries = SeriesModel.extend({

    type: 'series.map',

    dependencies: ['geo'],

    layoutMode: 'box',

    /**
     * Only first map series of same mapType will drawMap
     * @type {boolean}
     */
    needsDrawMap: false,

    /**
     * Group of all map series with same mapType
     * @type {boolean}
     */
    seriesGroup: [],

    getInitialData: function (option) {
        var data = createListSimply(this, ['value']);
        var valueDim = data.mapDimension('value');
        var dataNameMap = createHashMap();
        var selectTargetList = [];
        var toAppendNames = [];

        for (var i = 0, len = data.count(); i < len; i++) {
            var name = data.getName(i);
            dataNameMap.set(name, true);
            selectTargetList.push({
                name: name,
                value: data.get(valueDim, i),
                selected: retrieveRawAttr(data, i, 'selected')
            });
        }

        var geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap);
        each$1(geoSource.regions, function (region) {
            var name = region.name;
            if (!dataNameMap.get(name)) {
                selectTargetList.push({name: name});
                toAppendNames.push(name);
            }
        });

        this.updateSelectedMap(selectTargetList);

        // Complete data with missing regions. The consequent processes (like visual
        // map and render) can not be performed without a "full data". For example,
        // find `dataIndex` by name.
        data.appendValues([], toAppendNames);

        return data;
    },

    /**
     * If no host geo model, return null, which means using a
     * inner exclusive geo model.
     */
    getHostGeoModel: function () {
        var geoIndex = this.option.geoIndex;
        return geoIndex != null
            ? this.dependentModels.geo[geoIndex]
            : null;
    },

    getMapType: function () {
        return (this.getHostGeoModel() || this).option.map;
    },

    // _fillOption: function (option, mapName) {
        // Shallow clone
        // option = zrUtil.extend({}, option);

        // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap);

        // return option;
    // },

    getRawValue: function (dataIndex) {
        // Use value stored in data instead because it is calculated from multiple series
        // FIXME Provide all value of multiple series ?
        var data = this.getData();
        return data.get(data.mapDimension('value'), dataIndex);
    },

    /**
     * Get model of region
     * @param  {string} name
     * @return {module:echarts/model/Model}
     */
    getRegionModel: function (regionName) {
        var data = this.getData();
        return data.getItemModel(data.indexOfName(regionName));
    },

    /**
     * Map tooltip formatter
     *
     * @param {number} dataIndex
     */
    formatTooltip: function (dataIndex) {
        // FIXME orignalData and data is a bit confusing
        var data = this.getData();
        var formattedValue = addCommas(this.getRawValue(dataIndex));
        var name = data.getName(dataIndex);

        var seriesGroup = this.seriesGroup;
        var seriesNames = [];
        for (var i = 0; i < seriesGroup.length; i++) {
            var otherIndex = seriesGroup[i].originalData.indexOfName(name);
            var valueDim = data.mapDimension('value');
            if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) {
                seriesNames.push(
                    encodeHTML(seriesGroup[i].name)
                );
            }
        }

        return seriesNames.join(', ') + '<br />'
            + encodeHTML(name + ' : ' + formattedValue);
    },

    /**
     * @implement
     */
    getTooltipPosition: function (dataIndex) {
        if (dataIndex != null) {
            var name = this.getData().getName(dataIndex);
            var geo = this.coordinateSystem;
            var region = geo.getRegion(name);

            return region && geo.dataToPoint(region.center);
        }
    },

    setZoom: function (zoom) {
        this.option.zoom = zoom;
    },

    setCenter: function (center) {
        this.option.center = center;
    },

    defaultOption: {
        // 一级层叠
        zlevel: 0,
        // 二级层叠
        z: 2,

        coordinateSystem: 'geo',

        // map should be explicitly specified since ec3.
        map: '',

        // If `geoIndex` is not specified, a exclusive geo will be
        // created. Otherwise use the specified geo component, and
        // `map` and `mapType` are ignored.
        // geoIndex: 0,

        // 'center' | 'left' | 'right' | 'x%' | {number}
        left: 'center',
        // 'center' | 'top' | 'bottom' | 'x%' | {number}
        top: 'center',
        // right
        // bottom
        // width:
        // height

        // Aspect is width / height. Inited to be geoJson bbox aspect
        // This parameter is used for scale this aspect
        aspectScale: 0.75,

        ///// Layout with center and size
        // If you wan't to put map in a fixed size box with right aspect ratio
        // This two properties may more conveninet
        // layoutCenter: [50%, 50%]
        // layoutSize: 100


        // 数值合并方式，默认加和，可选为：
        // 'sum' | 'average' | 'max' | 'min'
        // mapValueCalculation: 'sum',
        // 地图数值计算结果小数精度
        // mapValuePrecision: 0,


        // 显示图例颜色标识（系列标识的小圆点），图例开启时有效
        showLegendSymbol: true,
        // 选择模式，默认关闭，可选single，multiple
        // selectedMode: false,
        dataRangeHoverLink: true,
        // 是否开启缩放及漫游模式
        // roam: false,

        // Define left-top, right-bottom coords to control view
        // For example, [ [180, 90], [-180, -90] ],
        // higher priority than center and zoom
        boundingCoords: null,

        // Default on center of map
        center: null,

        zoom: 1,

        scaleLimit: null,

        label: {
            show: false,
            color: '#000'
        },
        // scaleLimit: null,
        itemStyle: {
            borderWidth: 0.5,
            borderColor: '#444',
            areaColor: '#eee'
        },

        emphasis: {
            label: {
                show: true,
                color: 'rgb(100,0,0)'
            },
            itemStyle: {
                areaColor: 'rgba(255,215,0,0.8)'
            }
        }
    }

});

mixin(MapSeries, selectableMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var ATTR = '\0_ec_interaction_mutex';

function take(zr, resourceKey, userKey) {
    var store = getStore(zr);
    store[resourceKey] = userKey;
}

function release(zr, resourceKey, userKey) {
    var store = getStore(zr);
    var uKey = store[resourceKey];

    if (uKey === userKey) {
        store[resourceKey] = null;
    }
}

function isTaken(zr, resourceKey) {
    return !!getStore(zr)[resourceKey];
}

function getStore(zr) {
    return zr[ATTR] || (zr[ATTR] = {});
}

/**
 * payload: {
 *     type: 'takeGlobalCursor',
 *     key: 'dataZoomSelect', or 'brush', or ...,
 *         If no userKey, release global cursor.
 * }
 */
registerAction(
    {type: 'takeGlobalCursor', event: 'globalCursorTaken', update: 'update'},
    function () {}
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @alias module:echarts/component/helper/RoamController
 * @constructor
 * @mixin {module:zrender/mixin/Eventful}
 *
 * @param {module:zrender/zrender~ZRender} zr
 */
function RoamController(zr) {

    /**
     * @type {Function}
     */
    this.pointerChecker;

    /**
     * @type {module:zrender}
     */
    this._zr = zr;

    /**
     * @type {Object}
     */
    this._opt = {};

    // Avoid two roamController bind the same handler
    var bind$$1 = bind;
    var mousedownHandler = bind$$1(mousedown, this);
    var mousemoveHandler = bind$$1(mousemove, this);
    var mouseupHandler = bind$$1(mouseup, this);
    var mousewheelHandler = bind$$1(mousewheel, this);
    var pinchHandler = bind$$1(pinch, this);

    Eventful.call(this);

    /**
     * @param {Function} pointerChecker
     *                   input: x, y
     *                   output: boolean
     */
    this.setPointerChecker = function (pointerChecker) {
        this.pointerChecker = pointerChecker;
    };

    /**
     * Notice: only enable needed types. For example, if 'zoom'
     * is not needed, 'zoom' should not be enabled, otherwise
     * default mousewheel behaviour (scroll page) will be disabled.
     *
     * @param  {boolean|string} [controlType=true] Specify the control type,
     *                          which can be null/undefined or true/false
     *                          or 'pan/move' or 'zoom'/'scale'
     * @param {Object} [opt]
     * @param {Object} [opt.zoomOnMouseWheel=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.
     * @param {Object} [opt.moveOnMouseMove=true] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.
     * @param {Object} [opt.moveOnMouseWheel=false] The value can be: true / false / 'shift' / 'ctrl' / 'alt'.
     * @param {Object} [opt.preventDefaultMouseMove=true] When pan.
     */
    this.enable = function (controlType, opt) {

        // Disable previous first
        this.disable();

        this._opt = defaults(clone(opt) || {}, {
            zoomOnMouseWheel: true,
            moveOnMouseMove: true,
            // By default, wheel do not trigger move.
            moveOnMouseWheel: false,
            preventDefaultMouseMove: true
        });

        if (controlType == null) {
            controlType = true;
        }

        if (controlType === true || (controlType === 'move' || controlType === 'pan')) {
            zr.on('mousedown', mousedownHandler);
            zr.on('mousemove', mousemoveHandler);
            zr.on('mouseup', mouseupHandler);
        }
        if (controlType === true || (controlType === 'scale' || controlType === 'zoom')) {
            zr.on('mousewheel', mousewheelHandler);
            zr.on('pinch', pinchHandler);
        }
    };

    this.disable = function () {
        zr.off('mousedown', mousedownHandler);
        zr.off('mousemove', mousemoveHandler);
        zr.off('mouseup', mouseupHandler);
        zr.off('mousewheel', mousewheelHandler);
        zr.off('pinch', pinchHandler);
    };

    this.dispose = this.disable;

    this.isDragging = function () {
        return this._dragging;
    };

    this.isPinching = function () {
        return this._pinching;
    };
}

mixin(RoamController, Eventful);


function mousedown(e) {
    if (isMiddleOrRightButtonOnMouseUpDown(e)
        || (e.target && e.target.draggable)
    ) {
        return;
    }

    var x = e.offsetX;
    var y = e.offsetY;

    // Only check on mosedown, but not mousemove.
    // Mouse can be out of target when mouse moving.
    if (this.pointerChecker && this.pointerChecker(e, x, y)) {
        this._x = x;
        this._y = y;
        this._dragging = true;
    }
}

function mousemove(e) {
    if (!this._dragging
        || !isAvailableBehavior('moveOnMouseMove', e, this._opt)
        || e.gestureEvent === 'pinch'
        || isTaken(this._zr, 'globalPan')
    ) {
        return;
    }

    var x = e.offsetX;
    var y = e.offsetY;

    var oldX = this._x;
    var oldY = this._y;

    var dx = x - oldX;
    var dy = y - oldY;

    this._x = x;
    this._y = y;

    this._opt.preventDefaultMouseMove && stop(e.event);

    trigger(this, 'pan', 'moveOnMouseMove', e, {
        dx: dx, dy: dy, oldX: oldX, oldY: oldY, newX: x, newY: y
    });
}

function mouseup(e) {
    if (!isMiddleOrRightButtonOnMouseUpDown(e)) {
        this._dragging = false;
    }
}

function mousewheel(e) {
    var shouldZoom = isAvailableBehavior('zoomOnMouseWheel', e, this._opt);
    var shouldMove = isAvailableBehavior('moveOnMouseWheel', e, this._opt);
    var wheelDelta = e.wheelDelta;
    var absWheelDeltaDelta = Math.abs(wheelDelta);
    var originX = e.offsetX;
    var originY = e.offsetY;

    // wheelDelta maybe -0 in chrome mac.
    if (wheelDelta === 0 || (!shouldZoom && !shouldMove)) {
        return;
    }

    // If both `shouldZoom` and `shouldMove` is true, trigger
    // their event both, and the final behavior is determined
    // by event listener themselves.

    if (shouldZoom) {
        // Convenience:
        // Mac and VM Windows on Mac: scroll up: zoom out.
        // Windows: scroll up: zoom in.

        // FIXME: Should do more test in different environment.
        // wheelDelta is too complicated in difference nvironment
        // (https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel),
        // although it has been normallized by zrender.
        // wheelDelta of mouse wheel is bigger than touch pad.
        var factor = absWheelDeltaDelta > 3 ? 1.4 : absWheelDeltaDelta > 1 ? 1.2 : 1.1;
        var scale = wheelDelta > 0 ? factor : 1 / factor;
        checkPointerAndTrigger(this, 'zoom', 'zoomOnMouseWheel', e, {
            scale: scale, originX: originX, originY: originY
        });
    }

    if (shouldMove) {
        // FIXME: Should do more test in different environment.
        var absDelta = Math.abs(wheelDelta);
        // wheelDelta of mouse wheel is bigger than touch pad.
        var scrollDelta = (wheelDelta > 0 ? 1 : -1) * (absDelta > 3 ? 0.4 : absDelta > 1 ? 0.15 : 0.05);
        checkPointerAndTrigger(this, 'scrollMove', 'moveOnMouseWheel', e, {
            scrollDelta: scrollDelta, originX: originX, originY: originY
        });
    }
}

function pinch(e) {
    if (isTaken(this._zr, 'globalPan')) {
        return;
    }
    var scale = e.pinchScale > 1 ? 1.1 : 1 / 1.1;
    checkPointerAndTrigger(this, 'zoom', null, e, {
        scale: scale, originX: e.pinchX, originY: e.pinchY
    });
}

function checkPointerAndTrigger(controller, eventName, behaviorToCheck, e, contollerEvent) {
    if (controller.pointerChecker
        && controller.pointerChecker(e, contollerEvent.originX, contollerEvent.originY)
    ) {
        // When mouse is out of roamController rect,
        // default befavoius should not be be disabled, otherwise
        // page sliding is disabled, contrary to expectation.
        stop(e.event);

        trigger(controller, eventName, behaviorToCheck, e, contollerEvent);
    }
}

function trigger(controller, eventName, behaviorToCheck, e, contollerEvent) {
    // Also provide behavior checker for event listener, for some case that
    // multiple components share one listener.
    contollerEvent.isAvailableBehavior = bind(isAvailableBehavior, null, behaviorToCheck, e);
    controller.trigger(eventName, contollerEvent);
}

// settings: {
//     zoomOnMouseWheel
//     moveOnMouseMove
//     moveOnMouseWheel
// }
// The value can be: true / false / 'shift' / 'ctrl' / 'alt'.
function isAvailableBehavior(behaviorToCheck, e, settings) {
    var setting = settings[behaviorToCheck];
    return !behaviorToCheck || (
        setting && (!isString(setting) || e.event[setting + 'Key'])
    );
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * For geo and graph.
 *
 * @param {Object} controllerHost
 * @param {module:zrender/Element} controllerHost.target
 */
function updateViewOnPan(controllerHost, dx, dy) {
    var target = controllerHost.target;
    var pos = target.position;
    pos[0] += dx;
    pos[1] += dy;
    target.dirty();
}

/**
 * For geo and graph.
 *
 * @param {Object} controllerHost
 * @param {module:zrender/Element} controllerHost.target
 * @param {number} controllerHost.zoom
 * @param {number} controllerHost.zoomLimit like: {min: 1, max: 2}
 */
function updateViewOnZoom(controllerHost, zoomDelta, zoomX, zoomY) {
    var target = controllerHost.target;
    var zoomLimit = controllerHost.zoomLimit;
    var pos = target.position;
    var scale = target.scale;

    var newZoom = controllerHost.zoom = controllerHost.zoom || 1;
    newZoom *= zoomDelta;
    if (zoomLimit) {
        var zoomMin = zoomLimit.min || 0;
        var zoomMax = zoomLimit.max || Infinity;
        newZoom = Math.max(
            Math.min(zoomMax, newZoom),
            zoomMin
        );
    }
    var zoomScale = newZoom / controllerHost.zoom;
    controllerHost.zoom = newZoom;
    // Keep the mouse center when scaling
    pos[0] -= (zoomX - pos[0]) * (zoomScale - 1);
    pos[1] -= (zoomY - pos[1]) * (zoomScale - 1);
    scale[0] *= zoomScale;
    scale[1] *= zoomScale;

    target.dirty();
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var IRRELEVANT_EXCLUDES = {'axisPointer': 1, 'tooltip': 1, 'brush': 1};

/**
 * Avoid that: mouse click on a elements that is over geo or graph,
 * but roam is triggered.
 */
function onIrrelevantElement(e, api, targetCoordSysModel) {
    var model = api.getComponentByElement(e.topTarget);
    // If model is axisModel, it works only if it is injected with coordinateSystem.
    var coordSys = model && model.coordinateSystem;
    return model
        && model !== targetCoordSysModel
        && !IRRELEVANT_EXCLUDES[model.mainType]
        && (coordSys && coordSys.model !== targetCoordSysModel);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function getFixedItemStyle(model) {
    var itemStyle = model.getItemStyle();
    var areaColor = model.get('areaColor');

    // If user want the color not to be changed when hover,
    // they should both set areaColor and color to be null.
    if (areaColor != null) {
        itemStyle.fill = areaColor;
    }

    return itemStyle;
}

function updateMapSelectHandler(mapDraw, mapOrGeoModel, regionsGroup, api, fromView) {
    regionsGroup.off('click');
    regionsGroup.off('mousedown');

    if (mapOrGeoModel.get('selectedMode')) {

        regionsGroup.on('mousedown', function () {
            mapDraw._mouseDownFlag = true;
        });

        regionsGroup.on('click', function (e) {
            if (!mapDraw._mouseDownFlag) {
                return;
            }
            mapDraw._mouseDownFlag = false;

            var el = e.target;
            while (!el.__regions) {
                el = el.parent;
            }
            if (!el) {
                return;
            }

            var action = {
                type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect',
                batch: map(el.__regions, function (region) {
                    return {
                        name: region.name,
                        from: fromView.uid
                    };
                })
            };
            action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id;

            api.dispatchAction(action);

            updateMapSelected(mapOrGeoModel, regionsGroup);
        });
    }
}

function updateMapSelected(mapOrGeoModel, regionsGroup) {
    // FIXME
    regionsGroup.eachChild(function (otherRegionEl) {
        each$1(otherRegionEl.__regions, function (region) {
            otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal');
        });
    });
}

/**
 * @alias module:echarts/component/helper/MapDraw
 * @param {module:echarts/ExtensionAPI} api
 * @param {boolean} updateGroup
 */
function MapDraw(api, updateGroup) {

    var group = new Group();

    /**
     * @type {string}
     * @private
     */
    this.uid = getUID('ec_map_draw');

    /**
     * @type {module:echarts/component/helper/RoamController}
     * @private
     */
    this._controller = new RoamController(api.getZr());

    /**
     * @type {Object} {target, zoom, zoomLimit}
     * @private
     */
    this._controllerHost = {target: updateGroup ? group : null};

    /**
     * @type {module:zrender/container/Group}
     * @readOnly
     */
    this.group = group;

    /**
     * @type {boolean}
     * @private
     */
    this._updateGroup = updateGroup;

    /**
     * This flag is used to make sure that only one among
     * `pan`, `zoom`, `click` can occurs, otherwise 'selected'
     * action may be triggered when `pan`, which is unexpected.
     * @type {booelan}
     */
    this._mouseDownFlag;

    /**
     * @type {string}
     */
    this._mapName;

    /**
     * @type {boolean}
     */
    this._initialized;

    /**
     * @type {module:zrender/container/Group}
     */
    group.add(this._regionsGroup = new Group());

    /**
     * @type {module:zrender/container/Group}
     */
    group.add(this._backgroundGroup = new Group());
}

MapDraw.prototype = {

    constructor: MapDraw,

    draw: function (mapOrGeoModel, ecModel, api, fromView, payload) {

        var isGeo = mapOrGeoModel.mainType === 'geo';

        // Map series has data. GEO model that controlled by map series
        // will be assigned with map data. Other GEO model has no data.
        var data = mapOrGeoModel.getData && mapOrGeoModel.getData();
        isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) {
            if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) {
                data = mapSeries.getData();
            }
        });

        var geo = mapOrGeoModel.coordinateSystem;

        this._updateBackground(geo);

        var regionsGroup = this._regionsGroup;
        var group = this.group;

        if (geo._roamTransformable.transform) {
            group.transform = geo._roamTransformable.transform.slice();
            group.decomposeTransform();
        }

        var scale = geo._rawTransformable.scale;
        var position = geo._rawTransformable.position;

        regionsGroup.removeAll();

        var itemStyleAccessPath = ['itemStyle'];
        var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'];
        var labelAccessPath = ['label'];
        var hoverLabelAccessPath = ['emphasis', 'label'];
        var nameMap = createHashMap();

        each$1(geo.regions, function (region) {
            // Consider in GeoJson properties.name may be duplicated, for example,
            // there is multiple region named "United Kindom" or "France" (so many
            // colonies). And it is not appropriate to merge them in geo, which
            // will make them share the same label and bring trouble in label
            // location calculation.
            var regionGroup = nameMap.get(region.name)
                || nameMap.set(region.name, new Group());

            var compoundPath = new CompoundPath({
                segmentIgnoreThreshold: 1,
                shape: {
                    paths: []
                }
            });
            regionGroup.add(compoundPath);

            var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;

            var itemStyleModel = regionModel.getModel(itemStyleAccessPath);
            var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath);
            var itemStyle = getFixedItemStyle(itemStyleModel);
            var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel);

            var labelModel = regionModel.getModel(labelAccessPath);
            var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath);

            var dataIdx;
            // Use the itemStyle in data if has data
            if (data) {
                dataIdx = data.indexOfName(region.name);
                // Only visual color of each item will be used. It can be encoded by dataRange
                // But visual color of series is used in symbol drawing
                //
                // Visual color for each series is for the symbol draw
                var visualColor = data.getItemVisual(dataIdx, 'color', true);
                if (visualColor) {
                    itemStyle.fill = visualColor;
                }
            }

            var transformPoint = function (point) {
                return [
                    point[0] * scale[0] + position[0],
                    point[1] * scale[1] + position[1]
                ];
            };

            each$1(region.geometries, function (geometry) {
                if (geometry.type !== 'polygon') {
                    return;
                }
                var points = [];
                for (var i = 0; i < geometry.exterior.length; ++i) {
                    points.push(transformPoint(geometry.exterior[i]));
                }
                compoundPath.shape.paths.push(new Polygon({
                    segmentIgnoreThreshold: 1,
                    shape: {
                        points: points
                    }
                }));

                for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); ++i) {
                    var interior = geometry.interiors[i];
                    var points = [];
                    for (var j = 0; j < interior.length; ++j) {
                        points.push(transformPoint(interior[j]));
                    }
                    compoundPath.shape.paths.push(new Polygon({
                        segmentIgnoreThreshold: 1,
                        shape: {
                            points: points
                        }
                    }));
                }
            });

            compoundPath.setStyle(itemStyle);
            compoundPath.style.strokeNoScale = true;
            compoundPath.culling = true;

            // Label
            var showLabel = labelModel.get('show');
            var hoverShowLabel = hoverLabelModel.get('show');

            var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx));
            var itemLayout = data && data.getItemLayout(dataIdx);
            // In the following cases label will be drawn
            // 1. In map series and data value is NaN
            // 2. In geo component
            // 4. Region has no series legendSymbol, which will be add a showLabel flag in mapSymbolLayout
            if (
                (isGeo || isDataNaN && (showLabel || hoverShowLabel))
                || (itemLayout && itemLayout.showLabel)
            ) {
                var query = !isGeo ? dataIdx : region.name;
                var labelFetcher;

                // Consider dataIdx not found.
                if (!data || dataIdx >= 0) {
                    labelFetcher = mapOrGeoModel;
                }

                var textEl = new Text({
                    position: transformPoint(region.center.slice()),
                    // FIXME
                    // label rotation is not support yet in geo or regions of series-map
                    // that has no data. The rotation will be effected by this `scale`.
                    // So needed to change to RectText?
                    scale: [1 / group.scale[0], 1 / group.scale[1]],
                    z2: 10,
                    silent: true
                });

                setLabelStyle(
                    textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel,
                    {
                        labelFetcher: labelFetcher,
                        labelDataIndex: query,
                        defaultText: region.name,
                        useInsideStyle: false
                    },
                    {
                        textAlign: 'center',
                        textVerticalAlign: 'middle'
                    }
                );

                regionGroup.add(textEl);
            }

            // setItemGraphicEl, setHoverStyle after all polygons and labels
            // are added to the rigionGroup
            if (data) {
                data.setItemGraphicEl(dataIdx, regionGroup);
            }
            else {
                var regionModel = mapOrGeoModel.getRegionModel(region.name);
                // Package custom mouse event for geo component
                compoundPath.eventData = {
                    componentType: 'geo',
                    componentIndex: mapOrGeoModel.componentIndex,
                    geoIndex: mapOrGeoModel.componentIndex,
                    name: region.name,
                    region: (regionModel && regionModel.option) || {}
                };
            }

            var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
            groupRegions.push(region);

            regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
            setHoverStyle(regionGroup, hoverItemStyle);

            regionsGroup.add(regionGroup);
        });

        this._updateController(mapOrGeoModel, ecModel, api);

        updateMapSelectHandler(this, mapOrGeoModel, regionsGroup, api, fromView);

        updateMapSelected(mapOrGeoModel, regionsGroup);
    },

    remove: function () {
        this._regionsGroup.removeAll();
        this._backgroundGroup.removeAll();
        this._controller.dispose();
        this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid);
        this._mapName = null;
        this._controllerHost = {};
    },

    _updateBackground: function (geo) {
        var mapName = geo.map;

        if (this._mapName !== mapName) {
            each$1(geoSourceManager.makeGraphic(mapName, this.uid), function (root) {
                this._backgroundGroup.add(root);
            }, this);
        }

        this._mapName = mapName;
    },

    _updateController: function (mapOrGeoModel, ecModel, api) {
        var geo = mapOrGeoModel.coordinateSystem;
        var controller = this._controller;
        var controllerHost = this._controllerHost;

        controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit');
        controllerHost.zoom = geo.getZoom();

        // roamType is will be set default true if it is null
        controller.enable(mapOrGeoModel.get('roam') || false);
        var mainType = mapOrGeoModel.mainType;

        function makeActionBase() {
            var action = {
                type: 'geoRoam',
                componentType: mainType
            };
            action[mainType + 'Id'] = mapOrGeoModel.id;
            return action;
        }

        controller.off('pan').on('pan', function (e) {
            this._mouseDownFlag = false;

            updateViewOnPan(controllerHost, e.dx, e.dy);

            api.dispatchAction(extend(makeActionBase(), {
                dx: e.dx,
                dy: e.dy
            }));
        }, this);

        controller.off('zoom').on('zoom', function (e) {
            this._mouseDownFlag = false;

            updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);

            api.dispatchAction(extend(makeActionBase(), {
                zoom: e.scale,
                originX: e.originX,
                originY: e.originY
            }));

            if (this._updateGroup) {
                var scale = this.group.scale;
                this._regionsGroup.traverse(function (el) {
                    if (el.type === 'text') {
                        el.attr('scale', [1 / scale[0], 1 / scale[1]]);
                    }
                });
            }
        }, this);

        controller.setPointerChecker(function (e, x, y) {
            return geo.getViewRectAfterRoam().contain(x, y)
                && !onIrrelevantElement(e, api, mapOrGeoModel);
        });
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var HIGH_DOWN_PROP = '__seriesMapHighDown';
var RECORD_VERSION_PROP = '__seriesMapCallKey';

extendChartView({

    type: 'map',

    render: function (mapModel, ecModel, api, payload) {
        // Not render if it is an toggleSelect action from self
        if (payload && payload.type === 'mapToggleSelect'
            && payload.from === this.uid
        ) {
            return;
        }

        var group = this.group;
        group.removeAll();

        if (mapModel.getHostGeoModel()) {
            return;
        }

        // Not update map if it is an roam action from self
        if (!(payload && payload.type === 'geoRoam'
                && payload.componentType === 'series'
                && payload.seriesId === mapModel.id
            )
        ) {
            if (mapModel.needsDrawMap) {
                var mapDraw = this._mapDraw || new MapDraw(api, true);
                group.add(mapDraw.group);

                mapDraw.draw(mapModel, ecModel, api, this, payload);

                this._mapDraw = mapDraw;
            }
            else {
                // Remove drawed map
                this._mapDraw && this._mapDraw.remove();
                this._mapDraw = null;
            }
        }
        else {
            var mapDraw = this._mapDraw;
            mapDraw && group.add(mapDraw.group);
        }

        mapModel.get('showLegendSymbol') && ecModel.getComponent('legend')
            && this._renderSymbols(mapModel, ecModel, api);
    },

    remove: function () {
        this._mapDraw && this._mapDraw.remove();
        this._mapDraw = null;
        this.group.removeAll();
    },

    dispose: function () {
        this._mapDraw && this._mapDraw.remove();
        this._mapDraw = null;
    },

    _renderSymbols: function (mapModel, ecModel, api) {
        var originalData = mapModel.originalData;
        var group = this.group;

        originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) {
            if (isNaN(value)) {
                return;
            }

            var layout = originalData.getItemLayout(originalDataIndex);

            if (!layout || !layout.point) {
                // Not exists in map
                return;
            }

            var point = layout.point;
            var offset = layout.offset;

            var circle = new Circle({
                style: {
                    // Because the special of map draw.
                    // Which needs statistic of multiple series and draw on one map.
                    // And each series also need a symbol with legend color
                    //
                    // Layout and visual are put one the different data
                    fill: mapModel.getData().getVisual('color')
                },
                shape: {
                    cx: point[0] + offset * 9,
                    cy: point[1],
                    r: 3
                },
                silent: true,
                // Do not overlap the first series, on which labels are displayed.
                z2: 8 + (!offset ? Z2_EMPHASIS_LIFT + 1 : 0)
            });

            // Only the series that has the first value on the same region is in charge of rendering the label.
            // But consider the case:
            // series: [
            //     {id: 'X', type: 'map', map: 'm', {data: [{name: 'A', value: 11}, {name: 'B', {value: 22}]},
            //     {id: 'Y', type: 'map', map: 'm', {data: [{name: 'A', value: 21}, {name: 'C', {value: 33}]}
            // ]
            // The offset `0` of item `A` is at series `X`, but of item `C` is at series `Y`.
            // For backward compatibility, we follow the rule that render label `A` by the
            // settings on series `X` but render label `C` by the settings on series `Y`.
            if (!offset) {

                var fullData = mapModel.mainSeries.getData();
                var name = originalData.getName(originalDataIndex);

                var fullIndex = fullData.indexOfName(name);

                var itemModel = originalData.getItemModel(originalDataIndex);
                var labelModel = itemModel.getModel('label');
                var hoverLabelModel = itemModel.getModel('emphasis.label');

                var regionGroup = fullData.getItemGraphicEl(fullIndex);

                // `getFormattedLabel` needs to use `getData` inside. Here
                // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`.
                // FIXME
                // If this is not the `mainSeries`, the item model (like label formatter)
                // set on original data item will never get. But it has been working
                // like that from the begining, and this scenario is rarely encountered.
                // So it won't be fixed until have to.
                var normalText = retrieve2(
                    mapModel.getFormattedLabel(fullIndex, 'normal'),
                    name
                );
                var emphasisText = retrieve2(
                    mapModel.getFormattedLabel(fullIndex, 'emphasis'),
                    normalText
                );

                var highDownRecord = regionGroup[HIGH_DOWN_PROP];
                var recordVersion = Math.random();

                // Prevent from register listeners duplicatedly when roaming.
                if (!highDownRecord) {
                    highDownRecord = regionGroup[HIGH_DOWN_PROP] = {};
                    var onEmphasis = curry(onRegionHighDown, true);
                    var onNormal = curry(onRegionHighDown, false);
                    regionGroup.on('mouseover', onEmphasis)
                        .on('mouseout', onNormal)
                        .on('emphasis', onEmphasis)
                        .on('normal', onNormal);
                }

                // Prevent removed regions effect current grapics.
                regionGroup[RECORD_VERSION_PROP] = recordVersion;
                extend(highDownRecord, {
                    recordVersion: recordVersion,
                    circle: circle,
                    labelModel: labelModel,
                    hoverLabelModel: hoverLabelModel,
                    emphasisText: emphasisText,
                    normalText: normalText
                });

                // FIXME
                // Consider set option when emphasis.
                enterRegionHighDown(highDownRecord, false);
            }

            group.add(circle);
        });
    }
});

function onRegionHighDown(toHighOrDown) {
    var highDownRecord = this[HIGH_DOWN_PROP];
    if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) {
        enterRegionHighDown(highDownRecord, toHighOrDown);
    }
}

function enterRegionHighDown(highDownRecord, toHighOrDown) {
    var circle = highDownRecord.circle;
    var labelModel = highDownRecord.labelModel;
    var hoverLabelModel = highDownRecord.hoverLabelModel;
    var emphasisText = highDownRecord.emphasisText;
    var normalText = highDownRecord.normalText;

    if (toHighOrDown) {
        circle.style.extendFrom(
            setTextStyle({}, hoverLabelModel, {
                text: hoverLabelModel.get('show') ? emphasisText : null
            }, {isRectText: true, useInsideStyle: false}, true)
        );
        // Make label upper than others if overlaps.
        circle.__mapOriginalZ2 = circle.z2;
        circle.z2 += Z2_EMPHASIS_LIFT;
    }
    else {
        setTextStyle(circle.style, labelModel, {
            text: labelModel.get('show') ? normalText : null,
            textPosition: labelModel.getShallow('position') || 'bottom'
        }, {isRectText: true, useInsideStyle: false});
        // Trigger normalize style like padding.
        circle.dirty(false);

        if (circle.__mapOriginalZ2 != null) {
            circle.z2 = circle.__mapOriginalZ2;
            circle.__mapOriginalZ2 = null;
        }
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/coord/View} view
 * @param {Object} payload
 * @param {Object} [zoomLimit]
 */
function updateCenterAndZoom(
    view, payload, zoomLimit
) {
    var previousZoom = view.getZoom();
    var center = view.getCenter();
    var zoom = payload.zoom;

    var point = view.dataToPoint(center);

    if (payload.dx != null && payload.dy != null) {
        point[0] -= payload.dx;
        point[1] -= payload.dy;

        var center = view.pointToData(point);
        view.setCenter(center);
    }
    if (zoom != null) {
        if (zoomLimit) {
            var zoomMin = zoomLimit.min || 0;
            var zoomMax = zoomLimit.max || Infinity;
            zoom = Math.max(
                Math.min(previousZoom * zoom, zoomMax),
                zoomMin
            ) / previousZoom;
        }

        // Zoom on given point(originX, originY)
        view.scale[0] *= zoom;
        view.scale[1] *= zoom;
        var position = view.position;
        var fixX = (payload.originX - position[0]) * (zoom - 1);
        var fixY = (payload.originY - position[1]) * (zoom - 1);

        position[0] -= fixX;
        position[1] -= fixY;

        view.updateTransform();
        // Get the new center
        var center = view.pointToData(point);
        view.setCenter(center);
        view.setZoom(zoom * previousZoom);
    }

    return {
        center: view.getCenter(),
        zoom: view.getZoom()
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @payload
 * @property {string} [componentType=series]
 * @property {number} [dx]
 * @property {number} [dy]
 * @property {number} [zoom]
 * @property {number} [originX]
 * @property {number} [originY]
 */
registerAction({
    type: 'geoRoam',
    event: 'geoRoam',
    update: 'updateTransform'
}, function (payload, ecModel) {
    var componentType = payload.componentType || 'series';

    ecModel.eachComponent(
        { mainType: componentType, query: payload },
        function (componentModel) {
            var geo = componentModel.coordinateSystem;
            if (geo.type !== 'geo') {
                return;
            }

            var res = updateCenterAndZoom(
                geo, payload, componentModel.get('scaleLimit')
            );

            componentModel.setCenter
                && componentModel.setCenter(res.center);

            componentModel.setZoom
                && componentModel.setZoom(res.zoom);

            // All map series with same `map` use the same geo coordinate system
            // So the center and zoom must be in sync. Include the series not selected by legend
            if (componentType === 'series') {
                each$1(componentModel.seriesGroup, function (seriesModel) {
                    seriesModel.setCenter(res.center);
                    seriesModel.setZoom(res.zoom);
                });
            }
        }
    );
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Simple view coordinate system
 * Mapping given x, y to transformd view x, y
 */

var v2ApplyTransform$1 = applyTransform;

// Dummy transform node
function TransformDummy() {
    Transformable.call(this);
}
mixin(TransformDummy, Transformable);

function View(name) {
    /**
     * @type {string}
     */
    this.name = name;

    /**
     * @type {Object}
     */
    this.zoomLimit;

    Transformable.call(this);

    this._roamTransformable = new TransformDummy();

    this._rawTransformable = new TransformDummy();

    this._center;
    this._zoom;
}

View.prototype = {

    constructor: View,

    type: 'view',

    /**
     * @param {Array.<string>}
     * @readOnly
     */
    dimensions: ['x', 'y'],

    /**
     * Set bounding rect
     * @param {number} x
     * @param {number} y
     * @param {number} width
     * @param {number} height
     */

    // PENDING to getRect
    setBoundingRect: function (x, y, width, height) {
        this._rect = new BoundingRect(x, y, width, height);
        return this._rect;
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    // PENDING to getRect
    getBoundingRect: function () {
        return this._rect;
    },

    /**
     * @param {number} x
     * @param {number} y
     * @param {number} width
     * @param {number} height
     */
    setViewRect: function (x, y, width, height) {
        this.transformTo(x, y, width, height);
        this._viewRect = new BoundingRect(x, y, width, height);
    },

    /**
     * Transformed to particular position and size
     * @param {number} x
     * @param {number} y
     * @param {number} width
     * @param {number} height
     */
    transformTo: function (x, y, width, height) {
        var rect = this.getBoundingRect();
        var rawTransform = this._rawTransformable;

        rawTransform.transform = rect.calculateTransform(
            new BoundingRect(x, y, width, height)
        );

        rawTransform.decomposeTransform();

        this._updateTransform();
    },

    /**
     * Set center of view
     * @param {Array.<number>} [centerCoord]
     */
    setCenter: function (centerCoord) {
        if (!centerCoord) {
            return;
        }
        this._center = centerCoord;

        this._updateCenterAndZoom();
    },

    /**
     * @param {number} zoom
     */
    setZoom: function (zoom) {
        zoom = zoom || 1;

        var zoomLimit = this.zoomLimit;
        if (zoomLimit) {
            if (zoomLimit.max != null) {
                zoom = Math.min(zoomLimit.max, zoom);
            }
            if (zoomLimit.min != null) {
                zoom = Math.max(zoomLimit.min, zoom);
            }
        }
        this._zoom = zoom;

        this._updateCenterAndZoom();
    },

    /**
     * Get default center without roam
     */
    getDefaultCenter: function () {
        // Rect before any transform
        var rawRect = this.getBoundingRect();
        var cx = rawRect.x + rawRect.width / 2;
        var cy = rawRect.y + rawRect.height / 2;

        return [cx, cy];
    },

    getCenter: function () {
        return this._center || this.getDefaultCenter();
    },

    getZoom: function () {
        return this._zoom || 1;
    },

    /**
     * @return {Array.<number}
     */
    getRoamTransform: function () {
        return this._roamTransformable.getLocalTransform();
    },

    /**
     * Remove roam
     */

    _updateCenterAndZoom: function () {
        // Must update after view transform updated
        var rawTransformMatrix = this._rawTransformable.getLocalTransform();
        var roamTransform = this._roamTransformable;
        var defaultCenter = this.getDefaultCenter();
        var center = this.getCenter();
        var zoom = this.getZoom();

        center = applyTransform([], center, rawTransformMatrix);
        defaultCenter = applyTransform([], defaultCenter, rawTransformMatrix);

        roamTransform.origin = center;
        roamTransform.position = [
            defaultCenter[0] - center[0],
            defaultCenter[1] - center[1]
        ];
        roamTransform.scale = [zoom, zoom];

        this._updateTransform();
    },

    /**
     * Update transform from roam and mapLocation
     * @private
     */
    _updateTransform: function () {
        var roamTransformable = this._roamTransformable;
        var rawTransformable = this._rawTransformable;

        rawTransformable.parent = roamTransformable;
        roamTransformable.updateTransform();
        rawTransformable.updateTransform();

        copy$1(this.transform || (this.transform = []), rawTransformable.transform || create$1());

        this._rawTransform = rawTransformable.getLocalTransform();

        this.invTransform = this.invTransform || [];
        invert(this.invTransform, this.transform);

        this.decomposeTransform();
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getViewRect: function () {
        return this._viewRect;
    },

    /**
     * Get view rect after roam transform
     * @return {module:zrender/core/BoundingRect}
     */
    getViewRectAfterRoam: function () {
        var rect = this.getBoundingRect().clone();
        rect.applyTransform(this.transform);
        return rect;
    },

    /**
     * Convert a single (lon, lat) data item to (x, y) point.
     * @param {Array.<number>} data
     * @param {boolean} noRoam
     * @param {Array.<number>} [out]
     * @return {Array.<number>}
     */
    dataToPoint: function (data, noRoam, out) {
        var transform = noRoam ? this._rawTransform : this.transform;
        out = out || [];
        return transform
            ? v2ApplyTransform$1(out, data, transform)
            : copy(out, data);
    },

    /**
     * Convert a (x, y) point to (lon, lat) data
     * @param {Array.<number>} point
     * @return {Array.<number>}
     */
    pointToData: function (point) {
        var invTransform = this.invTransform;
        return invTransform
            ? v2ApplyTransform$1([], point, invTransform)
            : [point[0], point[1]];
    },

    /**
     * @implements
     * see {module:echarts/CoodinateSystem}
     */
    convertToPixel: curry(doConvert$1, 'dataToPoint'),

    /**
     * @implements
     * see {module:echarts/CoodinateSystem}
     */
    convertFromPixel: curry(doConvert$1, 'pointToData'),

    /**
     * @implements
     * see {module:echarts/CoodinateSystem}
     */
    containPoint: function (point) {
        return this.getViewRectAfterRoam().contain(point[0], point[1]);
    }

    /**
     * @return {number}
     */
    // getScalarScale: function () {
    //     // Use determinant square root of transform to mutiply scalar
    //     var m = this.transform;
    //     var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1]));
    //     return det;
    // }
};

mixin(View, Transformable);

function doConvert$1(methodName, ecModel, finder, value) {
    var seriesModel = finder.seriesModel;
    var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph.
    return coordSys === this ? coordSys[methodName](value) : null;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * [Geo description]
 * For backward compatibility, the orginal interface:
 * `name, map, geoJson, specialAreas, nameMap` is kept.
 *
 * @param {string|Object} name
 * @param {string} map Map type
 *        Specify the positioned areas by left, top, width, height
 * @param {Object.<string, string>} [nameMap]
 *        Specify name alias
 * @param {boolean} [invertLongitute=true]
 */
function Geo(name, map$$1, nameMap, invertLongitute) {

    View.call(this, name);

    /**
     * Map type
     * @type {string}
     */
    this.map = map$$1;

    var source = geoSourceManager.load(map$$1, nameMap);

    this._nameCoordMap = source.nameCoordMap;
    this._regionsMap = source.regionsMap;
    this._invertLongitute = invertLongitute == null ? true : invertLongitute;

    /**
     * @readOnly
     */
    this.regions = source.regions;

    /**
     * @type {module:zrender/src/core/BoundingRect}
     */
    this._rect = source.boundingRect;
}

Geo.prototype = {

    constructor: Geo,

    type: 'geo',

    /**
     * @param {Array.<string>}
     * @readOnly
     */
    dimensions: ['lng', 'lat'],

    /**
     * If contain given lng,lat coord
     * @param {Array.<number>}
     * @readOnly
     */
    containCoord: function (coord) {
        var regions = this.regions;
        for (var i = 0; i < regions.length; i++) {
            if (regions[i].contain(coord)) {
                return true;
            }
        }
        return false;
    },

    /**
     * @override
     */
    transformTo: function (x, y, width, height) {
        var rect = this.getBoundingRect();
        var invertLongitute = this._invertLongitute;

        rect = rect.clone();

        if (invertLongitute) {
            // Longitute is inverted
            rect.y = -rect.y - rect.height;
        }

        var rawTransformable = this._rawTransformable;

        rawTransformable.transform = rect.calculateTransform(
            new BoundingRect(x, y, width, height)
        );

        rawTransformable.decomposeTransform();

        if (invertLongitute) {
            var scale = rawTransformable.scale;
            scale[1] = -scale[1];
        }

        rawTransformable.updateTransform();

        this._updateTransform();
    },

    /**
     * @param {string} name
     * @return {module:echarts/coord/geo/Region}
     */
    getRegion: function (name) {
        return this._regionsMap.get(name);
    },

    getRegionByCoord: function (coord) {
        var regions = this.regions;
        for (var i = 0; i < regions.length; i++) {
            if (regions[i].contain(coord)) {
                return regions[i];
            }
        }
    },

    /**
     * Add geoCoord for indexing by name
     * @param {string} name
     * @param {Array.<number>} geoCoord
     */
    addGeoCoord: function (name, geoCoord) {
        this._nameCoordMap.set(name, geoCoord);
    },

    /**
     * Get geoCoord by name
     * @param {string} name
     * @return {Array.<number>}
     */
    getGeoCoord: function (name) {
        return this._nameCoordMap.get(name);
    },

    /**
     * @override
     */
    getBoundingRect: function () {
        return this._rect;
    },

    /**
     * @param {string|Array.<number>} data
     * @param {boolean} noRoam
     * @param {Array.<number>} [out]
     * @return {Array.<number>}
     */
    dataToPoint: function (data, noRoam, out) {
        if (typeof data === 'string') {
            // Map area name to geoCoord
            data = this.getGeoCoord(data);
        }
        if (data) {
            return View.prototype.dataToPoint.call(this, data, noRoam, out);
        }
    },

    /**
     * @override
     */
    convertToPixel: curry(doConvert, 'dataToPoint'),

    /**
     * @override
     */
    convertFromPixel: curry(doConvert, 'pointToData')

};

mixin(Geo, View);

function doConvert(methodName, ecModel, finder, value) {
    var geoModel = finder.geoModel;
    var seriesModel = finder.seriesModel;

    var coordSys = geoModel
        ? geoModel.coordinateSystem
        : seriesModel
        ? (
            seriesModel.coordinateSystem // For map.
            || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem
        )
        : null;

    return coordSys === this ? coordSys[methodName](value) : null;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Resize method bound to the geo
 * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel
 * @param {module:echarts/ExtensionAPI} api
 */
function resizeGeo(geoModel, api) {

    var boundingCoords = geoModel.get('boundingCoords');
    if (boundingCoords != null) {
        var leftTop = boundingCoords[0];
        var rightBottom = boundingCoords[1];
        if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) {
            if (__DEV__) {
                console.error('Invalid boundingCoords');
            }
        }
        else {
            this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]);
        }
    }

    var rect = this.getBoundingRect();

    var boxLayoutOption;

    var center = geoModel.get('layoutCenter');
    var size = geoModel.get('layoutSize');

    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();

    var aspect = rect.width / rect.height * this.aspectScale;

    var useCenterAndSize = false;

    if (center && size) {
        center = [
            parsePercent$1(center[0], viewWidth),
            parsePercent$1(center[1], viewHeight)
        ];
        size = parsePercent$1(size, Math.min(viewWidth, viewHeight));

        if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) {
            useCenterAndSize = true;
        }
        else {
            if (__DEV__) {
                console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.');
            }
        }
    }

    var viewRect;
    if (useCenterAndSize) {
        var viewRect = {};
        if (aspect > 1) {
            // Width is same with size
            viewRect.width = size;
            viewRect.height = size / aspect;
        }
        else {
            viewRect.height = size;
            viewRect.width = size * aspect;
        }
        viewRect.y = center[1] - viewRect.height / 2;
        viewRect.x = center[0] - viewRect.width / 2;
    }
    else {
        // Use left/top/width/height
        boxLayoutOption = geoModel.getBoxLayoutParams();

        // 0.75 rate
        boxLayoutOption.aspect = aspect;

        viewRect = getLayoutRect(boxLayoutOption, {
            width: viewWidth,
            height: viewHeight
        });
    }

    this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);

    this.setCenter(geoModel.get('center'));
    this.setZoom(geoModel.get('zoom'));
}

/**
 * @param {module:echarts/coord/Geo} geo
 * @param {module:echarts/model/Model} model
 * @inner
 */
function setGeoCoords(geo, model) {
    each$1(model.get('geoCoord'), function (geoCoord, name) {
        geo.addGeoCoord(name, geoCoord);
    });
}

var geoCreator = {

    // For deciding which dimensions to use when creating list data
    dimensions: Geo.prototype.dimensions,

    create: function (ecModel, api) {
        var geoList = [];

        // FIXME Create each time may be slow
        ecModel.eachComponent('geo', function (geoModel, idx) {
            var name = geoModel.get('map');

            var aspectScale = geoModel.get('aspectScale');
            var invertLongitute = true;
            var mapRecords = mapDataStorage.retrieveMap(name);
            if (mapRecords && mapRecords[0] && mapRecords[0].type === 'svg') {
                aspectScale == null && (aspectScale = 1);
                invertLongitute = false;
            }
            else {
                aspectScale == null && (aspectScale = 0.75);
            }

            var geo = new Geo(name + idx, name, geoModel.get('nameMap'), invertLongitute);

            geo.aspectScale = aspectScale;
            geo.zoomLimit = geoModel.get('scaleLimit');
            geoList.push(geo);

            setGeoCoords(geo, geoModel);

            geoModel.coordinateSystem = geo;
            geo.model = geoModel;

            // Inject resize method
            geo.resize = resizeGeo;

            geo.resize(geoModel, api);
        });

        ecModel.eachSeries(function (seriesModel) {
            var coordSys = seriesModel.get('coordinateSystem');
            if (coordSys === 'geo') {
                var geoIndex = seriesModel.get('geoIndex') || 0;
                seriesModel.coordinateSystem = geoList[geoIndex];
            }
        });

        // If has map series
        var mapModelGroupBySeries = {};

        ecModel.eachSeriesByType('map', function (seriesModel) {
            if (!seriesModel.getHostGeoModel()) {
                var mapType = seriesModel.getMapType();
                mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || [];
                mapModelGroupBySeries[mapType].push(seriesModel);
            }
        });

        each$1(mapModelGroupBySeries, function (mapSeries, mapType) {
            var nameMapList = map(mapSeries, function (singleMapSeries) {
                return singleMapSeries.get('nameMap');
            });
            var geo = new Geo(mapType, mapType, mergeAll(nameMapList));

            geo.zoomLimit = retrieve.apply(null, map(mapSeries, function (singleMapSeries) {
                return singleMapSeries.get('scaleLimit');
            }));
            geoList.push(geo);

            // Inject resize method
            geo.resize = resizeGeo;
            geo.aspectScale = mapSeries[0].get('aspectScale');

            geo.resize(mapSeries[0], api);

            each$1(mapSeries, function (singleMapSeries) {
                singleMapSeries.coordinateSystem = geo;

                setGeoCoords(geo, singleMapSeries);
            });
        });

        return geoList;
    },

    /**
     * Fill given regions array
     * @param  {Array.<Object>} originRegionArr
     * @param  {string} mapName
     * @param  {Object} [nameMap]
     * @return {Array}
     */
    getFilledRegions: function (originRegionArr, mapName, nameMap) {
        // Not use the original
        var regionsArr = (originRegionArr || []).slice();

        var dataNameMap = createHashMap();
        for (var i = 0; i < regionsArr.length; i++) {
            dataNameMap.set(regionsArr[i].name, regionsArr[i]);
        }

        var source = geoSourceManager.load(mapName, nameMap);
        each$1(source.regions, function (region) {
            var name = region.name;
            !dataNameMap.get(name) && regionsArr.push({name: name});
        });

        return regionsArr;
    }
};

registerCoordinateSystem('geo', geoCreator);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var mapSymbolLayout = function (ecModel) {

    var processedMapType = {};

    ecModel.eachSeriesByType('map', function (mapSeries) {
        var mapType = mapSeries.getMapType();
        if (mapSeries.getHostGeoModel() || processedMapType[mapType]) {
            return;
        }

        var mapSymbolOffsets = {};

        each$1(mapSeries.seriesGroup, function (subMapSeries) {
            var geo = subMapSeries.coordinateSystem;
            var data = subMapSeries.originalData;
            if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) {
                data.each(data.mapDimension('value'), function (value, idx) {
                    var name = data.getName(idx);
                    var region = geo.getRegion(name);

                    // If input series.data is [11, 22, '-'/null/undefined, 44],
                    // it will be filled with NaN: [11, 22, NaN, 44] and NaN will
                    // not be drawn. So here must validate if value is NaN.
                    if (!region || isNaN(value)) {
                        return;
                    }

                    var offset = mapSymbolOffsets[name] || 0;

                    var point = geo.dataToPoint(region.center);

                    mapSymbolOffsets[name] = offset + 1;

                    data.setItemLayout(idx, {
                        point: point,
                        offset: offset
                    });
                });
            }
        });

        // Show label of those region not has legendSymbol(which is offset 0)
        var data = mapSeries.getData();
        data.each(function (idx) {
            var name = data.getName(idx);
            var layout = data.getItemLayout(idx) || {};
            layout.showLabel = !mapSymbolOffsets[name];
            data.setItemLayout(idx, layout);
        });

        processedMapType[mapType] = true;
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var mapVisual = function (ecModel) {
    ecModel.eachSeriesByType('map', function (seriesModel) {
        var colorList = seriesModel.get('color');
        var itemStyleModel = seriesModel.getModel('itemStyle');

        var areaColor = itemStyleModel.get('areaColor');
        var color = itemStyleModel.get('color')
            || colorList[seriesModel.seriesIndex % colorList.length];

        seriesModel.getData().setVisual({
            'areaColor': areaColor,
            'color': color
        });
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME 公用？
/**
 * @param {Array.<module:echarts/data/List>} datas
 * @param {string} statisticType 'average' 'sum'
 * @inner
 */
function dataStatistics(datas, statisticType) {
    var dataNameMap = {};

    each$1(datas, function (data) {
        data.each(data.mapDimension('value'), function (value, idx) {
            // Add prefix to avoid conflict with Object.prototype.
            var mapKey = 'ec-' + data.getName(idx);
            dataNameMap[mapKey] = dataNameMap[mapKey] || [];
            if (!isNaN(value)) {
                dataNameMap[mapKey].push(value);
            }
        });
    });

    return datas[0].map(datas[0].mapDimension('value'), function (value, idx) {
        var mapKey = 'ec-' + datas[0].getName(idx);
        var sum = 0;
        var min = Infinity;
        var max = -Infinity;
        var len = dataNameMap[mapKey].length;
        for (var i = 0; i < len; i++) {
            min = Math.min(min, dataNameMap[mapKey][i]);
            max = Math.max(max, dataNameMap[mapKey][i]);
            sum += dataNameMap[mapKey][i];
        }
        var result;
        if (statisticType === 'min') {
            result = min;
        }
        else if (statisticType === 'max') {
            result = max;
        }
        else if (statisticType === 'average') {
            result = sum / len;
        }
        else {
            result = sum;
        }
        return len === 0 ? NaN : result;
    });
}

var mapDataStatistic = function (ecModel) {
    var seriesGroups = {};
    ecModel.eachSeriesByType('map', function (seriesModel) {
        var hostGeoModel = seriesModel.getHostGeoModel();
        var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType();
        (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel);
    });

    each$1(seriesGroups, function (seriesList, key) {
        var data = dataStatistics(
            map(seriesList, function (seriesModel) {
                return seriesModel.getData();
            }),
            seriesList[0].get('mapValueCalculation')
        );

        for (var i = 0; i < seriesList.length; i++) {
            seriesList[i].originalData = seriesList[i].getData();
        }

        // FIXME Put where?
        for (var i = 0; i < seriesList.length; i++) {
            seriesList[i].seriesGroup = seriesList;
            seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel();

            seriesList[i].setData(data.cloneShallow());
            seriesList[i].mainSeries = seriesList[0];
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var backwardCompat$2 = function (option) {
    // Save geoCoord
    var mapSeries = [];
    each$1(option.series, function (seriesOpt) {
        if (seriesOpt && seriesOpt.type === 'map') {
            mapSeries.push(seriesOpt);
            seriesOpt.map = seriesOpt.map || seriesOpt.mapType;
            // Put x, y, width, height, x2, y2 in the top level
            defaults(seriesOpt, seriesOpt.mapLocation);
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerLayout(mapSymbolLayout);
registerVisual(mapVisual);
registerProcessor(PRIORITY.PROCESSOR.STATISTIC, mapDataStatistic);
registerPreprocessor(backwardCompat$2);

createDataSelectAction('map', [{
    type: 'mapToggleSelect',
    event: 'mapselectchanged',
    method: 'toggleSelected'
}, {
    type: 'mapSelect',
    event: 'mapselected',
    method: 'select'
}, {
    type: 'mapUnSelect',
    event: 'mapunselected',
    method: 'unSelect'
}]);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Link lists and struct (graph or tree)
 */

var each$7 = each$1;

var DATAS = '\0__link_datas';
var MAIN_DATA = '\0__link_mainData';

// Caution:
// In most case, either list or its shallow clones (see list.cloneShallow)
// is active in echarts process. So considering heap memory consumption,
// we do not clone tree or graph, but share them among list and its shallow clones.
// But in some rare case, we have to keep old list (like do animation in chart). So
// please take care that both the old list and the new list share the same tree/graph.

/**
 * @param {Object} opt
 * @param {module:echarts/data/List} opt.mainData
 * @param {Object} [opt.struct] For example, instance of Graph or Tree.
 * @param {string} [opt.structAttr] designation: list[structAttr] = struct;
 * @param {Object} [opt.datas] {dataType: data},
 *                 like: {node: nodeList, edge: edgeList}.
 *                 Should contain mainData.
 * @param {Object} [opt.datasAttr] {dataType: attr},
 *                 designation: struct[datasAttr[dataType]] = list;
 */
function linkList(opt) {
    var mainData = opt.mainData;
    var datas = opt.datas;

    if (!datas) {
        datas = {main: mainData};
        opt.datasAttr = {main: 'data'};
    }
    opt.datas = opt.mainData = null;

    linkAll(mainData, datas, opt);

    // Porxy data original methods.
    each$7(datas, function (data) {
        each$7(mainData.TRANSFERABLE_METHODS, function (methodName) {
            data.wrapMethod(methodName, curry(transferInjection, opt));
        });

    });

    // Beyond transfer, additional features should be added to `cloneShallow`.
    mainData.wrapMethod('cloneShallow', curry(cloneShallowInjection, opt));

    // Only mainData trigger change, because struct.update may trigger
    // another changable methods, which may bring about dead lock.
    each$7(mainData.CHANGABLE_METHODS, function (methodName) {
        mainData.wrapMethod(methodName, curry(changeInjection, opt));
    });

    // Make sure datas contains mainData.
    assert$1(datas[mainData.dataType] === mainData);
}

function transferInjection(opt, res) {
    if (isMainData(this)) {
        // Transfer datas to new main data.
        var datas = extend({}, this[DATAS]);
        datas[this.dataType] = res;
        linkAll(res, datas, opt);
    }
    else {
        // Modify the reference in main data to point newData.
        linkSingle(res, this.dataType, this[MAIN_DATA], opt);
    }
    return res;
}

function changeInjection(opt, res) {
    opt.struct && opt.struct.update(this);
    return res;
}

function cloneShallowInjection(opt, res) {
    // cloneShallow, which brings about some fragilities, may be inappropriate
    // to be exposed as an API. So for implementation simplicity we can make
    // the restriction that cloneShallow of not-mainData should not be invoked
    // outside, but only be invoked here.
    each$7(res[DATAS], function (data, dataType) {
        data !== res && linkSingle(data.cloneShallow(), dataType, res, opt);
    });
    return res;
}

/**
 * Supplement method to List.
 *
 * @public
 * @param {string} [dataType] If not specified, return mainData.
 * @return {module:echarts/data/List}
 */
function getLinkedData(dataType) {
    var mainData = this[MAIN_DATA];
    return (dataType == null || mainData == null)
        ? mainData
        : mainData[DATAS][dataType];
}

function isMainData(data) {
    return data[MAIN_DATA] === data;
}

function linkAll(mainData, datas, opt) {
    mainData[DATAS] = {};
    each$7(datas, function (data, dataType) {
        linkSingle(data, dataType, mainData, opt);
    });
}

function linkSingle(data, dataType, mainData, opt) {
    mainData[DATAS][dataType] = data;
    data[MAIN_DATA] = mainData;
    data.dataType = dataType;

    if (opt.struct) {
        data[opt.structAttr] = opt.struct;
        opt.struct[opt.datasAttr[dataType]] = data;
    }

    // Supplement method.
    data.getLinkedData = getLinkedData;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Tree data structure
 *
 * @module echarts/data/Tree
 */

/**
 * @constructor module:echarts/data/Tree~TreeNode
 * @param {string} name
 * @param {module:echarts/data/Tree} hostTree
 */
var TreeNode = function (name, hostTree) {
    /**
     * @type {string}
     */
    this.name = name || '';

    /**
     * Depth of node
     *
     * @type {number}
     * @readOnly
     */
    this.depth = 0;

    /**
     * Height of the subtree rooted at this node.
     * @type {number}
     * @readOnly
     */
    this.height = 0;

    /**
     * @type {module:echarts/data/Tree~TreeNode}
     * @readOnly
     */
    this.parentNode = null;

    /**
     * Reference to list item.
     * Do not persistent dataIndex outside,
     * besause it may be changed by list.
     * If dataIndex -1,
     * this node is logical deleted (filtered) in list.
     *
     * @type {Object}
     * @readOnly
     */
    this.dataIndex = -1;

    /**
     * @type {Array.<module:echarts/data/Tree~TreeNode>}
     * @readOnly
     */
    this.children = [];

    /**
     * @type {Array.<module:echarts/data/Tree~TreeNode>}
     * @pubilc
     */
    this.viewChildren = [];

    /**
     * @type {moduel:echarts/data/Tree}
     * @readOnly
     */
    this.hostTree = hostTree;
};

TreeNode.prototype = {

    constructor: TreeNode,

    /**
     * The node is removed.
     * @return {boolean} is removed.
     */
    isRemoved: function () {
        return this.dataIndex < 0;
    },

    /**
     * Travel this subtree (include this node).
     * Usage:
     *    node.eachNode(function () { ... }); // preorder
     *    node.eachNode('preorder', function () { ... }); // preorder
     *    node.eachNode('postorder', function () { ... }); // postorder
     *    node.eachNode(
     *        {order: 'postorder', attr: 'viewChildren'},
     *        function () { ... }
     *    ); // postorder
     *
     * @param {(Object|string)} options If string, means order.
     * @param {string=} options.order 'preorder' or 'postorder'
     * @param {string=} options.attr 'children' or 'viewChildren'
     * @param {Function} cb If in preorder and return false,
     *                      its subtree will not be visited.
     * @param {Object} [context]
     */
    eachNode: function (options, cb, context) {
        if (typeof options === 'function') {
            context = cb;
            cb = options;
            options = null;
        }

        options = options || {};
        if (isString(options)) {
            options = {order: options};
        }

        var order = options.order || 'preorder';
        var children = this[options.attr || 'children'];

        var suppressVisitSub;
        order === 'preorder' && (suppressVisitSub = cb.call(context, this));

        for (var i = 0; !suppressVisitSub && i < children.length; i++) {
            children[i].eachNode(options, cb, context);
        }

        order === 'postorder' && cb.call(context, this);
    },

    /**
     * Update depth and height of this subtree.
     *
     * @param  {number} depth
     */
    updateDepthAndHeight: function (depth) {
        var height = 0;
        this.depth = depth;
        for (var i = 0; i < this.children.length; i++) {
            var child = this.children[i];
            child.updateDepthAndHeight(depth + 1);
            if (child.height > height) {
                height = child.height;
            }
        }
        this.height = height + 1;
    },

    /**
     * @param  {string} id
     * @return {module:echarts/data/Tree~TreeNode}
     */
    getNodeById: function (id) {
        if (this.getId() === id) {
            return this;
        }
        for (var i = 0, children = this.children, len = children.length; i < len; i++) {
            var res = children[i].getNodeById(id);
            if (res) {
                return res;
            }
        }
    },

    /**
     * @param {module:echarts/data/Tree~TreeNode} node
     * @return {boolean}
     */
    contains: function (node) {
        if (node === this) {
            return true;
        }
        for (var i = 0, children = this.children, len = children.length; i < len; i++) {
            var res = children[i].contains(node);
            if (res) {
                return res;
            }
        }
    },

    /**
     * @param {boolean} includeSelf Default false.
     * @return {Array.<module:echarts/data/Tree~TreeNode>} order: [root, child, grandchild, ...]
     */
    getAncestors: function (includeSelf) {
        var ancestors = [];
        var node = includeSelf ? this : this.parentNode;
        while (node) {
            ancestors.push(node);
            node = node.parentNode;
        }
        ancestors.reverse();
        return ancestors;
    },

    /**
     * @param {string|Array=} [dimension='value'] Default 'value'. can be 0, 1, 2, 3
     * @return {number} Value.
     */
    getValue: function (dimension) {
        var data = this.hostTree.data;
        return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
    },

    /**
     * @param {Object} layout
     * @param {boolean=} [merge=false]
     */
    setLayout: function (layout, merge$$1) {
        this.dataIndex >= 0
            && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge$$1);
    },

    /**
     * @return {Object} layout
     */
    getLayout: function () {
        return this.hostTree.data.getItemLayout(this.dataIndex);
    },

    /**
     * @param {string} [path]
     * @return {module:echarts/model/Model}
     */
    getModel: function (path) {
        if (this.dataIndex < 0) {
            return;
        }
        var hostTree = this.hostTree;
        var itemModel = hostTree.data.getItemModel(this.dataIndex);
        var levelModel = this.getLevelModel();
        var leavesModel;
        if (!levelModel && (this.children.length === 0 || (this.children.length !== 0 && this.isExpand === false))) {
            leavesModel = this.getLeavesModel();
        }
        return itemModel.getModel(path, (levelModel || leavesModel || hostTree.hostModel).getModel(path));
    },

    /**
     * @return {module:echarts/model/Model}
     */
    getLevelModel: function () {
        return (this.hostTree.levelModels || [])[this.depth];
    },

    /**
     * @return {module:echarts/model/Model}
     */
    getLeavesModel: function () {
        return this.hostTree.leavesModel;
    },

    /**
     * @example
     *  setItemVisual('color', color);
     *  setItemVisual({
     *      'color': color
     *  });
     */
    setVisual: function (key, value) {
        this.dataIndex >= 0
            && this.hostTree.data.setItemVisual(this.dataIndex, key, value);
    },

    /**
     * Get item visual
     */
    getVisual: function (key, ignoreParent) {
        return this.hostTree.data.getItemVisual(this.dataIndex, key, ignoreParent);
    },

    /**
     * @public
     * @return {number}
     */
    getRawIndex: function () {
        return this.hostTree.data.getRawIndex(this.dataIndex);
    },

    /**
     * @public
     * @return {string}
     */
    getId: function () {
        return this.hostTree.data.getId(this.dataIndex);
    },

    /**
     * if this is an ancestor of another node
     *
     * @public
     * @param {TreeNode} node another node
     * @return {boolean} if is ancestor
     */
    isAncestorOf: function (node) {
        var parent = node.parentNode;
        while (parent) {
            if (parent === this) {
                return true;
            }
            parent = parent.parentNode;
        }
        return false;
    },

    /**
     * if this is an descendant of another node
     *
     * @public
     * @param {TreeNode} node another node
     * @return {boolean} if is descendant
     */
    isDescendantOf: function (node) {
        return node !== this && node.isAncestorOf(this);
    }
};

/**
 * @constructor
 * @alias module:echarts/data/Tree
 * @param {module:echarts/model/Model} hostModel
 * @param {Array.<Object>} levelOptions
 * @param {Object} leavesOption
 */
function Tree(hostModel, levelOptions, leavesOption) {
    /**
     * @type {module:echarts/data/Tree~TreeNode}
     * @readOnly
     */
    this.root;

    /**
     * @type {module:echarts/data/List}
     * @readOnly
     */
    this.data;

    /**
     * Index of each item is the same as the raw index of coresponding list item.
     * @private
     * @type {Array.<module:echarts/data/Tree~TreeNode}
     */
    this._nodes = [];

    /**
     * @private
     * @readOnly
     * @type {module:echarts/model/Model}
     */
    this.hostModel = hostModel;

    /**
     * @private
     * @readOnly
     * @type {Array.<module:echarts/model/Model}
     */
    this.levelModels = map(levelOptions || [], function (levelDefine) {
        return new Model(levelDefine, hostModel, hostModel.ecModel);
    });

    this.leavesModel = new Model(leavesOption || {}, hostModel, hostModel.ecModel);
}

Tree.prototype = {

    constructor: Tree,

    type: 'tree',

    /**
     * Travel this subtree (include this node).
     * Usage:
     *    node.eachNode(function () { ... }); // preorder
     *    node.eachNode('preorder', function () { ... }); // preorder
     *    node.eachNode('postorder', function () { ... }); // postorder
     *    node.eachNode(
     *        {order: 'postorder', attr: 'viewChildren'},
     *        function () { ... }
     *    ); // postorder
     *
     * @param {(Object|string)} options If string, means order.
     * @param {string=} options.order 'preorder' or 'postorder'
     * @param {string=} options.attr 'children' or 'viewChildren'
     * @param {Function} cb
     * @param {Object}   [context]
     */
    eachNode: function (options, cb, context) {
        this.root.eachNode(options, cb, context);
    },

    /**
     * @param {number} dataIndex
     * @return {module:echarts/data/Tree~TreeNode}
     */
    getNodeByDataIndex: function (dataIndex) {
        var rawIndex = this.data.getRawIndex(dataIndex);
        return this._nodes[rawIndex];
    },

    /**
     * @param {string} name
     * @return {module:echarts/data/Tree~TreeNode}
     */
    getNodeByName: function (name) {
        return this.root.getNodeByName(name);
    },

    /**
     * Update item available by list,
     * when list has been performed options like 'filterSelf' or 'map'.
     */
    update: function () {
        var data = this.data;
        var nodes = this._nodes;

        for (var i = 0, len = nodes.length; i < len; i++) {
            nodes[i].dataIndex = -1;
        }

        for (var i = 0, len = data.count(); i < len; i++) {
            nodes[data.getRawIndex(i)].dataIndex = i;
        }
    },

    /**
     * Clear all layouts
     */
    clearLayouts: function () {
        this.data.clearItemLayouts();
    }
};

/**
 * data node format:
 * {
 *     name: ...
 *     value: ...
 *     children: [
 *         {
 *             name: ...
 *             value: ...
 *             children: ...
 *         },
 *         ...
 *     ]
 * }
 *
 * @static
 * @param {Object} dataRoot Root node.
 * @param {module:echarts/model/Model} hostModel
 * @param {Object} treeOptions
 * @param {Array.<Object>} treeOptions.levels
 * @param {Array.<Object>} treeOptions.leaves
 * @return module:echarts/data/Tree
 */
Tree.createTree = function (dataRoot, hostModel, treeOptions) {

    var tree = new Tree(hostModel, treeOptions.levels, treeOptions.leaves);
    var listData = [];
    var dimMax = 1;

    buildHierarchy(dataRoot);

    function buildHierarchy(dataNode, parentNode) {
        var value = dataNode.value;
        dimMax = Math.max(dimMax, isArray(value) ? value.length : 1);

        listData.push(dataNode);

        var node = new TreeNode(dataNode.name, tree);
        parentNode
            ? addChild(node, parentNode)
            : (tree.root = node);

        tree._nodes.push(node);

        var children = dataNode.children;
        if (children) {
            for (var i = 0; i < children.length; i++) {
                buildHierarchy(children[i], node);
            }
        }
    }

    tree.root.updateDepthAndHeight(0);

    var dimensionsInfo = createDimensions(listData, {
        coordDimensions: ['value'],
        dimensionsCount: dimMax
    });

    var list = new List(dimensionsInfo, hostModel);
    list.initData(listData);

    linkList({
        mainData: list,
        struct: tree,
        structAttr: 'tree'
    });

    tree.update();

    return tree;
};

/**
 * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote,
 * so this function is not ready and not necessary to be public.
 *
 * @param {(module:echarts/data/Tree~TreeNode|Object)} child
 */
function addChild(child, node) {
    var children = node.children;
    if (child.parentNode === node) {
        return;
    }

    children.push(child);
    child.parentNode = node;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.tree',

    layoutInfo: null,

    // can support the position parameters 'left', 'top','right','bottom', 'width',
    // 'height' in the setOption() with 'merge' mode normal.
    layoutMode: 'box',

    /**
     * Init a tree data structure from data in option series
     * @param  {Object} option  the object used to config echarts view
     * @return {module:echarts/data/List} storage initial data
     */
    getInitialData: function (option) {

        //create an virtual root
        var root = {name: option.name, children: option.data};

        var leaves = option.leaves || {};

        var treeOption = {};

        treeOption.leaves = leaves;

        var tree = Tree.createTree(root, this, treeOption);

        var treeDepth = 0;

        tree.eachNode('preorder', function (node) {
            if (node.depth > treeDepth) {
                treeDepth = node.depth;
            }
        });

        var expandAndCollapse = option.expandAndCollapse;
        var expandTreeDepth = (expandAndCollapse && option.initialTreeDepth >= 0)
            ? option.initialTreeDepth : treeDepth;

        tree.root.eachNode('preorder', function (node) {
            var item = node.hostTree.data.getRawDataItem(node.dataIndex);
            // Add item.collapsed != null, because users can collapse node original in the series.data.
            node.isExpand = (item && item.collapsed != null)
                ? !item.collapsed
                : node.depth <= expandTreeDepth;
        });

        return tree.data;
    },

    /**
     * Make the configuration 'orient' backward compatibly, with 'horizontal = LR', 'vertical = TB'.
     * @returns {string} orient
     */
    getOrient: function () {
        var orient = this.get('orient');
        if (orient === 'horizontal') {
            orient = 'LR';
        }
        else if (orient === 'vertical') {
            orient = 'TB';
        }
        return orient;
    },

    setZoom: function (zoom) {
        this.option.zoom = zoom;
    },

    setCenter: function (center) {
        this.option.center = center;
    },

    /**
     * @override
     * @param {number} dataIndex
     */
    formatTooltip: function (dataIndex) {
        var tree = this.getData().tree;
        var realRoot = tree.root.children[0];
        var node = tree.getNodeByDataIndex(dataIndex);
        var value = node.getValue();
        var name = node.name;
        while (node && (node !== realRoot)) {
            name = node.parentNode.name + '.' + name;
            node = node.parentNode;
        }
        return encodeHTML(name + (
            (isNaN(value) || value == null) ? '' : ' : ' + value
        ));
    },

    defaultOption: {
        zlevel: 0,
        z: 2,
        coordinateSystem: 'view',

        // the position of the whole view
        left: '12%',
        top: '12%',
        right: '12%',
        bottom: '12%',

        // the layout of the tree, two value can be selected, 'orthogonal' or 'radial'
        layout: 'orthogonal',

        // true | false | 'move' | 'scale', see module:component/helper/RoamController.
        roam: false,

        // Symbol size scale ratio in roam
        nodeScaleRatio: 0.4,

        // Default on center of graph
        center: null,

        zoom: 1,

        // The orient of orthoginal layout, can be setted to 'LR', 'TB', 'RL', 'BT'.
        // and the backward compatibility configuration 'horizontal = LR', 'vertical = TB'.
        orient: 'LR',

        symbol: 'emptyCircle',

        symbolSize: 7,

        expandAndCollapse: true,

        initialTreeDepth: 2,

        lineStyle: {
            color: '#ccc',
            width: 1.5,
            curveness: 0.5
        },

        itemStyle: {
            color: 'lightsteelblue',
            borderColor: '#c23531',
            borderWidth: 1.5
        },

        label: {
            show: true,
            color: '#555'
        },

        leaves: {
            label: {
                show: true
            }
        },

        animationEasing: 'linear',

        animationDuration: 700,

        animationDurationUpdate: 1000
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* A third-party license is embeded for some of the code in this file:
* The tree layoutHelper implementation was originally copied from
* "d3.js"(https://github.com/d3/d3-hierarchy) with
* some modifications made for this project.
* (see more details in the comment of the specific method below.)
* The use of the source code of this file is also subject to the terms
* and consitions of the licence of "d3.js" (BSD-3Clause, see
* </licenses/LICENSE-d3>).
*/

/**
 * @file The layout algorithm of node-link tree diagrams. Here we using Reingold-Tilford algorithm to drawing
 *       the tree.
 */

/**
 * Initialize all computational message for following algorithm.
 *
 * @param  {module:echarts/data/Tree~TreeNode} root   The virtual root of the tree.
 */
function init$2(root) {
    root.hierNode = {
        defaultAncestor: null,
        ancestor: root,
        prelim: 0,
        modifier: 0,
        change: 0,
        shift: 0,
        i: 0,
        thread: null
    };

    var nodes = [root];
    var node;
    var children;

    while (node = nodes.pop()) { // jshint ignore:line
        children = node.children;
        if (node.isExpand && children.length) {
            var n = children.length;
            for (var i = n - 1; i >= 0; i--) {
                var child = children[i];
                child.hierNode = {
                    defaultAncestor: null,
                    ancestor: child,
                    prelim: 0,
                    modifier: 0,
                    change: 0,
                    shift: 0,
                    i: i,
                    thread: null
                };
                nodes.push(child);
            }
        }
    }
}

/**
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * Computes a preliminary x coordinate for node. Before that, this function is
 * applied recursively to the children of node, as well as the function
 * apportion(). After spacing out the children by calling executeShifts(), the
 * node is placed to the midpoint of its outermost children.
 *
 * @param  {module:echarts/data/Tree~TreeNode} node
 * @param {Function} separation
 */
function firstWalk(node, separation) {
    var children = node.isExpand ? node.children : [];
    var siblings = node.parentNode.children;
    var subtreeW = node.hierNode.i ? siblings[node.hierNode.i - 1] : null;
    if (children.length) {
        executeShifts(node);
        var midPoint = (children[0].hierNode.prelim + children[children.length - 1].hierNode.prelim) / 2;
        if (subtreeW) {
            node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW);
            node.hierNode.modifier = node.hierNode.prelim - midPoint;
        }
        else {
            node.hierNode.prelim = midPoint;
        }
    }
    else if (subtreeW) {
        node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW);
    }
    node.parentNode.hierNode.defaultAncestor = apportion(
        node,
        subtreeW,
        node.parentNode.hierNode.defaultAncestor || siblings[0],
        separation
    );
}


/**
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * Computes all real x-coordinates by summing up the modifiers recursively.
 *
 * @param  {module:echarts/data/Tree~TreeNode} node
 */
function secondWalk(node) {
    var nodeX = node.hierNode.prelim + node.parentNode.hierNode.modifier;
    node.setLayout({x: nodeX}, true);
    node.hierNode.modifier += node.parentNode.hierNode.modifier;
}


function separation(cb) {
    return arguments.length ? cb : defaultSeparation;
}

/**
 * Transform the common coordinate to radial coordinate.
 *
 * @param  {number} x
 * @param  {number} y
 * @return {Object}
 */
function radialCoordinate(x, y) {
    var radialCoor = {};
    x -= Math.PI / 2;
    radialCoor.x = y * Math.cos(x);
    radialCoor.y = y * Math.sin(x);
    return radialCoor;
}

/**
 * Get the layout position of the whole view.
 *
 * @param {module:echarts/model/Series} seriesModel  the model object of sankey series
 * @param {module:echarts/ExtensionAPI} api  provide the API list that the developer can call
 * @return {module:zrender/core/BoundingRect}  size of rect to draw the sankey view
 */
function getViewRect(seriesModel, api) {
    return getLayoutRect(
        seriesModel.getBoxLayoutParams(), {
            width: api.getWidth(),
            height: api.getHeight()
        }
    );
}

/**
 * All other shifts, applied to the smaller subtrees between w- and w+, are
 * performed by this function.
 *
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * @param  {module:echarts/data/Tree~TreeNode} node
 */
function executeShifts(node) {
    var children = node.children;
    var n = children.length;
    var shift = 0;
    var change = 0;
    while (--n >= 0) {
        var child = children[n];
        child.hierNode.prelim += shift;
        child.hierNode.modifier += shift;
        change += child.hierNode.change;
        shift += child.hierNode.shift + change;
    }
}

/**
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * The core of the algorithm. Here, a new subtree is combined with the
 * previous subtrees. Threads are used to traverse the inside and outside
 * contours of the left and right subtree up to the highest common level.
 * Whenever two nodes of the inside contours conflict, we compute the left
 * one of the greatest uncommon ancestors using the function nextAncestor()
 * and call moveSubtree() to shift the subtree and prepare the shifts of
 * smaller subtrees. Finally, we add a new thread (if necessary).
 *
 * @param  {module:echarts/data/Tree~TreeNode} subtreeV
 * @param  {module:echarts/data/Tree~TreeNode} subtreeW
 * @param  {module:echarts/data/Tree~TreeNode} ancestor
 * @param  {Function} separation
 * @return {module:echarts/data/Tree~TreeNode}
 */
function apportion(subtreeV, subtreeW, ancestor, separation) {

    if (subtreeW) {
        var nodeOutRight = subtreeV;
        var nodeInRight = subtreeV;
        var nodeOutLeft = nodeInRight.parentNode.children[0];
        var nodeInLeft = subtreeW;

        var sumOutRight = nodeOutRight.hierNode.modifier;
        var sumInRight = nodeInRight.hierNode.modifier;
        var sumOutLeft = nodeOutLeft.hierNode.modifier;
        var sumInLeft = nodeInLeft.hierNode.modifier;

        while (nodeInLeft = nextRight(nodeInLeft), nodeInRight = nextLeft(nodeInRight), nodeInLeft && nodeInRight) {
            nodeOutRight = nextRight(nodeOutRight);
            nodeOutLeft = nextLeft(nodeOutLeft);
            nodeOutRight.hierNode.ancestor = subtreeV;
            var shift = nodeInLeft.hierNode.prelim + sumInLeft - nodeInRight.hierNode.prelim
                    - sumInRight + separation(nodeInLeft, nodeInRight);
            if (shift > 0) {
                moveSubtree(nextAncestor(nodeInLeft, subtreeV, ancestor), subtreeV, shift);
                sumInRight += shift;
                sumOutRight += shift;
            }
            sumInLeft += nodeInLeft.hierNode.modifier;
            sumInRight += nodeInRight.hierNode.modifier;
            sumOutRight += nodeOutRight.hierNode.modifier;
            sumOutLeft += nodeOutLeft.hierNode.modifier;
        }
        if (nodeInLeft && !nextRight(nodeOutRight)) {
            nodeOutRight.hierNode.thread = nodeInLeft;
            nodeOutRight.hierNode.modifier += sumInLeft - sumOutRight;

        }
        if (nodeInRight && !nextLeft(nodeOutLeft)) {
            nodeOutLeft.hierNode.thread = nodeInRight;
            nodeOutLeft.hierNode.modifier += sumInRight - sumOutLeft;
            ancestor = subtreeV;
        }
    }
    return ancestor;
}

/**
 * This function is used to traverse the right contour of a subtree.
 * It returns the rightmost child of node or the thread of node. The function
 * returns null if and only if node is on the highest depth of its subtree.
 *
 * @param  {module:echarts/data/Tree~TreeNode} node
 * @return {module:echarts/data/Tree~TreeNode}
 */
function nextRight(node) {
    var children = node.children;
    return children.length && node.isExpand ? children[children.length - 1] : node.hierNode.thread;
}

/**
 * This function is used to traverse the left contour of a subtree (or a subforest).
 * It returns the leftmost child of node or the thread of node. The function
 * returns null if and only if node is on the highest depth of its subtree.
 *
 * @param  {module:echarts/data/Tree~TreeNode} node
 * @return {module:echarts/data/Tree~TreeNode}
 */
function nextLeft(node) {
    var children = node.children;
    return children.length && node.isExpand ? children[0] : node.hierNode.thread;
}

/**
 * If nodeInLeft’s ancestor is a sibling of node, returns nodeInLeft’s ancestor.
 * Otherwise, returns the specified ancestor.
 *
 * @param  {module:echarts/data/Tree~TreeNode} nodeInLeft
 * @param  {module:echarts/data/Tree~TreeNode} node
 * @param  {module:echarts/data/Tree~TreeNode} ancestor
 * @return {module:echarts/data/Tree~TreeNode}
 */
function nextAncestor(nodeInLeft, node, ancestor) {
    return nodeInLeft.hierNode.ancestor.parentNode === node.parentNode
        ? nodeInLeft.hierNode.ancestor : ancestor;
}

/**
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * Shifts the current subtree rooted at wr.
 * This is done by increasing prelim(w+) and modifier(w+) by shift.
 *
 * @param  {module:echarts/data/Tree~TreeNode} wl
 * @param  {module:echarts/data/Tree~TreeNode} wr
 * @param  {number} shift [description]
 */
function moveSubtree(wl, wr, shift) {
    var change = shift / (wr.hierNode.i - wl.hierNode.i);
    wr.hierNode.change -= change;
    wr.hierNode.shift += shift;
    wr.hierNode.modifier += shift;
    wr.hierNode.prelim += shift;
    wl.hierNode.change += change;
}

/**
 * The implementation of this function was originally copied from "d3.js"
 * <https://github.com/d3/d3-hierarchy/blob/4c1f038f2725d6eae2e49b61d01456400694bac4/src/tree.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 */
function defaultSeparation(node1, node2) {
    return node1.parentNode === node2.parentNode ? 1 : 2;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendChartView({

    type: 'tree',

    /**
     * Init the chart
     * @override
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    init: function (ecModel, api) {

        /**
         * @private
         * @type {module:echarts/data/Tree}
         */
        this._oldTree;

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this._mainGroup = new Group();

        /**
         * @private
         * @type {module:echarts/componet/helper/RoamController}
         */
        this._controller = new RoamController(api.getZr());

        this._controllerHost = {target: this.group};

        this.group.add(this._mainGroup);
    },

    render: function (seriesModel, ecModel, api, payload) {
        var data = seriesModel.getData();

        var layoutInfo = seriesModel.layoutInfo;

        var group = this._mainGroup;

        var layout = seriesModel.get('layout');

        if (layout === 'radial') {
            group.attr('position', [layoutInfo.x + layoutInfo.width / 2, layoutInfo.y + layoutInfo.height / 2]);
        }
        else {
            group.attr('position', [layoutInfo.x, layoutInfo.y]);
        }

        this._updateViewCoordSys(seriesModel, layoutInfo, layout);
        this._updateController(seriesModel, ecModel, api);

        var oldData = this._data;

        var seriesScope = {
            expandAndCollapse: seriesModel.get('expandAndCollapse'),
            layout: layout,
            orient: seriesModel.getOrient(),
            curvature: seriesModel.get('lineStyle.curveness'),
            symbolRotate: seriesModel.get('symbolRotate'),
            symbolOffset: seriesModel.get('symbolOffset'),
            hoverAnimation: seriesModel.get('hoverAnimation'),
            useNameLabel: true,
            fadeIn: true
        };

        data.diff(oldData)
            .add(function (newIdx) {
                if (symbolNeedsDraw$1(data, newIdx)) {
                    // Create node and edge
                    updateNode(data, newIdx, null, group, seriesModel, seriesScope);
                }
            })
            .update(function (newIdx, oldIdx) {
                var symbolEl = oldData.getItemGraphicEl(oldIdx);
                if (!symbolNeedsDraw$1(data, newIdx)) {
                    symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope);
                    return;
                }
                // Update node and edge
                updateNode(data, newIdx, symbolEl, group, seriesModel, seriesScope);
            })
            .remove(function (oldIdx) {
                var symbolEl = oldData.getItemGraphicEl(oldIdx);
                // When remove a collapsed node of subtree, since the collapsed
                // node haven't been initialized with a symbol element,
                // you can't found it's symbol element through index.
                // so if we want to remove the symbol element we should insure
                // that the symbol element is not null.
                if (symbolEl) {
                    removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope);
                }
            })
            .execute();

        this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');

        this._updateNodeAndLinkScale(seriesModel);

        if (seriesScope.expandAndCollapse === true) {
            data.eachItemGraphicEl(function (el, dataIndex) {
                el.off('click').on('click', function () {
                    api.dispatchAction({
                        type: 'treeExpandAndCollapse',
                        seriesId: seriesModel.id,
                        dataIndex: dataIndex
                    });
                });
            });
        }
        this._data = data;
    },

    _updateViewCoordSys: function (seriesModel) {
        var data = seriesModel.getData();
        var points = [];
        data.each(function (idx) {
            var layout = data.getItemLayout(idx);
            if (layout && !isNaN(layout.x) && !isNaN(layout.y)) {
                points.push([+layout.x, +layout.y]);
            }
        });
        var min = [];
        var max = [];
        fromPoints(points, min, max);

        // If don't Store min max when collapse the root node after roam,
        // the root node will disappear.
        var oldMin = this._min;
        var oldMax = this._max;

        // If width or height is 0
        if (max[0] - min[0] === 0) {
            min[0] = oldMin ? oldMin[0] : min[0] - 1;
            max[0] = oldMax ? oldMax[0] : max[0] + 1;
        }
        if (max[1] - min[1] === 0) {
            min[1] = oldMin ? oldMin[1] : min[1] - 1;
            max[1] = oldMax ? oldMax[1] : max[1] + 1;
        }

        var viewCoordSys = seriesModel.coordinateSystem = new View();
        viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');

        viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);

        viewCoordSys.setCenter(seriesModel.get('center'));
        viewCoordSys.setZoom(seriesModel.get('zoom'));

        // Here we use viewCoordSys just for computing the 'position' and 'scale' of the group
        this.group.attr({
            position: viewCoordSys.position,
            scale: viewCoordSys.scale
        });

        this._viewCoordSys = viewCoordSys;
        this._min = min;
        this._max = max;
    },

    _updateController: function (seriesModel, ecModel, api) {
        var controller = this._controller;
        var controllerHost = this._controllerHost;
        var group = this.group;
        controller.setPointerChecker(function (e, x, y) {
            var rect = group.getBoundingRect();
            rect.applyTransform(group.transform);
            return rect.contain(x, y)
                && !onIrrelevantElement(e, api, seriesModel);
        });

        controller.enable(seriesModel.get('roam'));
        controllerHost.zoomLimit = seriesModel.get('scaleLimit');
        controllerHost.zoom = seriesModel.coordinateSystem.getZoom();

        controller
            .off('pan')
            .off('zoom')
            .on('pan', function (e) {
                updateViewOnPan(controllerHost, e.dx, e.dy);
                api.dispatchAction({
                    seriesId: seriesModel.id,
                    type: 'treeRoam',
                    dx: e.dx,
                    dy: e.dy
                });
            }, this)
            .on('zoom', function (e) {
                updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
                api.dispatchAction({
                    seriesId: seriesModel.id,
                    type: 'treeRoam',
                    zoom: e.scale,
                    originX: e.originX,
                    originY: e.originY
                });
                this._updateNodeAndLinkScale(seriesModel);
            }, this);
    },

    _updateNodeAndLinkScale: function (seriesModel) {
        var data = seriesModel.getData();

        var nodeScale = this._getNodeGlobalScale(seriesModel);
        var invScale = [nodeScale, nodeScale];

        data.eachItemGraphicEl(function (el, idx) {
            el.attr('scale', invScale);
        });
    },

    _getNodeGlobalScale: function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;
        if (coordSys.type !== 'view') {
            return 1;
        }

        var nodeScaleRatio = this._nodeScaleRatio;

        var groupScale = coordSys.scale;
        var groupZoom = (groupScale && groupScale[0]) || 1;
        // Scale node when zoom changes
        var roamZoom = coordSys.getZoom();
        var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;

        return nodeScale / groupZoom;
    },

    dispose: function () {
        this._controller && this._controller.dispose();
        this._controllerHost = {};
    },

    remove: function () {
        this._mainGroup.removeAll();
        this._data = null;
    }

});

function symbolNeedsDraw$1(data, dataIndex) {
    var layout = data.getItemLayout(dataIndex);

    return layout
        && !isNaN(layout.x) && !isNaN(layout.y)
        && data.getItemVisual(dataIndex, 'symbol') !== 'none';
}

function getTreeNodeStyle(node, itemModel, seriesScope) {
    seriesScope.itemModel = itemModel;
    seriesScope.itemStyle = itemModel.getModel('itemStyle').getItemStyle();
    seriesScope.hoverItemStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();
    seriesScope.lineStyle = itemModel.getModel('lineStyle').getLineStyle();
    seriesScope.labelModel = itemModel.getModel('label');
    seriesScope.hoverLabelModel = itemModel.getModel('emphasis.label');

    if (node.isExpand === false && node.children.length !== 0) {
        seriesScope.symbolInnerColor = seriesScope.itemStyle.fill;
    }
    else {
        seriesScope.symbolInnerColor = '#fff';
    }

    return seriesScope;
}

function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
    var isInit = !symbolEl;
    var node = data.tree.getNodeByDataIndex(dataIndex);
    var itemModel = node.getModel();
    var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);
    var virtualRoot = data.tree.root;

    var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
    var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
    var sourceLayout = source.getLayout();
    var sourceOldLayout = sourceSymbolEl
        ? {
            x: sourceSymbolEl.position[0],
            y: sourceSymbolEl.position[1],
            rawX: sourceSymbolEl.__radialOldRawX,
            rawY: sourceSymbolEl.__radialOldRawY
        }
        : sourceLayout;
    var targetLayout = node.getLayout();

    if (isInit) {
        symbolEl = new SymbolClz$1(data, dataIndex, seriesScope);
        symbolEl.attr('position', [sourceOldLayout.x, sourceOldLayout.y]);
    }
    else {
        symbolEl.updateData(data, dataIndex, seriesScope);
    }

    symbolEl.__radialOldRawX = symbolEl.__radialRawX;
    symbolEl.__radialOldRawY = symbolEl.__radialRawY;
    symbolEl.__radialRawX = targetLayout.rawX;
    symbolEl.__radialRawY = targetLayout.rawY;

    group.add(symbolEl);
    data.setItemGraphicEl(dataIndex, symbolEl);
    updateProps(symbolEl, {
        position: [targetLayout.x, targetLayout.y]
    }, seriesModel);

    var symbolPath = symbolEl.getSymbolPath();

    if (seriesScope.layout === 'radial') {
        var realRoot = virtualRoot.children[0];
        var rootLayout = realRoot.getLayout();
        var length = realRoot.children.length;
        var rad;
        var isLeft;

        if (targetLayout.x === rootLayout.x && node.isExpand === true) {
            var center = {};
            center.x = (realRoot.children[0].getLayout().x + realRoot.children[length - 1].getLayout().x) / 2;
            center.y = (realRoot.children[0].getLayout().y + realRoot.children[length - 1].getLayout().y) / 2;
            rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x);
            if (rad < 0) {
                rad = Math.PI * 2 + rad;
            }
            isLeft = center.x < rootLayout.x;
            if (isLeft) {
                rad = rad - Math.PI;
            }
        }
        else {
            rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x);
            if (rad < 0) {
                rad = Math.PI * 2 + rad;
            }
            if (node.children.length === 0 || (node.children.length !== 0 && node.isExpand === false)) {
                isLeft = targetLayout.x < rootLayout.x;
                if (isLeft) {
                    rad = rad - Math.PI;
                }
            }
            else {
                isLeft = targetLayout.x > rootLayout.x;
                if (!isLeft) {
                    rad = rad - Math.PI;
                }
            }
        }

        var textPosition = isLeft ? 'left' : 'right';
        var rotate = seriesScope.labelModel.get('rotate');
        var labelRotateRadian = rotate * (Math.PI / 180);

        symbolPath.setStyle({
            textPosition: seriesScope.labelModel.get('position') || textPosition,
            textRotation: rotate == null ? -rad : labelRotateRadian,
            textOrigin: 'center',
            verticalAlign: 'middle'
        });
    }

    if (node.parentNode && node.parentNode !== virtualRoot) {
        var edge = symbolEl.__edge;
        if (!edge) {
            edge = symbolEl.__edge = new BezierCurve({
                shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
                style: defaults({opacity: 0, strokeNoScale: true}, seriesScope.lineStyle)
            });
        }

        updateProps(edge, {
            shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
            style: {opacity: 1}
        }, seriesModel);

        group.add(edge);
    }
}

function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
    var node = data.tree.getNodeByDataIndex(dataIndex);
    var virtualRoot = data.tree.root;
    var itemModel = node.getModel();
    var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);

    var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
    var sourceLayout;
    while (sourceLayout = source.getLayout(), sourceLayout == null) {
        source = source.parentNode === virtualRoot ? source : source.parentNode || source;
    }

    updateProps(symbolEl, {
        position: [sourceLayout.x + 1, sourceLayout.y + 1]
    }, seriesModel, function () {
        group.remove(symbolEl);
        data.setItemGraphicEl(dataIndex, null);
    });

    symbolEl.fadeOut(null, {keepLabel: true});

    var edge = symbolEl.__edge;
    if (edge) {
        updateProps(edge, {
            shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
            style: {
                opacity: 0
            }
        }, seriesModel, function () {
            group.remove(edge);
        });
    }
}

function getEdgeShape(seriesScope, sourceLayout, targetLayout) {
    var cpx1;
    var cpy1;
    var cpx2;
    var cpy2;
    var orient = seriesScope.orient;
    var x1;
    var x2;
    var y1;
    var y2;

    if (seriesScope.layout === 'radial') {
        x1 = sourceLayout.rawX;
        y1 = sourceLayout.rawY;
        x2 = targetLayout.rawX;
        y2 = targetLayout.rawY;

        var radialCoor1 = radialCoordinate(x1, y1);
        var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * seriesScope.curvature);
        var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * seriesScope.curvature);
        var radialCoor4 = radialCoordinate(x2, y2);

        return {
            x1: radialCoor1.x,
            y1: radialCoor1.y,
            x2: radialCoor4.x,
            y2: radialCoor4.y,
            cpx1: radialCoor2.x,
            cpy1: radialCoor2.y,
            cpx2: radialCoor3.x,
            cpy2: radialCoor3.y
        };
    }
    else {
        x1 = sourceLayout.x;
        y1 = sourceLayout.y;
        x2 = targetLayout.x;
        y2 = targetLayout.y;

        if (orient === 'LR' || orient === 'RL') {
            cpx1 = x1 + (x2 - x1) * seriesScope.curvature;
            cpy1 = y1;
            cpx2 = x2 + (x1 - x2) * seriesScope.curvature;
            cpy2 = y2;
        }
        if (orient === 'TB' || orient === 'BT') {
            cpx1 = x1;
            cpy1 = y1 + (y2 - y1) * seriesScope.curvature;
            cpx2 = x2;
            cpy2 = y2 + (y1 - y2) * seriesScope.curvature;
        }
    }

    return {
        x1: x1,
        y1: y1,
        x2: x2,
        y2: y2,
        cpx1: cpx1,
        cpy1: cpy1,
        cpx2: cpx2,
        cpy2: cpy2
    };

}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerAction({
    type: 'treeExpandAndCollapse',
    event: 'treeExpandAndCollapse',
    update: 'update'
}, function (payload, ecModel) {
    ecModel.eachComponent({mainType: 'series', subType: 'tree', query: payload}, function (seriesModel) {
        var dataIndex = payload.dataIndex;
        var tree = seriesModel.getData().tree;
        var node = tree.getNodeByDataIndex(dataIndex);
        node.isExpand = !node.isExpand;
    });
});

registerAction({
    type: 'treeRoam',
    event: 'treeRoam',
    // Here we set 'none' instead of 'update', because roam action
    // just need to update the transform matrix without having to recalculate
    // the layout. So don't need to go through the whole update process, such
    // as 'dataPrcocess', 'coordSystemUpdate', 'layout' and so on.
    update: 'none'
}, function (payload, ecModel) {
    ecModel.eachComponent({mainType: 'series', subType: 'tree', query: payload}, function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;
        var res = updateCenterAndZoom(coordSys, payload);

        seriesModel.setCenter
            && seriesModel.setCenter(res.center);

        seriesModel.setZoom
            && seriesModel.setZoom(res.zoom);
    });
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * Traverse the tree from bottom to top and do something
 * @param  {module:echarts/data/Tree~TreeNode} root  The real root of the tree
 * @param  {Function} callback
 */
function eachAfter(root, callback, separation) {
    var nodes = [root];
    var next = [];
    var node;

    while (node = nodes.pop()) { // jshint ignore:line
        next.push(node);
        if (node.isExpand) {
            var children = node.children;
            if (children.length) {
                for (var i = 0; i < children.length; i++) {
                    nodes.push(children[i]);
                }
            }
        }
    }

    while (node = next.pop()) { // jshint ignore:line
        callback(node, separation);
    }
}

/**
 * Traverse the tree from top to bottom and do something
 * @param  {module:echarts/data/Tree~TreeNode} root  The real root of the tree
 * @param  {Function} callback
 */
function eachBefore(root, callback) {
    var nodes = [root];
    var node;
    while (node = nodes.pop()) { // jshint ignore:line
        callback(node);
        if (node.isExpand) {
            var children = node.children;
            if (children.length) {
                for (var i = children.length - 1; i >= 0; i--) {
                    nodes.push(children[i]);
                }
            }
        }
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var treeLayout = function (ecModel, api) {
    ecModel.eachSeriesByType('tree', function (seriesModel) {
        commonLayout(seriesModel, api);
    });
};

function commonLayout(seriesModel, api) {
    var layoutInfo = getViewRect(seriesModel, api);
    seriesModel.layoutInfo = layoutInfo;
    var layout = seriesModel.get('layout');
    var width = 0;
    var height = 0;
    var separation$$1 = null;

    if (layout === 'radial') {
        width = 2 * Math.PI;
        height = Math.min(layoutInfo.height, layoutInfo.width) / 2;
        separation$$1 = separation(function (node1, node2) {
            return (node1.parentNode === node2.parentNode ? 1 : 2) / node1.depth;
        });
    }
    else {
        width = layoutInfo.width;
        height = layoutInfo.height;
        separation$$1 = separation();
    }

    var virtualRoot = seriesModel.getData().tree.root;
    var realRoot = virtualRoot.children[0];

    if (realRoot) {
        init$2(virtualRoot);
        eachAfter(realRoot, firstWalk, separation$$1);
        virtualRoot.hierNode.modifier = -realRoot.hierNode.prelim;
        eachBefore(realRoot, secondWalk);

        var left = realRoot;
        var right = realRoot;
        var bottom = realRoot;
        eachBefore(realRoot, function (node) {
            var x = node.getLayout().x;
            if (x < left.getLayout().x) {
                left = node;
            }
            if (x > right.getLayout().x) {
                right = node;
            }
            if (node.depth > bottom.depth) {
                bottom = node;
            }
        });

        var delta = left === right ? 1 : separation$$1(left, right) / 2;
        var tx = delta - left.getLayout().x;
        var kx = 0;
        var ky = 0;
        var coorX = 0;
        var coorY = 0;
        if (layout === 'radial') {
            kx = width / (right.getLayout().x + delta + tx);
            // here we use (node.depth - 1), bucause the real root's depth is 1
            ky = height / ((bottom.depth - 1) || 1);
            eachBefore(realRoot, function (node) {
                coorX = (node.getLayout().x + tx) * kx;
                coorY = (node.depth - 1) * ky;
                var finalCoor = radialCoordinate(coorX, coorY);
                node.setLayout({x: finalCoor.x, y: finalCoor.y, rawX: coorX, rawY: coorY}, true);
            });
        }
        else {
            var orient = seriesModel.getOrient();
            if (orient === 'RL' || orient === 'LR') {
                ky = height / (right.getLayout().x + delta + tx);
                kx = width / ((bottom.depth - 1) || 1);
                eachBefore(realRoot, function (node) {
                    coorY = (node.getLayout().x + tx) * ky;
                    coorX = orient === 'LR'
                        ? (node.depth - 1) * kx
                        : width - (node.depth - 1) * kx;
                    node.setLayout({x: coorX, y: coorY}, true);
                });
            }
            else if (orient === 'TB' || orient === 'BT') {
                kx = width / (right.getLayout().x + delta + tx);
                ky = height / ((bottom.depth - 1) || 1);
                eachBefore(realRoot, function (node) {
                    coorX = (node.getLayout().x + tx) * kx;
                    coorY = orient === 'TB'
                        ? (node.depth - 1) * ky
                        : height - (node.depth - 1) * ky;
                    node.setLayout({x: coorX, y: coorY}, true);
                });
            }
        }
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(visualSymbol('tree', 'circle'));
registerLayout(treeLayout);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function retrieveTargetInfo(payload, validPayloadTypes, seriesModel) {
    if (payload && indexOf(validPayloadTypes, payload.type) >= 0) {
        var root = seriesModel.getData().tree.root;
        var targetNode = payload.targetNode;

        if (typeof targetNode === 'string') {
            targetNode = root.getNodeById(targetNode);
        }

        if (targetNode && root.contains(targetNode)) {
            return {node: targetNode};
        }

        var targetNodeId = payload.targetNodeId;
        if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) {
            return {node: targetNode};
        }
    }
}

// Not includes the given node at the last item.
function getPathToRoot(node) {
    var path = [];
    while (node) {
        node = node.parentNode;
        node && path.push(node);
    }
    return path.reverse();
}

function aboveViewRoot(viewRoot, node) {
    var viewPath = getPathToRoot(viewRoot);
    return indexOf(viewPath, node) >= 0;
}

// From root to the input node (the input node will be included).
function wrapTreePathInfo(node, seriesModel) {
    var treePathInfo = [];

    while (node) {
        var nodeDataIndex = node.dataIndex;
        treePathInfo.push({
            name: node.name,
            dataIndex: nodeDataIndex,
            value: seriesModel.getRawValue(nodeDataIndex)
        });
        node = node.parentNode;
    }

    treePathInfo.reverse();

    return treePathInfo;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.treemap',

    layoutMode: 'box',

    dependencies: ['grid', 'polar'],

    preventUsingHoverLayer: true,

    /**
     * @type {module:echarts/data/Tree~Node}
     */
    _viewRoot: null,

    defaultOption: {
        // Disable progressive rendering
        progressive: 0,
        // center: ['50%', '50%'],          // not supported in ec3.
        // size: ['80%', '80%'],            // deprecated, compatible with ec2.
        left: 'center',
        top: 'middle',
        right: null,
        bottom: null,
        width: '80%',
        height: '80%',
        sort: true,                         // Can be null or false or true
                                            // (order by desc default, asc not supported yet (strange effect))
        clipWindow: 'origin',               // Size of clipped window when zooming. 'origin' or 'fullscreen'
        squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio
        leafDepth: null,                    // Nodes on depth from root are regarded as leaves.
                                            // Count from zero (zero represents only view root).
        drillDownIcon: '▶',                 // Use html character temporarily because it is complicated
                                            // to align specialized icon. ▷▶❒❐▼✚

        zoomToNodeRatio: 0.32 * 0.32,       // Be effective when using zoomToNode. Specify the proportion of the
                                            // target node area in the view area.
        roam: true,                         // true, false, 'scale' or 'zoom', 'move'.
        nodeClick: 'zoomToNode',            // Leaf node click behaviour: 'zoomToNode', 'link', false.
                                            // If leafDepth is set and clicking a node which has children but
                                            // be on left depth, the behaviour would be changing root. Otherwise
                                            // use behavious defined above.
        animation: true,
        animationDurationUpdate: 900,
        animationEasing: 'quinticInOut',
        breadcrumb: {
            show: true,
            height: 22,
            left: 'center',
            top: 'bottom',
            // right
            // bottom
            emptyItemWidth: 25,             // Width of empty node.
            itemStyle: {
                color: 'rgba(0,0,0,0.7)', //'#5793f3',
                borderColor: 'rgba(255,255,255,0.7)',
                borderWidth: 1,
                shadowColor: 'rgba(150,150,150,1)',
                shadowBlur: 3,
                shadowOffsetX: 0,
                shadowOffsetY: 0,
                textStyle: {
                    color: '#fff'
                }
            },
            emphasis: {
                textStyle: {}
            }
        },
        label: {
            show: true,
            // Do not use textDistance, for ellipsis rect just the same as treemap node rect.
            distance: 0,
            padding: 5,
            position: 'inside', // Can be [5, '5%'] or position stirng like 'insideTopLeft', ...
            // formatter: null,
            color: '#fff',
            ellipsis: true
            // align
            // verticalAlign
        },
        upperLabel: {                   // Label when node is parent.
            show: false,
            position: [0, '50%'],
            height: 20,
            // formatter: null,
            color: '#fff',
            ellipsis: true,
            // align: null,
            verticalAlign: 'middle'
        },
        itemStyle: {
            color: null,            // Can be 'none' if not necessary.
            colorAlpha: null,       // Can be 'none' if not necessary.
            colorSaturation: null,  // Can be 'none' if not necessary.
            borderWidth: 0,
            gapWidth: 0,
            borderColor: '#fff',
            borderColorSaturation: null // If specified, borderColor will be ineffective, and the
                                        // border color is evaluated by color of current node and
                                        // borderColorSaturation.
        },
        emphasis: {
            upperLabel: {
                show: true,
                position: [0, '50%'],
                color: '#fff',
                ellipsis: true,
                verticalAlign: 'middle'
            }
        },

        visualDimension: 0,                 // Can be 0, 1, 2, 3.
        visualMin: null,
        visualMax: null,

        color: [],                  // + treemapSeries.color should not be modified. Please only modified
                                    // level[n].color (if necessary).
                                    // + Specify color list of each level. level[0].color would be global
                                    // color list if not specified. (see method `setDefault`).
                                    // + But set as a empty array to forbid fetch color from global palette
                                    // when using nodeModel.get('color'), otherwise nodes on deep level
                                    // will always has color palette set and are not able to inherit color
                                    // from parent node.
                                    // + TreemapSeries.color can not be set as 'none', otherwise effect
                                    // legend color fetching (see seriesColor.js).
        colorAlpha: null,           // Array. Specify color alpha range of each level, like [0.2, 0.8]
        colorSaturation: null,      // Array. Specify color saturation of each level, like [0.2, 0.5]
        colorMappingBy: 'index',    // 'value' or 'index' or 'id'.
        visibleMin: 10,             // If area less than this threshold (unit: pixel^2), node will not
                                    // be rendered. Only works when sort is 'asc' or 'desc'.
        childrenVisibleMin: null,   // If area of a node less than this threshold (unit: pixel^2),
                                    // grandchildren will not show.
                                    // Why grandchildren? If not grandchildren but children,
                                    // some siblings show children and some not,
                                    // the appearance may be mess and not consistent,
        levels: []                  // Each item: {
                                    //     visibleMin, itemStyle, visualDimension, label
                                    // }
        // data: {
        //      value: [],
        //      children: [],
        //      link: 'http://xxx.xxx.xxx',
        //      target: 'blank' or 'self'
        // }
    },

    /**
     * @override
     */
    getInitialData: function (option, ecModel) {
        // Create a virtual root.
        var root = {name: option.name, children: option.data};

        completeTreeValue(root);

        var levels = option.levels || [];

        levels = option.levels = setDefault(levels, ecModel);

        var treeOption = {};

        treeOption.levels = levels;

        // Make sure always a new tree is created when setOption,
        // in TreemapView, we check whether oldTree === newTree
        // to choose mappings approach among old shapes and new shapes.
        return Tree.createTree(root, this, treeOption).data;
    },

    optionUpdated: function () {
        this.resetViewRoot();
    },

    /**
     * @override
     * @param {number} dataIndex
     * @param {boolean} [mutipleSeries=false]
     */
    formatTooltip: function (dataIndex) {
        var data = this.getData();
        var value = this.getRawValue(dataIndex);
        var formattedValue = isArray(value)
            ? addCommas(value[0]) : addCommas(value);
        var name = data.getName(dataIndex);

        return encodeHTML(name + ': ' + formattedValue);
    },

    /**
     * Add tree path to tooltip param
     *
     * @override
     * @param {number} dataIndex
     * @return {Object}
     */
    getDataParams: function (dataIndex) {
        var params = SeriesModel.prototype.getDataParams.apply(this, arguments);

        var node = this.getData().tree.getNodeByDataIndex(dataIndex);
        params.treePathInfo = wrapTreePathInfo(node, this);

        return params;
    },

    /**
     * @public
     * @param {Object} layoutInfo {
     *                                x: containerGroup x
     *                                y: containerGroup y
     *                                width: containerGroup width
     *                                height: containerGroup height
     *                            }
     */
    setLayoutInfo: function (layoutInfo) {
        /**
         * @readOnly
         * @type {Object}
         */
        this.layoutInfo = this.layoutInfo || {};
        extend(this.layoutInfo, layoutInfo);
    },

    /**
     * @param  {string} id
     * @return {number} index
     */
    mapIdToIndex: function (id) {
        // A feature is implemented:
        // index is monotone increasing with the sequence of
        // input id at the first time.
        // This feature can make sure that each data item and its
        // mapped color have the same index between data list and
        // color list at the beginning, which is useful for user
        // to adjust data-color mapping.

        /**
         * @private
         * @type {Object}
         */
        var idIndexMap = this._idIndexMap;

        if (!idIndexMap) {
            idIndexMap = this._idIndexMap = createHashMap();
            /**
             * @private
             * @type {number}
             */
            this._idIndexMapCount = 0;
        }

        var index = idIndexMap.get(id);
        if (index == null) {
            idIndexMap.set(id, index = this._idIndexMapCount++);
        }

        return index;
    },

    getViewRoot: function () {
        return this._viewRoot;
    },

    /**
     * @param {module:echarts/data/Tree~Node} [viewRoot]
     */
    resetViewRoot: function (viewRoot) {
        viewRoot
            ? (this._viewRoot = viewRoot)
            : (viewRoot = this._viewRoot);

        var root = this.getRawData().tree.root;

        if (!viewRoot
            || (viewRoot !== root && !root.contains(viewRoot))
        ) {
            this._viewRoot = root;
        }
    }
});

/**
 * @param {Object} dataNode
 */
function completeTreeValue(dataNode) {
    // Postorder travel tree.
    // If value of none-leaf node is not set,
    // calculate it by suming up the value of all children.
    var sum = 0;

    each$1(dataNode.children, function (child) {

        completeTreeValue(child);

        var childValue = child.value;
        isArray(childValue) && (childValue = childValue[0]);

        sum += childValue;
    });

    var thisValue = dataNode.value;
    if (isArray(thisValue)) {
        thisValue = thisValue[0];
    }

    if (thisValue == null || isNaN(thisValue)) {
        thisValue = sum;
    }
    // Value should not less than 0.
    if (thisValue < 0) {
        thisValue = 0;
    }

    isArray(dataNode.value)
        ? (dataNode.value[0] = thisValue)
        : (dataNode.value = thisValue);
}

/**
 * set default to level configuration
 */
function setDefault(levels, ecModel) {
    var globalColorList = ecModel.get('color');

    if (!globalColorList) {
        return;
    }

    levels = levels || [];
    var hasColorDefine;
    each$1(levels, function (levelDefine) {
        var model = new Model(levelDefine);
        var modelColor = model.get('color');

        if (model.get('itemStyle.color')
            || (modelColor && modelColor !== 'none')
        ) {
            hasColorDefine = true;
        }
    });

    if (!hasColorDefine) {
        var level0 = levels[0] || (levels[0] = {});
        level0.color = globalColorList.slice();
    }

    return levels;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var TEXT_PADDING = 8;
var ITEM_GAP = 8;
var ARRAY_LENGTH = 5;

function Breadcrumb(containerGroup) {
    /**
     * @private
     * @type {module:zrender/container/Group}
     */
    this.group = new Group();

    containerGroup.add(this.group);
}

Breadcrumb.prototype = {

    constructor: Breadcrumb,

    render: function (seriesModel, api, targetNode, onSelect) {
        var model = seriesModel.getModel('breadcrumb');
        var thisGroup = this.group;

        thisGroup.removeAll();

        if (!model.get('show') || !targetNode) {
            return;
        }

        var normalStyleModel = model.getModel('itemStyle');
        // var emphasisStyleModel = model.getModel('emphasis.itemStyle');
        var textStyleModel = normalStyleModel.getModel('textStyle');

        var layoutParam = {
            pos: {
                left: model.get('left'),
                right: model.get('right'),
                top: model.get('top'),
                bottom: model.get('bottom')
            },
            box: {
                width: api.getWidth(),
                height: api.getHeight()
            },
            emptyItemWidth: model.get('emptyItemWidth'),
            totalWidth: 0,
            renderList: []
        };

        this._prepare(targetNode, layoutParam, textStyleModel);
        this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect);

        positionElement(thisGroup, layoutParam.pos, layoutParam.box);
    },

    /**
     * Prepare render list and total width
     * @private
     */
    _prepare: function (targetNode, layoutParam, textStyleModel) {
        for (var node = targetNode; node; node = node.parentNode) {
            var text = node.getModel().get('name');
            var textRect = textStyleModel.getTextRect(text);
            var itemWidth = Math.max(
                textRect.width + TEXT_PADDING * 2,
                layoutParam.emptyItemWidth
            );
            layoutParam.totalWidth += itemWidth + ITEM_GAP;
            layoutParam.renderList.push({node: node, text: text, width: itemWidth});
        }
    },

    /**
     * @private
     */
    _renderContent: function (
        seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect
    ) {
        // Start rendering.
        var lastX = 0;
        var emptyItemWidth = layoutParam.emptyItemWidth;
        var height = seriesModel.get('breadcrumb.height');
        var availableSize = getAvailableSize(layoutParam.pos, layoutParam.box);
        var totalWidth = layoutParam.totalWidth;
        var renderList = layoutParam.renderList;

        for (var i = renderList.length - 1; i >= 0; i--) {
            var item = renderList[i];
            var itemNode = item.node;
            var itemWidth = item.width;
            var text = item.text;

            // Hdie text and shorten width if necessary.
            if (totalWidth > availableSize.width) {
                totalWidth -= itemWidth - emptyItemWidth;
                itemWidth = emptyItemWidth;
                text = null;
            }

            var el = new Polygon({
                shape: {
                    points: makeItemPoints(
                        lastX, 0, itemWidth, height,
                        i === renderList.length - 1, i === 0
                    )
                },
                style: defaults(
                    normalStyleModel.getItemStyle(),
                    {
                        lineJoin: 'bevel',
                        text: text,
                        textFill: textStyleModel.getTextColor(),
                        textFont: textStyleModel.getFont()
                    }
                ),
                z: 10,
                onclick: curry(onSelect, itemNode)
            });
            this.group.add(el);

            packEventData(el, seriesModel, itemNode);

            lastX += itemWidth + ITEM_GAP;
        }
    },

    /**
     * @override
     */
    remove: function () {
        this.group.removeAll();
    }
};

function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) {
    var points = [
        [head ? x : x - ARRAY_LENGTH, y],
        [x + itemWidth, y],
        [x + itemWidth, y + itemHeight],
        [head ? x : x - ARRAY_LENGTH, y + itemHeight]
    ];
    !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]);
    !head && points.push([x, y + itemHeight / 2]);
    return points;
}

// Package custom mouse event.
function packEventData(el, seriesModel, itemNode) {
    el.eventData = {
        componentType: 'series',
        componentSubType: 'treemap',
        componentIndex: seriesModel.componentIndex,
        seriesIndex: seriesModel.componentIndex,
        seriesName: seriesModel.name,
        seriesType: 'treemap',
        selfType: 'breadcrumb', // Distinguish with click event on treemap node.
        nodeData: {
            dataIndex: itemNode && itemNode.dataIndex,
            name: itemNode && itemNode.name
        },
        treePathInfo: itemNode && wrapTreePathInfo(itemNode, seriesModel)
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {number} [time=500] Time in ms
 * @param {string} [easing='linear']
 * @param {number} [delay=0]
 * @param {Function} [callback]
 *
 * @example
 *  // Animate position
 *  animation
 *      .createWrap()
 *      .add(el1, {position: [10, 10]})
 *      .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400)
 *      .done(function () { // done })
 *      .start('cubicOut');
 */
function createWrap() {

    var storage = [];
    var elExistsMap = {};
    var doneCallback;

    return {

        /**
         * Caution: a el can only be added once, otherwise 'done'
         * might not be called. This method checks this (by el.id),
         * suppresses adding and returns false when existing el found.
         *
         * @param {modele:zrender/Element} el
         * @param {Object} target
         * @param {number} [time=500]
         * @param {number} [delay=0]
         * @param {string} [easing='linear']
         * @return {boolean} Whether adding succeeded.
         *
         * @example
         *     add(el, target, time, delay, easing);
         *     add(el, target, time, easing);
         *     add(el, target, time);
         *     add(el, target);
         */
        add: function (el, target, time, delay, easing) {
            if (isString(delay)) {
                easing = delay;
                delay = 0;
            }

            if (elExistsMap[el.id]) {
                return false;
            }
            elExistsMap[el.id] = 1;

            storage.push(
                {el: el, target: target, time: time, delay: delay, easing: easing}
            );

            return true;
        },

        /**
         * Only execute when animation finished. Will not execute when any
         * of 'stop' or 'stopAnimation' called.
         *
         * @param {Function} callback
         */
        done: function (callback) {
            doneCallback = callback;
            return this;
        },

        /**
         * Will stop exist animation firstly.
         */
        start: function () {
            var count = storage.length;

            for (var i = 0, len = storage.length; i < len; i++) {
                var item = storage[i];
                item.el.animateTo(item.target, item.time, item.delay, item.easing, done);
            }

            return this;

            function done() {
                count--;
                if (!count) {
                    storage.length = 0;
                    elExistsMap = {};
                    doneCallback && doneCallback();
                }
            }
        }
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var bind$1 = bind;
var Group$2 = Group;
var Rect$1 = Rect;
var each$8 = each$1;

var DRAG_THRESHOLD = 3;
var PATH_LABEL_NOAMAL = ['label'];
var PATH_LABEL_EMPHASIS = ['emphasis', 'label'];
var PATH_UPPERLABEL_NORMAL = ['upperLabel'];
var PATH_UPPERLABEL_EMPHASIS = ['emphasis', 'upperLabel'];
var Z_BASE = 10; // Should bigger than every z.
var Z_BG = 1;
var Z_CONTENT = 2;

var getItemStyleEmphasis = makeStyleMapper([
    ['fill', 'color'],
    // `borderColor` and `borderWidth` has been occupied,
    // so use `stroke` to indicate the stroke of the rect.
    ['stroke', 'strokeColor'],
    ['lineWidth', 'strokeWidth'],
    ['shadowBlur'],
    ['shadowOffsetX'],
    ['shadowOffsetY'],
    ['shadowColor']
]);
var getItemStyleNormal = function (model) {
    // Normal style props should include emphasis style props.
    var itemStyle = getItemStyleEmphasis(model);
    // Clear styles set by emphasis.
    itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null;
    return itemStyle;
};

extendChartView({

    type: 'treemap',

    /**
     * @override
     */
    init: function (o, api) {

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this._containerGroup;

        /**
         * @private
         * @type {Object.<string, Array.<module:zrender/container/Group>>}
         */
        this._storage = createStorage();

        /**
         * @private
         * @type {module:echarts/data/Tree}
         */
        this._oldTree;

        /**
         * @private
         * @type {module:echarts/chart/treemap/Breadcrumb}
         */
        this._breadcrumb;

        /**
         * @private
         * @type {module:echarts/component/helper/RoamController}
         */
        this._controller;

        /**
         * 'ready', 'animating'
         * @private
         */
        this._state = 'ready';
    },

    /**
     * @override
     */
    render: function (seriesModel, ecModel, api, payload) {

        var models = ecModel.findComponents({
            mainType: 'series', subType: 'treemap', query: payload
        });
        if (indexOf(models, seriesModel) < 0) {
            return;
        }

        this.seriesModel = seriesModel;
        this.api = api;
        this.ecModel = ecModel;

        var types = ['treemapZoomToNode', 'treemapRootToNode'];
        var targetInfo = retrieveTargetInfo(payload, types, seriesModel);
        var payloadType = payload && payload.type;
        var layoutInfo = seriesModel.layoutInfo;
        var isInit = !this._oldTree;
        var thisStorage = this._storage;

        // Mark new root when action is treemapRootToNode.
        var reRoot = (payloadType === 'treemapRootToNode' && targetInfo && thisStorage)
            ? {
                rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()],
                direction: payload.direction
            }
            : null;

        var containerGroup = this._giveContainerGroup(layoutInfo);

        var renderResult = this._doRender(containerGroup, seriesModel, reRoot);
        (
            !isInit && (
                !payloadType
                || payloadType === 'treemapZoomToNode'
                || payloadType === 'treemapRootToNode'
            )
        )
            ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot)
            : renderResult.renderFinally();

        this._resetController(api);

        this._renderBreadcrumb(seriesModel, api, targetInfo);
    },

    /**
     * @private
     */
    _giveContainerGroup: function (layoutInfo) {
        var containerGroup = this._containerGroup;
        if (!containerGroup) {
            // FIXME
            // 加一层containerGroup是为了clip，但是现在clip功能并没有实现。
            containerGroup = this._containerGroup = new Group$2();
            this._initEvents(containerGroup);
            this.group.add(containerGroup);
        }
        containerGroup.attr('position', [layoutInfo.x, layoutInfo.y]);

        return containerGroup;
    },

    /**
     * @private
     */
    _doRender: function (containerGroup, seriesModel, reRoot) {
        var thisTree = seriesModel.getData().tree;
        var oldTree = this._oldTree;

        // Clear last shape records.
        var lastsForAnimation = createStorage();
        var thisStorage = createStorage();
        var oldStorage = this._storage;
        var willInvisibleEls = [];
        var doRenderNode = curry(
            renderNode, seriesModel,
            thisStorage, oldStorage, reRoot,
            lastsForAnimation, willInvisibleEls
        );

        // Notice: when thisTree and oldTree are the same tree (see list.cloneShallow),
        // the oldTree is actually losted, so we can not find all of the old graphic
        // elements from tree. So we use this stragegy: make element storage, move
        // from old storage to new storage, clear old storage.

        dualTravel(
            thisTree.root ? [thisTree.root] : [],
            (oldTree && oldTree.root) ? [oldTree.root] : [],
            containerGroup,
            thisTree === oldTree || !oldTree,
            0
        );

        // Process all removing.
        var willDeleteEls = clearStorage(oldStorage);

        this._oldTree = thisTree;
        this._storage = thisStorage;

        return {
            lastsForAnimation: lastsForAnimation,
            willDeleteEls: willDeleteEls,
            renderFinally: renderFinally
        };

        function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) {
            // When 'render' is triggered by action,
            // 'this' and 'old' may be the same tree,
            // we use rawIndex in that case.
            if (sameTree) {
                oldViewChildren = thisViewChildren;
                each$8(thisViewChildren, function (child, index) {
                    !child.isRemoved() && processNode(index, index);
                });
            }
            // Diff hierarchically (diff only in each subtree, but not whole).
            // because, consistency of view is important.
            else {
                (new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey))
                    .add(processNode)
                    .update(processNode)
                    .remove(curry(processNode, null))
                    .execute();
            }

            function getKey(node) {
                // Identify by name or raw index.
                return node.getId();
            }

            function processNode(newIndex, oldIndex) {
                var thisNode = newIndex != null ? thisViewChildren[newIndex] : null;
                var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null;

                var group = doRenderNode(thisNode, oldNode, parentGroup, depth);

                group && dualTravel(
                    thisNode && thisNode.viewChildren || [],
                    oldNode && oldNode.viewChildren || [],
                    group,
                    sameTree,
                    depth + 1
                );
            }
        }

        function clearStorage(storage) {
            var willDeleteEls = createStorage();
            storage && each$8(storage, function (store, storageName) {
                var delEls = willDeleteEls[storageName];
                each$8(store, function (el) {
                    el && (delEls.push(el), el.__tmWillDelete = 1);
                });
            });
            return willDeleteEls;
        }

        function renderFinally() {
            each$8(willDeleteEls, function (els) {
                each$8(els, function (el) {
                    el.parent && el.parent.remove(el);
                });
            });
            each$8(willInvisibleEls, function (el) {
                el.invisible = true;
                // Setting invisible is for optimizing, so no need to set dirty,
                // just mark as invisible.
                el.dirty();
            });
        }
    },

    /**
     * @private
     */
    _doAnimation: function (containerGroup, renderResult, seriesModel, reRoot) {
        if (!seriesModel.get('animation')) {
            return;
        }

        var duration = seriesModel.get('animationDurationUpdate');
        var easing = seriesModel.get('animationEasing');
        var animationWrap = createWrap();

        // Make delete animations.
        each$8(renderResult.willDeleteEls, function (store, storageName) {
            each$8(store, function (el, rawIndex) {
                if (el.invisible) {
                    return;
                }

                var parent = el.parent; // Always has parent, and parent is nodeGroup.
                var target;

                if (reRoot && reRoot.direction === 'drillDown') {
                    target = parent === reRoot.rootNodeGroup
                        // This is the content element of view root.
                        // Only `content` will enter this branch, because
                        // `background` and `nodeGroup` will not be deleted.
                        ? {
                            shape: {
                                x: 0,
                                y: 0,
                                width: parent.__tmNodeWidth,
                                height: parent.__tmNodeHeight
                            },
                            style: {
                                opacity: 0
                            }
                        }
                        // Others.
                        : {style: {opacity: 0}};
                }
                else {
                    var targetX = 0;
                    var targetY = 0;

                    if (!parent.__tmWillDelete) {
                        // Let node animate to right-bottom corner, cooperating with fadeout,
                        // which is appropriate for user understanding.
                        // Divided by 2 for reRoot rolling up effect.
                        targetX = parent.__tmNodeWidth / 2;
                        targetY = parent.__tmNodeHeight / 2;
                    }

                    target = storageName === 'nodeGroup'
                        ? {position: [targetX, targetY], style: {opacity: 0}}
                        : {
                            shape: {x: targetX, y: targetY, width: 0, height: 0},
                            style: {opacity: 0}
                        };
                }

                target && animationWrap.add(el, target, duration, easing);
            });
        });

        // Make other animations
        each$8(this._storage, function (store, storageName) {
            each$8(store, function (el, rawIndex) {
                var last = renderResult.lastsForAnimation[storageName][rawIndex];
                var target = {};

                if (!last) {
                    return;
                }

                if (storageName === 'nodeGroup') {
                    if (last.old) {
                        target.position = el.position.slice();
                        el.attr('position', last.old);
                    }
                }
                else {
                    if (last.old) {
                        target.shape = extend({}, el.shape);
                        el.setShape(last.old);
                    }

                    if (last.fadein) {
                        el.setStyle('opacity', 0);
                        target.style = {opacity: 1};
                    }
                    // When animation is stopped for succedent animation starting,
                    // el.style.opacity might not be 1
                    else if (el.style.opacity !== 1) {
                        target.style = {opacity: 1};
                    }
                }

                animationWrap.add(el, target, duration, easing);
            });
        }, this);

        this._state = 'animating';

        animationWrap
            .done(bind$1(function () {
                this._state = 'ready';
                renderResult.renderFinally();
            }, this))
            .start();
    },

    /**
     * @private
     */
    _resetController: function (api) {
        var controller = this._controller;

        // Init controller.
        if (!controller) {
            controller = this._controller = new RoamController(api.getZr());
            controller.enable(this.seriesModel.get('roam'));
            controller.on('pan', bind$1(this._onPan, this));
            controller.on('zoom', bind$1(this._onZoom, this));
        }

        var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight());
        controller.setPointerChecker(function (e, x, y) {
            return rect.contain(x, y);
        });
    },

    /**
     * @private
     */
    _clearController: function () {
        var controller = this._controller;
        if (controller) {
            controller.dispose();
            controller = null;
        }
    },

    /**
     * @private
     */
    _onPan: function (e) {
        if (this._state !== 'animating'
            && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)
        ) {
            // These param must not be cached.
            var root = this.seriesModel.getData().tree.root;

            if (!root) {
                return;
            }

            var rootLayout = root.getLayout();

            if (!rootLayout) {
                return;
            }

            this.api.dispatchAction({
                type: 'treemapMove',
                from: this.uid,
                seriesId: this.seriesModel.id,
                rootRect: {
                    x: rootLayout.x + e.dx, y: rootLayout.y + e.dy,
                    width: rootLayout.width, height: rootLayout.height
                }
            });
        }
    },

    /**
     * @private
     */
    _onZoom: function (e) {
        var mouseX = e.originX;
        var mouseY = e.originY;

        if (this._state !== 'animating') {
            // These param must not be cached.
            var root = this.seriesModel.getData().tree.root;

            if (!root) {
                return;
            }

            var rootLayout = root.getLayout();

            if (!rootLayout) {
                return;
            }

            var rect = new BoundingRect(
                rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height
            );
            var layoutInfo = this.seriesModel.layoutInfo;

            // Transform mouse coord from global to containerGroup.
            mouseX -= layoutInfo.x;
            mouseY -= layoutInfo.y;

            // Scale root bounding rect.
            var m = create$1();
            translate(m, m, [-mouseX, -mouseY]);
            scale$1(m, m, [e.scale, e.scale]);
            translate(m, m, [mouseX, mouseY]);

            rect.applyTransform(m);

            this.api.dispatchAction({
                type: 'treemapRender',
                from: this.uid,
                seriesId: this.seriesModel.id,
                rootRect: {
                    x: rect.x, y: rect.y,
                    width: rect.width, height: rect.height
                }
            });
        }
    },

    /**
     * @private
     */
    _initEvents: function (containerGroup) {
        containerGroup.on('click', function (e) {
            if (this._state !== 'ready') {
                return;
            }

            var nodeClick = this.seriesModel.get('nodeClick', true);

            if (!nodeClick) {
                return;
            }

            var targetInfo = this.findTarget(e.offsetX, e.offsetY);

            if (!targetInfo) {
                return;
            }

            var node = targetInfo.node;
            if (node.getLayout().isLeafRoot) {
                this._rootToNode(targetInfo);
            }
            else {
                if (nodeClick === 'zoomToNode') {
                    this._zoomToNode(targetInfo);
                }
                else if (nodeClick === 'link') {
                    var itemModel = node.hostTree.data.getItemModel(node.dataIndex);
                    var link = itemModel.get('link', true);
                    var linkTarget = itemModel.get('target', true) || 'blank';
                    link && window.open(link, linkTarget);
                }
            }

        }, this);
    },

    /**
     * @private
     */
    _renderBreadcrumb: function (seriesModel, api, targetInfo) {
        if (!targetInfo) {
            targetInfo = seriesModel.get('leafDepth', true) != null
                ? {node: seriesModel.getViewRoot()}
                // FIXME
                // better way?
                // Find breadcrumb tail on center of containerGroup.
                : this.findTarget(api.getWidth() / 2, api.getHeight() / 2);

            if (!targetInfo) {
                targetInfo = {node: seriesModel.getData().tree.root};
            }
        }

        (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group)))
            .render(seriesModel, api, targetInfo.node, bind$1(onSelect, this));

        function onSelect(node) {
            if (this._state !== 'animating') {
                aboveViewRoot(seriesModel.getViewRoot(), node)
                    ? this._rootToNode({node: node})
                    : this._zoomToNode({node: node});
            }
        }
    },

    /**
     * @override
     */
    remove: function () {
        this._clearController();
        this._containerGroup && this._containerGroup.removeAll();
        this._storage = createStorage();
        this._state = 'ready';
        this._breadcrumb && this._breadcrumb.remove();
    },

    dispose: function () {
        this._clearController();
    },

    /**
     * @private
     */
    _zoomToNode: function (targetInfo) {
        this.api.dispatchAction({
            type: 'treemapZoomToNode',
            from: this.uid,
            seriesId: this.seriesModel.id,
            targetNode: targetInfo.node
        });
    },

    /**
     * @private
     */
    _rootToNode: function (targetInfo) {
        this.api.dispatchAction({
            type: 'treemapRootToNode',
            from: this.uid,
            seriesId: this.seriesModel.id,
            targetNode: targetInfo.node
        });
    },

    /**
     * @public
     * @param {number} x Global coord x.
     * @param {number} y Global coord y.
     * @return {Object} info If not found, return undefined;
     * @return {number} info.node Target node.
     * @return {number} info.offsetX x refer to target node.
     * @return {number} info.offsetY y refer to target node.
     */
    findTarget: function (x, y) {
        var targetInfo;
        var viewRoot = this.seriesModel.getViewRoot();

        viewRoot.eachNode({attr: 'viewChildren', order: 'preorder'}, function (node) {
            var bgEl = this._storage.background[node.getRawIndex()];
            // If invisible, there might be no element.
            if (bgEl) {
                var point = bgEl.transformCoordToLocal(x, y);
                var shape = bgEl.shape;

                // For performance consideration, dont use 'getBoundingRect'.
                if (shape.x <= point[0]
                    && point[0] <= shape.x + shape.width
                    && shape.y <= point[1]
                    && point[1] <= shape.y + shape.height
                ) {
                    targetInfo = {node: node, offsetX: point[0], offsetY: point[1]};
                }
                else {
                    return false; // Suppress visit subtree.
                }
            }
        }, this);

        return targetInfo;
    }

});

/**
 * @inner
 */
function createStorage() {
    return {nodeGroup: [], background: [], content: []};
}

/**
 * @inner
 * @return Return undefined means do not travel further.
 */
function renderNode(
    seriesModel, thisStorage, oldStorage, reRoot,
    lastsForAnimation, willInvisibleEls,
    thisNode, oldNode, parentGroup, depth
) {
    // Whether under viewRoot.
    if (!thisNode) {
        // Deleting nodes will be performed finally. This method just find
        // element from old storage, or create new element, set them to new
        // storage, and set styles.
        return;
    }

    // -------------------------------------------------------------------
    // Start of closure variables available in "Procedures in renderNode".

    var thisLayout = thisNode.getLayout();

    if (!thisLayout || !thisLayout.isInView) {
        return;
    }

    var thisWidth = thisLayout.width;
    var thisHeight = thisLayout.height;
    var borderWidth = thisLayout.borderWidth;
    var thisInvisible = thisLayout.invisible;

    var thisRawIndex = thisNode.getRawIndex();
    var oldRawIndex = oldNode && oldNode.getRawIndex();

    var thisViewChildren = thisNode.viewChildren;
    var upperHeight = thisLayout.upperHeight;
    var isParent = thisViewChildren && thisViewChildren.length;
    var itemStyleNormalModel = thisNode.getModel('itemStyle');
    var itemStyleEmphasisModel = thisNode.getModel('emphasis.itemStyle');

    // End of closure ariables available in "Procedures in renderNode".
    // -----------------------------------------------------------------

    // Node group
    var group = giveGraphic('nodeGroup', Group$2);

    if (!group) {
        return;
    }

    parentGroup.add(group);
    // x,y are not set when el is above view root.
    group.attr('position', [thisLayout.x || 0, thisLayout.y || 0]);
    group.__tmNodeWidth = thisWidth;
    group.__tmNodeHeight = thisHeight;

    if (thisLayout.isAboveViewRoot) {
        return group;
    }

    // Background
    var bg = giveGraphic('background', Rect$1, depth, Z_BG);
    bg && renderBackground(group, bg, isParent && thisLayout.upperHeight);

    // No children, render content.
    if (!isParent) {
        var content = giveGraphic('content', Rect$1, depth, Z_CONTENT);
        content && renderContent(group, content);
    }

    return group;

    // ----------------------------
    // | Procedures in renderNode |
    // ----------------------------

    function renderBackground(group, bg, useUpperLabel) {
        // For tooltip.
        bg.dataIndex = thisNode.dataIndex;
        bg.seriesIndex = seriesModel.seriesIndex;

        bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight});
        var visualBorderColor = thisNode.getVisual('borderColor', true);
        var emphasisBorderColor = itemStyleEmphasisModel.get('borderColor');

        updateStyle(bg, function () {
            var normalStyle = getItemStyleNormal(itemStyleNormalModel);
            normalStyle.fill = visualBorderColor;
            var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);
            emphasisStyle.fill = emphasisBorderColor;

            if (useUpperLabel) {
                var upperLabelWidth = thisWidth - 2 * borderWidth;

                prepareText(
                    normalStyle, emphasisStyle, visualBorderColor, upperLabelWidth, upperHeight,
                    {x: borderWidth, y: 0, width: upperLabelWidth, height: upperHeight}
                );
            }
            // For old bg.
            else {
                normalStyle.text = emphasisStyle.text = null;
            }

            bg.setStyle(normalStyle);
            setHoverStyle(bg, emphasisStyle);
        });

        group.add(bg);
    }

    function renderContent(group, content) {
        // For tooltip.
        content.dataIndex = thisNode.dataIndex;
        content.seriesIndex = seriesModel.seriesIndex;

        var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0);
        var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0);

        content.culling = true;
        content.setShape({
            x: borderWidth,
            y: borderWidth,
            width: contentWidth,
            height: contentHeight
        });

        var visualColor = thisNode.getVisual('color', true);
        updateStyle(content, function () {
            var normalStyle = getItemStyleNormal(itemStyleNormalModel);
            normalStyle.fill = visualColor;
            var emphasisStyle = getItemStyleEmphasis(itemStyleEmphasisModel);

            prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight);

            content.setStyle(normalStyle);
            setHoverStyle(content, emphasisStyle);
        });

        group.add(content);
    }

    function updateStyle(element, cb) {
        if (!thisInvisible) {
            // If invisible, do not set visual, otherwise the element will
            // change immediately before animation. We think it is OK to
            // remain its origin color when moving out of the view window.
            cb();

            if (!element.__tmWillVisible) {
                element.invisible = false;
            }
        }
        else {
            // Delay invisible setting utill animation finished,
            // avoid element vanish suddenly before animation.
            !element.invisible && willInvisibleEls.push(element);
        }
    }

    function prepareText(normalStyle, emphasisStyle, visualColor, width, height, upperLabelRect) {
        var nodeModel = thisNode.getModel();
        var text = retrieve(
            seriesModel.getFormattedLabel(
                thisNode.dataIndex, 'normal', null, null, upperLabelRect ? 'upperLabel' : 'label'
            ),
            nodeModel.get('name')
        );
        if (!upperLabelRect && thisLayout.isLeafRoot) {
            var iconChar = seriesModel.get('drillDownIcon', true);
            text = iconChar ? iconChar + ' ' + text : text;
        }

        var normalLabelModel = nodeModel.getModel(
            upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL
        );
        var emphasisLabelModel = nodeModel.getModel(
            upperLabelRect ? PATH_UPPERLABEL_EMPHASIS : PATH_LABEL_EMPHASIS
        );

        var isShow = normalLabelModel.getShallow('show');

        setLabelStyle(
            normalStyle, emphasisStyle, normalLabelModel, emphasisLabelModel,
            {
                defaultText: isShow ? text : null,
                autoColor: visualColor,
                isRectText: true
            }
        );

        upperLabelRect && (normalStyle.textRect = clone(upperLabelRect));

        normalStyle.truncate = (isShow && normalLabelModel.get('ellipsis'))
            ? {
                outerWidth: width,
                outerHeight: height,
                minChar: 2
            }
            : null;
    }

    function giveGraphic(storageName, Ctor, depth, z) {
        var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex];
        var lasts = lastsForAnimation[storageName];

        if (element) {
            // Remove from oldStorage
            oldStorage[storageName][oldRawIndex] = null;
            prepareAnimationWhenHasOld(lasts, element, storageName);
        }
        // If invisible and no old element, do not create new element (for optimizing).
        else if (!thisInvisible) {
            element = new Ctor({z: calculateZ(depth, z)});
            element.__tmDepth = depth;
            element.__tmStorageName = storageName;
            prepareAnimationWhenNoOld(lasts, element, storageName);
        }

        // Set to thisStorage
        return (thisStorage[storageName][thisRawIndex] = element);
    }

    function prepareAnimationWhenHasOld(lasts, element, storageName) {
        var lastCfg = lasts[thisRawIndex] = {};
        lastCfg.old = storageName === 'nodeGroup'
            ? element.position.slice()
            : extend({}, element.shape);
    }

    // If a element is new, we need to find the animation start point carefully,
    // otherwise it will looks strange when 'zoomToNode'.
    function prepareAnimationWhenNoOld(lasts, element, storageName) {
        var lastCfg = lasts[thisRawIndex] = {};
        var parentNode = thisNode.parentNode;

        if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) {
            var parentOldX = 0;
            var parentOldY = 0;

            // New nodes appear from right-bottom corner in 'zoomToNode' animation.
            // For convenience, get old bounding rect from background.
            var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()];
            if (!reRoot && parentOldBg && parentOldBg.old) {
                parentOldX = parentOldBg.old.width;
                parentOldY = parentOldBg.old.height;
            }

            // When no parent old shape found, its parent is new too,
            // so we can just use {x:0, y:0}.
            lastCfg.old = storageName === 'nodeGroup'
                ? [0, parentOldY]
                : {x: parentOldX, y: parentOldY, width: 0, height: 0};
        }

        // Fade in, user can be aware that these nodes are new.
        lastCfg.fadein = storageName !== 'nodeGroup';
    }
}

// We can not set all backgroud with the same z, Because the behaviour of
// drill down and roll up differ background creation sequence from tree
// hierarchy sequence, which cause that lowser background element overlap
// upper ones. So we calculate z based on depth.
// Moreover, we try to shrink down z interval to [0, 1] to avoid that
// treemap with large z overlaps other components.
function calculateZ(depth, zInLevel) {
    var zb = depth * Z_BASE + zInLevel;
    return (zb - 1) / zb;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @file Treemap action
 */

var noop$1 = function () {};

var actionTypes = [
    'treemapZoomToNode',
    'treemapRender',
    'treemapMove'
];

for (var i$2 = 0; i$2 < actionTypes.length; i$2++) {
    registerAction({type: actionTypes[i$2], update: 'updateView'}, noop$1);
}

registerAction(
    {type: 'treemapRootToNode', update: 'updateView'},
    function (payload, ecModel) {

        ecModel.eachComponent(
            {mainType: 'series', subType: 'treemap', query: payload},
            handleRootToNode
        );

        function handleRootToNode(model, index) {
            var types = ['treemapZoomToNode', 'treemapRootToNode'];
            var targetInfo = retrieveTargetInfo(payload, types, model);

            if (targetInfo) {
                var originViewRoot = model.getViewRoot();
                if (originViewRoot) {
                    payload.direction = aboveViewRoot(originViewRoot, targetInfo.node)
                        ? 'rollUp' : 'drillDown';
                }
                model.resetViewRoot(targetInfo.node);
            }
        }
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$9 = each$1;
var isObject$5 = isObject$1;

var CATEGORY_DEFAULT_VISUAL_INDEX = -1;

/**
 * @param {Object} option
 * @param {string} [option.type] See visualHandlers.
 * @param {string} [option.mappingMethod] 'linear' or 'piecewise' or 'category' or 'fixed'
 * @param {Array.<number>=} [option.dataExtent] [minExtent, maxExtent],
 *                                              required when mappingMethod is 'linear'
 * @param {Array.<Object>=} [option.pieceList] [
 *                                             {value: someValue},
 *                                             {interval: [min1, max1], visual: {...}},
 *                                             {interval: [min2, max2]}
 *                                             ],
 *                                            required when mappingMethod is 'piecewise'.
 *                                            Visual for only each piece can be specified.
 * @param {Array.<string|Object>=} [option.categories] ['cate1', 'cate2']
 *                                            required when mappingMethod is 'category'.
 *                                            If no option.categories, categories is set
 *                                            as [0, 1, 2, ...].
 * @param {boolean} [option.loop=false] Whether loop mapping when mappingMethod is 'category'.
 * @param {(Array|Object|*)} [option.visual]  Visual data.
 *                                            when mappingMethod is 'category',
 *                                            visual data can be array or object
 *                                            (like: {cate1: '#222', none: '#fff'})
 *                                            or primary types (which represents
 *                                            defualt category visual), otherwise visual
 *                                            can be array or primary (which will be
 *                                            normalized to array).
 *
 */
var VisualMapping = function (option) {
    var mappingMethod = option.mappingMethod;
    var visualType = option.type;

    /**
     * @readOnly
     * @type {Object}
     */
    var thisOption = this.option = clone(option);

    /**
     * @readOnly
     * @type {string}
     */
    this.type = visualType;

    /**
     * @readOnly
     * @type {string}
     */
    this.mappingMethod = mappingMethod;

    /**
     * @private
     * @type {Function}
     */
    this._normalizeData = normalizers[mappingMethod];

    var visualHandler = visualHandlers[visualType];

    /**
     * @public
     * @type {Function}
     */
    this.applyVisual = visualHandler.applyVisual;

    /**
     * @public
     * @type {Function}
     */
    this.getColorMapper = visualHandler.getColorMapper;

    /**
     * @private
     * @type {Function}
     */
    this._doMap = visualHandler._doMap[mappingMethod];

    if (mappingMethod === 'piecewise') {
        normalizeVisualRange(thisOption);
        preprocessForPiecewise(thisOption);
    }
    else if (mappingMethod === 'category') {
        thisOption.categories
            ? preprocessForSpecifiedCategory(thisOption)
            // categories is ordinal when thisOption.categories not specified,
            // which need no more preprocess except normalize visual.
            : normalizeVisualRange(thisOption, true);
    }
    else { // mappingMethod === 'linear' or 'fixed'
        assert$1(mappingMethod !== 'linear' || thisOption.dataExtent);
        normalizeVisualRange(thisOption);
    }
};

VisualMapping.prototype = {

    constructor: VisualMapping,

    mapValueToVisual: function (value) {
        var normalized = this._normalizeData(value);
        return this._doMap(normalized, value);
    },

    getNormalizer: function () {
        return bind(this._normalizeData, this);
    }
};

var visualHandlers = VisualMapping.visualHandlers = {

    color: {

        applyVisual: makeApplyVisual('color'),

        /**
         * Create a mapper function
         * @return {Function}
         */
        getColorMapper: function () {
            var thisOption = this.option;

            return bind(
                thisOption.mappingMethod === 'category'
                    ? function (value, isNormalized) {
                        !isNormalized && (value = this._normalizeData(value));
                        return doMapCategory.call(this, value);
                    }
                    : function (value, isNormalized, out) {
                        // If output rgb array
                        // which will be much faster and useful in pixel manipulation
                        var returnRGBArray = !!out;
                        !isNormalized && (value = this._normalizeData(value));
                        out = fastLerp(value, thisOption.parsedVisual, out);
                        return returnRGBArray ? out : stringify(out, 'rgba');
                    },
                this
            );
        },

        _doMap: {
            linear: function (normalized) {
                return stringify(
                    fastLerp(normalized, this.option.parsedVisual),
                    'rgba'
                );
            },
            category: doMapCategory,
            piecewise: function (normalized, value) {
                var result = getSpecifiedVisual.call(this, value);
                if (result == null) {
                    result = stringify(
                        fastLerp(normalized, this.option.parsedVisual),
                        'rgba'
                    );
                }
                return result;
            },
            fixed: doMapFixed
        }
    },

    colorHue: makePartialColorVisualHandler(function (color, value) {
        return modifyHSL(color, value);
    }),

    colorSaturation: makePartialColorVisualHandler(function (color, value) {
        return modifyHSL(color, null, value);
    }),

    colorLightness: makePartialColorVisualHandler(function (color, value) {
        return modifyHSL(color, null, null, value);
    }),

    colorAlpha: makePartialColorVisualHandler(function (color, value) {
        return modifyAlpha(color, value);
    }),

    opacity: {
        applyVisual: makeApplyVisual('opacity'),
        _doMap: makeDoMap([0, 1])
    },

    liftZ: {
        applyVisual: makeApplyVisual('liftZ'),
        _doMap: {
            linear: doMapFixed,
            category: doMapFixed,
            piecewise: doMapFixed,
            fixed: doMapFixed
        }
    },

    symbol: {
        applyVisual: function (value, getter, setter) {
            var symbolCfg = this.mapValueToVisual(value);
            if (isString(symbolCfg)) {
                setter('symbol', symbolCfg);
            }
            else if (isObject$5(symbolCfg)) {
                for (var name in symbolCfg) {
                    if (symbolCfg.hasOwnProperty(name)) {
                        setter(name, symbolCfg[name]);
                    }
                }
            }
        },
        _doMap: {
            linear: doMapToArray,
            category: doMapCategory,
            piecewise: function (normalized, value) {
                var result = getSpecifiedVisual.call(this, value);
                if (result == null) {
                    result = doMapToArray.call(this, normalized);
                }
                return result;
            },
            fixed: doMapFixed
        }
    },

    symbolSize: {
        applyVisual: makeApplyVisual('symbolSize'),
        _doMap: makeDoMap([0, 1])
    }
};


function preprocessForPiecewise(thisOption) {
    var pieceList = thisOption.pieceList;
    thisOption.hasSpecialVisual = false;

    each$1(pieceList, function (piece, index) {
        piece.originIndex = index;
        // piece.visual is "result visual value" but not
        // a visual range, so it does not need to be normalized.
        if (piece.visual != null) {
            thisOption.hasSpecialVisual = true;
        }
    });
}

function preprocessForSpecifiedCategory(thisOption) {
    // Hash categories.
    var categories = thisOption.categories;
    var visual = thisOption.visual;

    var categoryMap = thisOption.categoryMap = {};
    each$9(categories, function (cate, index) {
        categoryMap[cate] = index;
    });

    // Process visual map input.
    if (!isArray(visual)) {
        var visualArr = [];

        if (isObject$1(visual)) {
            each$9(visual, function (v, cate) {
                var index = categoryMap[cate];
                visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
            });
        }
        else { // Is primary type, represents default visual.
            visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
        }

        visual = setVisualToOption(thisOption, visualArr);
    }

    // Remove categories that has no visual,
    // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX.
    for (var i = categories.length - 1; i >= 0; i--) {
        if (visual[i] == null) {
            delete categoryMap[categories[i]];
            categories.pop();
        }
    }
}

function normalizeVisualRange(thisOption, isCategory) {
    var visual = thisOption.visual;
    var visualArr = [];

    if (isObject$1(visual)) {
        each$9(visual, function (v) {
            visualArr.push(v);
        });
    }
    else if (visual != null) {
        visualArr.push(visual);
    }

    var doNotNeedPair = {color: 1, symbol: 1};

    if (!isCategory
        && visualArr.length === 1
        && !doNotNeedPair.hasOwnProperty(thisOption.type)
    ) {
        // Do not care visualArr.length === 0, which is illegal.
        visualArr[1] = visualArr[0];
    }

    setVisualToOption(thisOption, visualArr);
}

function makePartialColorVisualHandler(applyValue) {
    return {
        applyVisual: function (value, getter, setter) {
            value = this.mapValueToVisual(value);
            // Must not be array value
            setter('color', applyValue(getter('color'), value));
        },
        _doMap: makeDoMap([0, 1])
    };
}

function doMapToArray(normalized) {
    var visual = this.option.visual;
    return visual[
        Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))
    ] || {};
}

function makeApplyVisual(visualType) {
    return function (value, getter, setter) {
        setter(visualType, this.mapValueToVisual(value));
    };
}

function doMapCategory(normalized) {
    var visual = this.option.visual;
    return visual[
        (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX)
            ? normalized % visual.length
            : normalized
    ];
}

function doMapFixed() {
    return this.option.visual[0];
}

function makeDoMap(sourceExtent) {
    return {
        linear: function (normalized) {
            return linearMap(normalized, sourceExtent, this.option.visual, true);
        },
        category: doMapCategory,
        piecewise: function (normalized, value) {
            var result = getSpecifiedVisual.call(this, value);
            if (result == null) {
                result = linearMap(normalized, sourceExtent, this.option.visual, true);
            }
            return result;
        },
        fixed: doMapFixed
    };
}

function getSpecifiedVisual(value) {
    var thisOption = this.option;
    var pieceList = thisOption.pieceList;
    if (thisOption.hasSpecialVisual) {
        var pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
        var piece = pieceList[pieceIndex];
        if (piece && piece.visual) {
            return piece.visual[this.type];
        }
    }
}

function setVisualToOption(thisOption, visualArr) {
    thisOption.visual = visualArr;
    if (thisOption.type === 'color') {
        thisOption.parsedVisual = map(visualArr, function (item) {
            return parse(item);
        });
    }
    return visualArr;
}


/**
 * Normalizers by mapping methods.
 */
var normalizers = {

    linear: function (value) {
        return linearMap(value, this.option.dataExtent, [0, 1], true);
    },

    piecewise: function (value) {
        var pieceList = this.option.pieceList;
        var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true);
        if (pieceIndex != null) {
            return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
        }
    },

    category: function (value) {
        var index = this.option.categories
            ? this.option.categoryMap[value]
            : value; // ordinal
        return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
    },

    fixed: noop
};



/**
 * List available visual types.
 *
 * @public
 * @return {Array.<string>}
 */
VisualMapping.listVisualTypes = function () {
    var visualTypes = [];
    each$1(visualHandlers, function (handler, key) {
        visualTypes.push(key);
    });
    return visualTypes;
};

/**
 * @public
 */
VisualMapping.addVisualHandler = function (name, handler) {
    visualHandlers[name] = handler;
};

/**
 * @public
 */
VisualMapping.isValidType = function (visualType) {
    return visualHandlers.hasOwnProperty(visualType);
};

/**
 * Convinent method.
 * Visual can be Object or Array or primary type.
 *
 * @public
 */
VisualMapping.eachVisual = function (visual, callback, context) {
    if (isObject$1(visual)) {
        each$1(visual, callback, context);
    }
    else {
        callback.call(context, visual);
    }
};

VisualMapping.mapVisual = function (visual, callback, context) {
    var isPrimary;
    var newVisual = isArray(visual)
        ? []
        : isObject$1(visual)
        ? {}
        : (isPrimary = true, null);

    VisualMapping.eachVisual(visual, function (v, key) {
        var newVal = callback.call(context, v, key);
        isPrimary ? (newVisual = newVal) : (newVisual[key] = newVal);
    });
    return newVisual;
};

/**
 * @public
 * @param {Object} obj
 * @return {Object} new object containers visual values.
 *                 If no visuals, return null.
 */
VisualMapping.retrieveVisuals = function (obj) {
    var ret = {};
    var hasVisual;

    obj && each$9(visualHandlers, function (h, visualType) {
        if (obj.hasOwnProperty(visualType)) {
            ret[visualType] = obj[visualType];
            hasVisual = true;
        }
    });

    return hasVisual ? ret : null;
};

/**
 * Give order to visual types, considering colorSaturation, colorAlpha depends on color.
 *
 * @public
 * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...}
 *                                     IF Array, like: ['color', 'symbol', 'colorSaturation']
 * @return {Array.<string>} Sorted visual types.
 */
VisualMapping.prepareVisualTypes = function (visualTypes) {
    if (isObject$5(visualTypes)) {
        var types = [];
        each$9(visualTypes, function (item, type) {
            types.push(type);
        });
        visualTypes = types;
    }
    else if (isArray(visualTypes)) {
        visualTypes = visualTypes.slice();
    }
    else {
        return [];
    }

    visualTypes.sort(function (type1, type2) {
        // color should be front of colorSaturation, colorAlpha, ...
        // symbol and symbolSize do not matter.
        return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0)
            ? 1 : -1;
    });

    return visualTypes;
};

/**
 * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'.
 * Other visuals are only depends on themself.
 *
 * @public
 * @param {string} visualType1
 * @param {string} visualType2
 * @return {boolean}
 */
VisualMapping.dependsOn = function (visualType1, visualType2) {
    return visualType2 === 'color'
        ? !!(visualType1 && visualType1.indexOf(visualType2) === 0)
        : visualType1 === visualType2;
};

/**
 * @param {number} value
 * @param {Array.<Object>} pieceList [{value: ..., interval: [min, max]}, ...]
 *                         Always from small to big.
 * @param {boolean} [findClosestWhenOutside=false]
 * @return {number} index
 */
VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) {
    var possibleI;
    var abs = Infinity;

    // value has the higher priority.
    for (var i = 0, len = pieceList.length; i < len; i++) {
        var pieceValue = pieceList[i].value;
        if (pieceValue != null) {
            if (pieceValue === value
                // FIXME
                // It is supposed to compare value according to value type of dimension,
                // but currently value type can exactly be string or number.
                // Compromise for numeric-like string (like '12'), especially
                // in the case that visualMap.categories is ['22', '33'].
                || (typeof pieceValue === 'string' && pieceValue === value + '')
            ) {
                return i;
            }
            findClosestWhenOutside && updatePossible(pieceValue, i);
        }
    }

    for (var i = 0, len = pieceList.length; i < len; i++) {
        var piece = pieceList[i];
        var interval = piece.interval;
        var close = piece.close;

        if (interval) {
            if (interval[0] === -Infinity) {
                if (littleThan(close[1], value, interval[1])) {
                    return i;
                }
            }
            else if (interval[1] === Infinity) {
                if (littleThan(close[0], interval[0], value)) {
                    return i;
                }
            }
            else if (
                littleThan(close[0], interval[0], value)
                && littleThan(close[1], value, interval[1])
            ) {
                return i;
            }
            findClosestWhenOutside && updatePossible(interval[0], i);
            findClosestWhenOutside && updatePossible(interval[1], i);
        }
    }

    if (findClosestWhenOutside) {
        return value === Infinity
            ? pieceList.length - 1
            : value === -Infinity
            ? 0
            : possibleI;
    }

    function updatePossible(val, index) {
        var newAbs = Math.abs(val - value);
        if (newAbs < abs) {
            abs = newAbs;
            possibleI = index;
        }
    }

};

function littleThan(close, a, b) {
    return close ? a <= b : a < b;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var isArray$2 = isArray;

var ITEM_STYLE_NORMAL = 'itemStyle';

var treemapVisual = {
    seriesType: 'treemap',
    reset: function (seriesModel, ecModel, api, payload) {
        var tree = seriesModel.getData().tree;
        var root = tree.root;
        var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL);

        if (root.isRemoved()) {
            return;
        }

        var levelItemStyles = map(tree.levelModels, function (levelModel) {
            return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null;
        });

        travelTree(
            root, // Visual should calculate from tree root but not view root.
            {},
            levelItemStyles,
            seriesItemStyleModel,
            seriesModel.getViewRoot().getAncestors(),
            seriesModel
        );
    }
};

function travelTree(
    node, designatedVisual, levelItemStyles, seriesItemStyleModel,
    viewRootAncestors, seriesModel
) {
    var nodeModel = node.getModel();
    var nodeLayout = node.getLayout();

    // Optimize
    if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) {
        return;
    }

    var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL);
    var levelItemStyle = levelItemStyles[node.depth];
    var visuals = buildVisuals(
        nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
    );

    // calculate border color
    var borderColor = nodeItemStyleModel.get('borderColor');
    var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation');
    var thisNodeColor;
    if (borderColorSaturation != null) {
        // For performance, do not always execute 'calculateColor'.
        thisNodeColor = calculateColor(visuals, node);
        borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor);
    }
    node.setVisual('borderColor', borderColor);

    var viewChildren = node.viewChildren;
    if (!viewChildren || !viewChildren.length) {
        thisNodeColor = calculateColor(visuals, node);
        // Apply visual to this node.
        node.setVisual('color', thisNodeColor);
    }
    else {
        var mapping = buildVisualMapping(
            node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren
        );

        // Designate visual to children.
        each$1(viewChildren, function (child, index) {
            // If higher than viewRoot, only ancestors of viewRoot is needed to visit.
            if (child.depth >= viewRootAncestors.length
                || child === viewRootAncestors[child.depth]
            ) {
                var childVisual = mapVisual$1(
                    nodeModel, visuals, child, index, mapping, seriesModel
                );
                travelTree(
                    child, childVisual, levelItemStyles, seriesItemStyleModel,
                    viewRootAncestors, seriesModel
                );
            }
        });
    }
}

function buildVisuals(
    nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
) {
    var visuals = extend({}, designatedVisual);

    each$1(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
        // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel
        var val = nodeItemStyleModel.get(visualName, true); // Ignore parent
        val == null && levelItemStyle && (val = levelItemStyle[visualName]);
        val == null && (val = designatedVisual[visualName]);
        val == null && (val = seriesItemStyleModel.get(visualName));

        val != null && (visuals[visualName] = val);
    });

    return visuals;
}

function calculateColor(visuals) {
    var color = getValueVisualDefine(visuals, 'color');

    if (color) {
        var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha');
        var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation');
        if (colorSaturation) {
            color = modifyHSL(color, null, null, colorSaturation);
        }
        if (colorAlpha) {
            color = modifyAlpha(color, colorAlpha);
        }

        return color;
    }
}

function calculateBorderColor(borderColorSaturation, thisNodeColor) {
    return thisNodeColor != null
            ? modifyHSL(thisNodeColor, null, null, borderColorSaturation)
            : null;
}

function getValueVisualDefine(visuals, name) {
    var value = visuals[name];
    if (value != null && value !== 'none') {
        return value;
    }
}

function buildVisualMapping(
    node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren
) {
    if (!viewChildren || !viewChildren.length) {
        return;
    }

    var rangeVisual = getRangeVisual(nodeModel, 'color')
        || (
            visuals.color != null
            && visuals.color !== 'none'
            && (
                getRangeVisual(nodeModel, 'colorAlpha')
                || getRangeVisual(nodeModel, 'colorSaturation')
            )
        );

    if (!rangeVisual) {
        return;
    }

    var visualMin = nodeModel.get('visualMin');
    var visualMax = nodeModel.get('visualMax');
    var dataExtent = nodeLayout.dataExtent.slice();
    visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin);
    visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax);

    var colorMappingBy = nodeModel.get('colorMappingBy');
    var opt = {
        type: rangeVisual.name,
        dataExtent: dataExtent,
        visual: rangeVisual.range
    };
    if (opt.type === 'color'
        && (colorMappingBy === 'index' || colorMappingBy === 'id')
    ) {
        opt.mappingMethod = 'category';
        opt.loop = true;
        // categories is ordinal, so do not set opt.categories.
    }
    else {
        opt.mappingMethod = 'linear';
    }

    var mapping = new VisualMapping(opt);
    mapping.__drColorMappingBy = colorMappingBy;

    return mapping;
}

// Notice: If we dont have the attribute 'colorRange', but only use
// attribute 'color' to represent both concepts of 'colorRange' and 'color',
// (It means 'colorRange' when 'color' is Array, means 'color' when not array),
// this problem will be encountered:
// If a level-1 node dont have children, and its siblings has children,
// and colorRange is set on level-1, then the node can not be colored.
// So we separate 'colorRange' and 'color' to different attributes.
function getRangeVisual(nodeModel, name) {
    // 'colorRange', 'colorARange', 'colorSRange'.
    // If not exsits on this node, fetch from levels and series.
    var range = nodeModel.get(name);
    return (isArray$2(range) && range.length) ? {name: name, range: range} : null;
}

function mapVisual$1(nodeModel, visuals, child, index, mapping, seriesModel) {
    var childVisuals = extend({}, visuals);

    if (mapping) {
        var mappingType = mapping.type;
        var colorMappingBy = mappingType === 'color' && mapping.__drColorMappingBy;
        var value = colorMappingBy === 'index'
            ? index
            : colorMappingBy === 'id'
            ? seriesModel.mapIdToIndex(child.getId())
            : child.getValue(nodeModel.get('visualDimension'));

        childVisuals[mappingType] = mapping.mapValueToVisual(value);
    }

    return childVisuals;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* A third-party license is embeded for some of the code in this file:
* The treemap layout implementation was originally copied from
* "d3.js" with some modifications made for this project.
* (See more details in the comment of the method "squarify" below.)
* The use of the source code of this file is also subject to the terms
* and consitions of the license of "d3.js" (BSD-3Clause, see
* </licenses/LICENSE-d3>).
*/

var mathMax$5 = Math.max;
var mathMin$5 = Math.min;
var retrieveValue = retrieve;
var each$10 = each$1;

var PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth'];
var PATH_GAP_WIDTH = ['itemStyle', 'gapWidth'];
var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'show'];
var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'height'];

/**
 * @public
 */
var treemapLayout = {
    seriesType: 'treemap',
    reset: function (seriesModel, ecModel, api, payload) {
        // Layout result in each node:
        // {x, y, width, height, area, borderWidth}
        var ecWidth = api.getWidth();
        var ecHeight = api.getHeight();
        var seriesOption = seriesModel.option;

        var layoutInfo = getLayoutRect(
            seriesModel.getBoxLayoutParams(),
            {
                width: api.getWidth(),
                height: api.getHeight()
            }
        );

        var size = seriesOption.size || []; // Compatible with ec2.
        var containerWidth = parsePercent$1(
            retrieveValue(layoutInfo.width, size[0]),
            ecWidth
        );
        var containerHeight = parsePercent$1(
            retrieveValue(layoutInfo.height, size[1]),
            ecHeight
        );

        // Fetch payload info.
        var payloadType = payload && payload.type;
        var types = ['treemapZoomToNode', 'treemapRootToNode'];
        var targetInfo = retrieveTargetInfo(payload, types, seriesModel);
        var rootRect = (payloadType === 'treemapRender' || payloadType === 'treemapMove')
            ? payload.rootRect : null;
        var viewRoot = seriesModel.getViewRoot();
        var viewAbovePath = getPathToRoot(viewRoot);

        if (payloadType !== 'treemapMove') {
            var rootSize = payloadType === 'treemapZoomToNode'
                ? estimateRootSize(
                    seriesModel, targetInfo, viewRoot, containerWidth, containerHeight
                )
                : rootRect
                ? [rootRect.width, rootRect.height]
                : [containerWidth, containerHeight];

            var sort = seriesOption.sort;
            if (sort && sort !== 'asc' && sort !== 'desc') {
                sort = 'desc';
            }
            var options = {
                squareRatio: seriesOption.squareRatio,
                sort: sort,
                leafDepth: seriesOption.leafDepth
            };

            // layout should be cleared because using updateView but not update.
            viewRoot.hostTree.clearLayouts();

            // TODO
            // optimize: if out of view clip, do not layout.
            // But take care that if do not render node out of view clip,
            // how to calculate start po

            var viewRootLayout = {
                x: 0, y: 0,
                width: rootSize[0], height: rootSize[1],
                area: rootSize[0] * rootSize[1]
            };
            viewRoot.setLayout(viewRootLayout);

            squarify(viewRoot, options, false, 0);
            // Supplement layout.
            var viewRootLayout = viewRoot.getLayout();
            each$10(viewAbovePath, function (node, index) {
                var childValue = (viewAbovePath[index + 1] || viewRoot).getValue();
                node.setLayout(extend(
                    {dataExtent: [childValue, childValue], borderWidth: 0, upperHeight: 0},
                    viewRootLayout
                ));
            });
        }

        var treeRoot = seriesModel.getData().tree.root;

        treeRoot.setLayout(
            calculateRootPosition(layoutInfo, rootRect, targetInfo),
            true
        );

        seriesModel.setLayoutInfo(layoutInfo);

        // FIXME
        // 现在没有clip功能，暂时取ec高宽。
        prunning(
            treeRoot,
            // Transform to base element coordinate system.
            new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight),
            viewAbovePath,
            viewRoot,
            0
        );
    }
};

/**
 * Layout treemap with squarify algorithm.
 * The original presentation of this algorithm
 * was made by Mark Bruls, Kees Huizing, and Jarke J. van Wijk
 * <https://graphics.ethz.ch/teaching/scivis_common/Literature/squarifiedTreeMaps.pdf>.
 * The implementation of this algorithm was originally copied from "d3.js"
 * <https://github.com/d3/d3/blob/9cc9a875e636a1dcf36cc1e07bdf77e1ad6e2c74/src/layout/treemap.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 *
 * @protected
 * @param {module:echarts/data/Tree~TreeNode} node
 * @param {Object} options
 * @param {string} options.sort 'asc' or 'desc'
 * @param {number} options.squareRatio
 * @param {boolean} hideChildren
 * @param {number} depth
 */
function squarify(node, options, hideChildren, depth) {
    var width;
    var height;

    if (node.isRemoved()) {
        return;
    }

    var thisLayout = node.getLayout();
    width = thisLayout.width;
    height = thisLayout.height;

    // Considering border and gap
    var nodeModel = node.getModel();
    var borderWidth = nodeModel.get(PATH_BORDER_WIDTH);
    var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2;
    var upperLabelHeight = getUpperLabelHeight(nodeModel);
    var upperHeight = Math.max(borderWidth, upperLabelHeight);
    var layoutOffset = borderWidth - halfGapWidth;
    var layoutOffsetUpper = upperHeight - halfGapWidth;
    var nodeModel = node.getModel();

    node.setLayout({
        borderWidth: borderWidth,
        upperHeight: upperHeight,
        upperLabelHeight: upperLabelHeight
    }, true);

    width = mathMax$5(width - 2 * layoutOffset, 0);
    height = mathMax$5(height - layoutOffset - layoutOffsetUpper, 0);

    var totalArea = width * height;
    var viewChildren = initChildren(
        node, nodeModel, totalArea, options, hideChildren, depth
    );

    if (!viewChildren.length) {
        return;
    }

    var rect = {x: layoutOffset, y: layoutOffsetUpper, width: width, height: height};
    var rowFixedLength = mathMin$5(width, height);
    var best = Infinity; // the best row score so far
    var row = [];
    row.area = 0;

    for (var i = 0, len = viewChildren.length; i < len;) {
        var child = viewChildren[i];

        row.push(child);
        row.area += child.getLayout().area;
        var score = worst(row, rowFixedLength, options.squareRatio);

        // continue with this orientation
        if (score <= best) {
            i++;
            best = score;
        }
        // abort, and try a different orientation
        else {
            row.area -= row.pop().getLayout().area;
            position(row, rowFixedLength, rect, halfGapWidth, false);
            rowFixedLength = mathMin$5(rect.width, rect.height);
            row.length = row.area = 0;
            best = Infinity;
        }
    }

    if (row.length) {
        position(row, rowFixedLength, rect, halfGapWidth, true);
    }

    if (!hideChildren) {
        var childrenVisibleMin = nodeModel.get('childrenVisibleMin');
        if (childrenVisibleMin != null && totalArea < childrenVisibleMin) {
            hideChildren = true;
        }
    }

    for (var i = 0, len = viewChildren.length; i < len; i++) {
        squarify(viewChildren[i], options, hideChildren, depth + 1);
    }
}

/**
 * Set area to each child, and calculate data extent for visual coding.
 */
function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) {
    var viewChildren = node.children || [];
    var orderBy = options.sort;
    orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null);

    var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth;

    // leafDepth has higher priority.
    if (hideChildren && !overLeafDepth) {
        return (node.viewChildren = []);
    }

    // Sort children, order by desc.
    viewChildren = filter(viewChildren, function (child) {
        return !child.isRemoved();
    });

    sort$1(viewChildren, orderBy);

    var info = statistic(nodeModel, viewChildren, orderBy);

    if (info.sum === 0) {
        return (node.viewChildren = []);
    }

    info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren);

    if (info.sum === 0) {
        return (node.viewChildren = []);
    }

    // Set area to each child.
    for (var i = 0, len = viewChildren.length; i < len; i++) {
        var area = viewChildren[i].getValue() / info.sum * totalArea;
        // Do not use setLayout({...}, true), because it is needed to clear last layout.
        viewChildren[i].setLayout({area: area});
    }

    if (overLeafDepth) {
        viewChildren.length && node.setLayout({isLeafRoot: true}, true);
        viewChildren.length = 0;
    }

    node.viewChildren = viewChildren;
    node.setLayout({dataExtent: info.dataExtent}, true);

    return viewChildren;
}

/**
 * Consider 'visibleMin'. Modify viewChildren and get new sum.
 */
function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) {

    // visibleMin is not supported yet when no option.sort.
    if (!orderBy) {
        return sum;
    }

    var visibleMin = nodeModel.get('visibleMin');
    var len = orderedChildren.length;
    var deletePoint = len;

    // Always travel from little value to big value.
    for (var i = len - 1; i >= 0; i--) {
        var value = orderedChildren[
            orderBy === 'asc' ? len - i - 1 : i
        ].getValue();

        if (value / sum * totalArea < visibleMin) {
            deletePoint = i;
            sum -= value;
        }
    }

    orderBy === 'asc'
        ? orderedChildren.splice(0, len - deletePoint)
        : orderedChildren.splice(deletePoint, len - deletePoint);

    return sum;
}

/**
 * Sort
 */
function sort$1(viewChildren, orderBy) {
    if (orderBy) {
        viewChildren.sort(function (a, b) {
            var diff = orderBy === 'asc'
                ? a.getValue() - b.getValue() : b.getValue() - a.getValue();
            return diff === 0
                ? (orderBy === 'asc'
                    ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex
                )
                : diff;
        });
    }
    return viewChildren;
}

/**
 * Statistic
 */
function statistic(nodeModel, children, orderBy) {
    // Calculate sum.
    var sum = 0;
    for (var i = 0, len = children.length; i < len; i++) {
        sum += children[i].getValue();
    }

    // Statistic data extent for latter visual coding.
    // Notice: data extent should be calculate based on raw children
    // but not filtered view children, otherwise visual mapping will not
    // be stable when zoom (where children is filtered by visibleMin).

    var dimension = nodeModel.get('visualDimension');
    var dataExtent;

    // The same as area dimension.
    if (!children || !children.length) {
        dataExtent = [NaN, NaN];
    }
    else if (dimension === 'value' && orderBy) {
        dataExtent = [
            children[children.length - 1].getValue(),
            children[0].getValue()
        ];
        orderBy === 'asc' && dataExtent.reverse();
    }
    // Other dimension.
    else {
        var dataExtent = [Infinity, -Infinity];
        each$10(children, function (child) {
            var value = child.getValue(dimension);
            value < dataExtent[0] && (dataExtent[0] = value);
            value > dataExtent[1] && (dataExtent[1] = value);
        });
    }

    return {sum: sum, dataExtent: dataExtent};
}

/**
 * Computes the score for the specified row,
 * as the worst aspect ratio.
 */
function worst(row, rowFixedLength, ratio) {
    var areaMax = 0;
    var areaMin = Infinity;

    for (var i = 0, area, len = row.length; i < len; i++) {
        area = row[i].getLayout().area;
        if (area) {
            area < areaMin && (areaMin = area);
            area > areaMax && (areaMax = area);
        }
    }

    var squareArea = row.area * row.area;
    var f = rowFixedLength * rowFixedLength * ratio;

    return squareArea
        ? mathMax$5(
            (f * areaMax) / squareArea,
            squareArea / (f * areaMin)
        )
        : Infinity;
}

/**
 * Positions the specified row of nodes. Modifies `rect`.
 */
function position(row, rowFixedLength, rect, halfGapWidth, flush) {
    // When rowFixedLength === rect.width,
    // it is horizontal subdivision,
    // rowFixedLength is the width of the subdivision,
    // rowOtherLength is the height of the subdivision,
    // and nodes will be positioned from left to right.

    // wh[idx0WhenH] means: when horizontal,
    //      wh[idx0WhenH] => wh[0] => 'width'.
    //      xy[idx1WhenH] => xy[1] => 'y'.
    var idx0WhenH = rowFixedLength === rect.width ? 0 : 1;
    var idx1WhenH = 1 - idx0WhenH;
    var xy = ['x', 'y'];
    var wh = ['width', 'height'];

    var last = rect[xy[idx0WhenH]];
    var rowOtherLength = rowFixedLength
        ? row.area / rowFixedLength : 0;

    if (flush || rowOtherLength > rect[wh[idx1WhenH]]) {
        rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow
    }
    for (var i = 0, rowLen = row.length; i < rowLen; i++) {
        var node = row[i];
        var nodeLayout = {};
        var step = rowOtherLength
            ? node.getLayout().area / rowOtherLength : 0;

        var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax$5(rowOtherLength - 2 * halfGapWidth, 0);

        // We use Math.max/min to avoid negative width/height when considering gap width.
        var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last;
        var modWH = (i === rowLen - 1 || remain < step) ? remain : step;
        var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax$5(modWH - 2 * halfGapWidth, 0);

        nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin$5(halfGapWidth, wh1 / 2);
        nodeLayout[xy[idx0WhenH]] = last + mathMin$5(halfGapWidth, wh0 / 2);

        last += modWH;
        node.setLayout(nodeLayout, true);
    }

    rect[xy[idx1WhenH]] += rowOtherLength;
    rect[wh[idx1WhenH]] -= rowOtherLength;
}

// Return [containerWidth, containerHeight] as defualt.
function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
    // If targetInfo.node exists, we zoom to the node,
    // so estimate whold width and heigth by target node.
    var currNode = (targetInfo || {}).node;
    var defaultSize = [containerWidth, containerHeight];

    if (!currNode || currNode === viewRoot) {
        return defaultSize;
    }

    var parent;
    var viewArea = containerWidth * containerHeight;
    var area = viewArea * seriesModel.option.zoomToNodeRatio;

    while (parent = currNode.parentNode) { // jshint ignore:line
        var sum = 0;
        var siblings = parent.children;

        for (var i = 0, len = siblings.length; i < len; i++) {
            sum += siblings[i].getValue();
        }
        var currNodeValue = currNode.getValue();
        if (currNodeValue === 0) {
            return defaultSize;
        }
        area *= sum / currNodeValue;

        // Considering border, suppose aspect ratio is 1.
        var parentModel = parent.getModel();
        var borderWidth = parentModel.get(PATH_BORDER_WIDTH);
        var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel, borderWidth));
        area += 4 * borderWidth * borderWidth
            + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5);

        area > MAX_SAFE_INTEGER && (area = MAX_SAFE_INTEGER);

        currNode = parent;
    }

    area < viewArea && (area = viewArea);
    var scale = Math.pow(area / viewArea, 0.5);

    return [containerWidth * scale, containerHeight * scale];
}

// Root postion base on coord of containerGroup
function calculateRootPosition(layoutInfo, rootRect, targetInfo) {
    if (rootRect) {
        return {x: rootRect.x, y: rootRect.y};
    }

    var defaultPosition = {x: 0, y: 0};
    if (!targetInfo) {
        return defaultPosition;
    }

    // If targetInfo is fetched by 'retrieveTargetInfo',
    // old tree and new tree are the same tree,
    // so the node still exists and we can visit it.

    var targetNode = targetInfo.node;
    var layout = targetNode.getLayout();

    if (!layout) {
        return defaultPosition;
    }

    // Transform coord from local to container.
    var targetCenter = [layout.width / 2, layout.height / 2];
    var node = targetNode;
    while (node) {
        var nodeLayout = node.getLayout();
        targetCenter[0] += nodeLayout.x;
        targetCenter[1] += nodeLayout.y;
        node = node.parentNode;
    }

    return {
        x: layoutInfo.width / 2 - targetCenter[0],
        y: layoutInfo.height / 2 - targetCenter[1]
    };
}

// Mark nodes visible for prunning when visual coding and rendering.
// Prunning depends on layout and root position, so we have to do it after layout.
function prunning(node, clipRect, viewAbovePath, viewRoot, depth) {
    var nodeLayout = node.getLayout();
    var nodeInViewAbovePath = viewAbovePath[depth];
    var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node;

    if (
        (nodeInViewAbovePath && !isAboveViewRoot)
        || (depth === viewAbovePath.length && node !== viewRoot)
    ) {
        return;
    }

    node.setLayout({
        // isInView means: viewRoot sub tree + viewAbovePath
        isInView: true,
        // invisible only means: outside view clip so that the node can not
        // see but still layout for animation preparation but not render.
        invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout),
        isAboveViewRoot: isAboveViewRoot
    }, true);

    // Transform to child coordinate.
    var childClipRect = new BoundingRect(
        clipRect.x - nodeLayout.x,
        clipRect.y - nodeLayout.y,
        clipRect.width,
        clipRect.height
    );

    each$10(node.viewChildren || [], function (child) {
        prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1);
    });
}

function getUpperLabelHeight(model) {
    return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(treemapVisual);
registerLayout(treemapLayout);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// id may be function name of Object, add a prefix to avoid this problem.
function generateNodeKey(id) {
    return '_EC_' + id;
}
/**
 * @alias module:echarts/data/Graph
 * @constructor
 * @param {boolean} directed
 */
var Graph = function (directed) {
    /**
     * 是否是有向图
     * @type {boolean}
     * @private
     */
    this._directed = directed || false;

    /**
     * @type {Array.<module:echarts/data/Graph.Node>}
     * @readOnly
     */
    this.nodes = [];

    /**
     * @type {Array.<module:echarts/data/Graph.Edge>}
     * @readOnly
     */
    this.edges = [];

    /**
     * @type {Object.<string, module:echarts/data/Graph.Node>}
     * @private
     */
    this._nodesMap = {};
    /**
     * @type {Object.<string, module:echarts/data/Graph.Edge>}
     * @private
     */
    this._edgesMap = {};

    /**
     * @type {module:echarts/data/List}
     * @readOnly
     */
    this.data;

    /**
     * @type {module:echarts/data/List}
     * @readOnly
     */
    this.edgeData;
};

var graphProto = Graph.prototype;
/**
 * @type {string}
 */
graphProto.type = 'graph';

/**
 * If is directed graph
 * @return {boolean}
 */
graphProto.isDirected = function () {
    return this._directed;
};

/**
 * Add a new node
 * @param {string} id
 * @param {number} [dataIndex]
 */
graphProto.addNode = function (id, dataIndex) {
    id = id == null ? ('' + dataIndex) : ('' + id);

    var nodesMap = this._nodesMap;

    if (nodesMap[generateNodeKey(id)]) {
        if (__DEV__) {
            console.error('Graph nodes have duplicate name or id');
        }
        return;
    }

    var node = new Node(id, dataIndex);
    node.hostGraph = this;

    this.nodes.push(node);

    nodesMap[generateNodeKey(id)] = node;
    return node;
};

/**
 * Get node by data index
 * @param  {number} dataIndex
 * @return {module:echarts/data/Graph~Node}
 */
graphProto.getNodeByIndex = function (dataIndex) {
    var rawIdx = this.data.getRawIndex(dataIndex);
    return this.nodes[rawIdx];
};
/**
 * Get node by id
 * @param  {string} id
 * @return {module:echarts/data/Graph.Node}
 */
graphProto.getNodeById = function (id) {
    return this._nodesMap[generateNodeKey(id)];
};

/**
 * Add a new edge
 * @param {number|string|module:echarts/data/Graph.Node} n1
 * @param {number|string|module:echarts/data/Graph.Node} n2
 * @param {number} [dataIndex=-1]
 * @return {module:echarts/data/Graph.Edge}
 */
graphProto.addEdge = function (n1, n2, dataIndex) {
    var nodesMap = this._nodesMap;
    var edgesMap = this._edgesMap;

    // PNEDING
    if (typeof n1 === 'number') {
        n1 = this.nodes[n1];
    }
    if (typeof n2 === 'number') {
        n2 = this.nodes[n2];
    }

    if (!Node.isInstance(n1)) {
        n1 = nodesMap[generateNodeKey(n1)];
    }
    if (!Node.isInstance(n2)) {
        n2 = nodesMap[generateNodeKey(n2)];
    }
    if (!n1 || !n2) {
        return;
    }

    var key = n1.id + '-' + n2.id;
    // PENDING
    if (edgesMap[key]) {
        return;
    }

    var edge = new Edge(n1, n2, dataIndex);
    edge.hostGraph = this;

    if (this._directed) {
        n1.outEdges.push(edge);
        n2.inEdges.push(edge);
    }
    n1.edges.push(edge);
    if (n1 !== n2) {
        n2.edges.push(edge);
    }

    this.edges.push(edge);
    edgesMap[key] = edge;

    return edge;
};

/**
 * Get edge by data index
 * @param  {number} dataIndex
 * @return {module:echarts/data/Graph~Node}
 */
graphProto.getEdgeByIndex = function (dataIndex) {
    var rawIdx = this.edgeData.getRawIndex(dataIndex);
    return this.edges[rawIdx];
};
/**
 * Get edge by two linked nodes
 * @param  {module:echarts/data/Graph.Node|string} n1
 * @param  {module:echarts/data/Graph.Node|string} n2
 * @return {module:echarts/data/Graph.Edge}
 */
graphProto.getEdge = function (n1, n2) {
    if (Node.isInstance(n1)) {
        n1 = n1.id;
    }
    if (Node.isInstance(n2)) {
        n2 = n2.id;
    }

    var edgesMap = this._edgesMap;

    if (this._directed) {
        return edgesMap[n1 + '-' + n2];
    }
    else {
        return edgesMap[n1 + '-' + n2]
            || edgesMap[n2 + '-' + n1];
    }
};

/**
 * Iterate all nodes
 * @param  {Function} cb
 * @param  {*} [context]
 */
graphProto.eachNode = function (cb, context) {
    var nodes = this.nodes;
    var len = nodes.length;
    for (var i = 0; i < len; i++) {
        if (nodes[i].dataIndex >= 0) {
            cb.call(context, nodes[i], i);
        }
    }
};

/**
 * Iterate all edges
 * @param  {Function} cb
 * @param  {*} [context]
 */
graphProto.eachEdge = function (cb, context) {
    var edges = this.edges;
    var len = edges.length;
    for (var i = 0; i < len; i++) {
        if (edges[i].dataIndex >= 0
            && edges[i].node1.dataIndex >= 0
            && edges[i].node2.dataIndex >= 0
        ) {
            cb.call(context, edges[i], i);
        }
    }
};

/**
 * Breadth first traverse
 * @param {Function} cb
 * @param {module:echarts/data/Graph.Node} startNode
 * @param {string} [direction='none'] 'none'|'in'|'out'
 * @param {*} [context]
 */
graphProto.breadthFirstTraverse = function (
    cb, startNode, direction, context
) {
    if (!Node.isInstance(startNode)) {
        startNode = this._nodesMap[generateNodeKey(startNode)];
    }
    if (!startNode) {
        return;
    }

    var edgeType = direction === 'out'
        ? 'outEdges' : (direction === 'in' ? 'inEdges' : 'edges');

    for (var i = 0; i < this.nodes.length; i++) {
        this.nodes[i].__visited = false;
    }

    if (cb.call(context, startNode, null)) {
        return;
    }

    var queue = [startNode];
    while (queue.length) {
        var currentNode = queue.shift();
        var edges = currentNode[edgeType];

        for (var i = 0; i < edges.length; i++) {
            var e = edges[i];
            var otherNode = e.node1 === currentNode
                ? e.node2 : e.node1;
            if (!otherNode.__visited) {
                if (cb.call(context, otherNode, currentNode)) {
                    // Stop traversing
                    return;
                }
                queue.push(otherNode);
                otherNode.__visited = true;
            }
        }
    }
};

// TODO
// graphProto.depthFirstTraverse = function (
//     cb, startNode, direction, context
// ) {

// };

// Filter update
graphProto.update = function () {
    var data = this.data;
    var edgeData = this.edgeData;
    var nodes = this.nodes;
    var edges = this.edges;

    for (var i = 0, len = nodes.length; i < len; i++) {
        nodes[i].dataIndex = -1;
    }
    for (var i = 0, len = data.count(); i < len; i++) {
        nodes[data.getRawIndex(i)].dataIndex = i;
    }

    edgeData.filterSelf(function (idx) {
        var edge = edges[edgeData.getRawIndex(idx)];
        return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0;
    });

    // Update edge
    for (var i = 0, len = edges.length; i < len; i++) {
        edges[i].dataIndex = -1;
    }
    for (var i = 0, len = edgeData.count(); i < len; i++) {
        edges[edgeData.getRawIndex(i)].dataIndex = i;
    }
};

/**
 * @return {module:echarts/data/Graph}
 */
graphProto.clone = function () {
    var graph = new Graph(this._directed);
    var nodes = this.nodes;
    var edges = this.edges;
    for (var i = 0; i < nodes.length; i++) {
        graph.addNode(nodes[i].id, nodes[i].dataIndex);
    }
    for (var i = 0; i < edges.length; i++) {
        var e = edges[i];
        graph.addEdge(e.node1.id, e.node2.id, e.dataIndex);
    }
    return graph;
};


/**
 * @alias module:echarts/data/Graph.Node
 */
function Node(id, dataIndex) {
    /**
    * @type {string}
    */
    this.id = id == null ? '' : id;

    /**
    * @type {Array.<module:echarts/data/Graph.Edge>}
    */
    this.inEdges = [];
    /**
    * @type {Array.<module:echarts/data/Graph.Edge>}
    */
    this.outEdges = [];
    /**
    * @type {Array.<module:echarts/data/Graph.Edge>}
    */
    this.edges = [];
    /**
     * @type {module:echarts/data/Graph}
     */
    this.hostGraph;

    /**
     * @type {number}
     */
    this.dataIndex = dataIndex == null ? -1 : dataIndex;
}

Node.prototype = {

    constructor: Node,

    /**
     * @return {number}
     */
    degree: function () {
        return this.edges.length;
    },

    /**
     * @return {number}
     */
    inDegree: function () {
        return this.inEdges.length;
    },

    /**
    * @return {number}
    */
    outDegree: function () {
        return this.outEdges.length;
    },

    /**
     * @param {string} [path]
     * @return {module:echarts/model/Model}
     */
    getModel: function (path) {
        if (this.dataIndex < 0) {
            return;
        }
        var graph = this.hostGraph;
        var itemModel = graph.data.getItemModel(this.dataIndex);

        return itemModel.getModel(path);
    }
};

/**
 * 图边
 * @alias module:echarts/data/Graph.Edge
 * @param {module:echarts/data/Graph.Node} n1
 * @param {module:echarts/data/Graph.Node} n2
 * @param {number} [dataIndex=-1]
 */
function Edge(n1, n2, dataIndex) {

    /**
     * 节点1，如果是有向图则为源节点
     * @type {module:echarts/data/Graph.Node}
     */
    this.node1 = n1;

    /**
     * 节点2，如果是有向图则为目标节点
     * @type {module:echarts/data/Graph.Node}
     */
    this.node2 = n2;

    this.dataIndex = dataIndex == null ? -1 : dataIndex;
}

/**
 * @param {string} [path]
 * @return {module:echarts/model/Model}
 */
Edge.prototype.getModel = function (path) {
    if (this.dataIndex < 0) {
        return;
    }
    var graph = this.hostGraph;
    var itemModel = graph.edgeData.getItemModel(this.dataIndex);

    return itemModel.getModel(path);
};

var createGraphDataProxyMixin = function (hostName, dataName) {
    return {
        /**
         * @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'.
         * @return {number}
         */
        getValue: function (dimension) {
            var data = this[hostName][dataName];
            return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
        },

        /**
         * @param {Object|string} key
         * @param {*} [value]
         */
        setVisual: function (key, value) {
            this.dataIndex >= 0
                && this[hostName][dataName].setItemVisual(this.dataIndex, key, value);
        },

        /**
         * @param {string} key
         * @return {boolean}
         */
        getVisual: function (key, ignoreParent) {
            return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent);
        },

        /**
         * @param {Object} layout
         * @return {boolean} [merge=false]
         */
        setLayout: function (layout, merge$$1) {
            this.dataIndex >= 0
                && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge$$1);
        },

        /**
         * @return {Object}
         */
        getLayout: function () {
            return this[hostName][dataName].getItemLayout(this.dataIndex);
        },

        /**
         * @return {module:zrender/Element}
         */
        getGraphicEl: function () {
            return this[hostName][dataName].getItemGraphicEl(this.dataIndex);
        },

        /**
         * @return {number}
         */
        getRawIndex: function () {
            return this[hostName][dataName].getRawIndex(this.dataIndex);
        }
    };
};

mixin(Node, createGraphDataProxyMixin('hostGraph', 'data'));
mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData'));

Graph.Node = Node;
Graph.Edge = Edge;

enableClassCheck(Node);
enableClassCheck(Edge);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var createGraphFromNodeEdge = function (nodes, edges, seriesModel, directed, beforeLink) {
    // ??? TODO
    // support dataset?
    var graph = new Graph(directed);
    for (var i = 0; i < nodes.length; i++) {
        graph.addNode(retrieve(
            // Id, name, dataIndex
            nodes[i].id, nodes[i].name, i
        ), i);
    }

    var linkNameList = [];
    var validEdges = [];
    var linkCount = 0;
    for (var i = 0; i < edges.length; i++) {
        var link = edges[i];
        var source = link.source;
        var target = link.target;
        // addEdge may fail when source or target not exists
        if (graph.addEdge(source, target, linkCount)) {
            validEdges.push(link);
            linkNameList.push(retrieve(link.id, source + ' > ' + target));
            linkCount++;
        }
    }

    var coordSys = seriesModel.get('coordinateSystem');
    var nodeData;
    if (coordSys === 'cartesian2d' || coordSys === 'polar') {
        nodeData = createListFromArray(nodes, seriesModel);
    }
    else {
        var coordSysCtor = CoordinateSystemManager.get(coordSys);
        var coordDimensions = (coordSysCtor && coordSysCtor.type !== 'view')
            ? (coordSysCtor.dimensions || []) : [];
        // FIXME: Some geo do not need `value` dimenson, whereas `calendar` needs
        // `value` dimension, but graph need `value` dimension. It's better to
        // uniform this behavior.
        if (indexOf(coordDimensions, 'value') < 0) {
            coordDimensions.concat(['value']);
        }

        var dimensionNames = createDimensions(nodes, {
            coordDimensions: coordDimensions
        });
        nodeData = new List(dimensionNames, seriesModel);
        nodeData.initData(nodes);
    }

    var edgeData = new List(['value'], seriesModel);
    edgeData.initData(validEdges, linkNameList);

    beforeLink && beforeLink(nodeData, edgeData);

    linkList({
        mainData: nodeData,
        struct: graph,
        structAttr: 'graph',
        datas: {node: nodeData, edge: edgeData},
        datasAttr: {node: 'data', edge: 'edgeData'}
    });

    // Update dataIndex of nodes and edges because invalid edge may be removed
    graph.update();

    return graph;
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var GraphSeries = extendSeriesModel({

    type: 'series.graph',

    init: function (option) {
        GraphSeries.superApply(this, 'init', arguments);

        // Provide data for legend select
        this.legendDataProvider = function () {
            return this._categoriesData;
        };

        this.fillDataTextStyle(option.edges || option.links);

        this._updateCategoriesData();
    },

    mergeOption: function (option) {
        GraphSeries.superApply(this, 'mergeOption', arguments);

        this.fillDataTextStyle(option.edges || option.links);

        this._updateCategoriesData();
    },

    mergeDefaultAndTheme: function (option) {
        GraphSeries.superApply(this, 'mergeDefaultAndTheme', arguments);
        defaultEmphasis(option, ['edgeLabel'], ['show']);
    },

    getInitialData: function (option, ecModel) {
        var edges = option.edges || option.links || [];
        var nodes = option.data || option.nodes || [];
        var self = this;

        if (nodes && edges) {
            return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
        }

        function beforeLink(nodeData, edgeData) {
            // Overwrite nodeData.getItemModel to
            nodeData.wrapMethod('getItemModel', function (model) {
                var categoriesModels = self._categoriesModels;
                var categoryIdx = model.getShallow('category');
                var categoryModel = categoriesModels[categoryIdx];
                if (categoryModel) {
                    categoryModel.parentModel = model.parentModel;
                    model.parentModel = categoryModel;
                }
                return model;
            });

            var edgeLabelModel = self.getModel('edgeLabel');
            // For option `edgeLabel` can be found by label.xxx.xxx on item mode.
            var fakeSeriesModel = new Model(
                {label: edgeLabelModel.option},
                edgeLabelModel.parentModel,
                ecModel
            );
            var emphasisEdgeLabelModel = self.getModel('emphasis.edgeLabel');
            var emphasisFakeSeriesModel = new Model(
                {emphasis: {label: emphasisEdgeLabelModel.option}},
                emphasisEdgeLabelModel.parentModel,
                ecModel
            );

            edgeData.wrapMethod('getItemModel', function (model) {
                model.customizeGetParent(edgeGetParent);
                return model;
            });

            function edgeGetParent(path) {
                path = this.parsePath(path);
                return (path && path[0] === 'label')
                    ? fakeSeriesModel
                    : (path && path[0] === 'emphasis' && path[1] === 'label')
                    ? emphasisFakeSeriesModel
                    : this.parentModel;
            }
        }
    },

    /**
     * @return {module:echarts/data/Graph}
     */
    getGraph: function () {
        return this.getData().graph;
    },

    /**
     * @return {module:echarts/data/List}
     */
    getEdgeData: function () {
        return this.getGraph().edgeData;
    },

    /**
     * @return {module:echarts/data/List}
     */
    getCategoriesData: function () {
        return this._categoriesData;
    },

    /**
     * @override
     */
    formatTooltip: function (dataIndex, multipleSeries, dataType) {
        if (dataType === 'edge') {
            var nodeData = this.getData();
            var params = this.getDataParams(dataIndex, dataType);
            var edge = nodeData.graph.getEdgeByIndex(dataIndex);
            var sourceName = nodeData.getName(edge.node1.dataIndex);
            var targetName = nodeData.getName(edge.node2.dataIndex);

            var html = [];
            sourceName != null && html.push(sourceName);
            targetName != null && html.push(targetName);
            html = encodeHTML(html.join(' > '));

            if (params.value) {
                html += ' : ' + encodeHTML(params.value);
            }
            return html;
        }
        else { // dataType === 'node' or empty
            return GraphSeries.superApply(this, 'formatTooltip', arguments);
        }
    },

    _updateCategoriesData: function () {
        var categories = map(this.option.categories || [], function (category) {
            // Data must has value
            return category.value != null ? category : extend({
                value: 0
            }, category);
        });
        var categoriesData = new List(['value'], this);
        categoriesData.initData(categories);

        this._categoriesData = categoriesData;

        this._categoriesModels = categoriesData.mapArray(function (idx) {
            return categoriesData.getItemModel(idx, true);
        });
    },

    setZoom: function (zoom) {
        this.option.zoom = zoom;
    },

    setCenter: function (center) {
        this.option.center = center;
    },

    isAnimationEnabled: function () {
        return GraphSeries.superCall(this, 'isAnimationEnabled')
            // Not enable animation when do force layout
            && !(this.get('layout') === 'force' && this.get('force.layoutAnimation'));
    },

    defaultOption: {
        zlevel: 0,
        z: 2,

        coordinateSystem: 'view',

        // Default option for all coordinate systems
        // xAxisIndex: 0,
        // yAxisIndex: 0,
        // polarIndex: 0,
        // geoIndex: 0,

        legendHoverLink: true,

        hoverAnimation: true,

        layout: null,

        focusNodeAdjacency: false,

        // Configuration of circular layout
        circular: {
            rotateLabel: false
        },
        // Configuration of force directed layout
        force: {
            initLayout: null,
            // Node repulsion. Can be an array to represent range.
            repulsion: [0, 50],
            gravity: 0.1,
            // Initial friction
            friction: 0.6,

            // Edge length. Can be an array to represent range.
            edgeLength: 30,

            layoutAnimation: true
        },

        left: 'center',
        top: 'center',
        // right: null,
        // bottom: null,
        // width: '80%',
        // height: '80%',

        symbol: 'circle',
        symbolSize: 10,

        edgeSymbol: ['none', 'none'],
        edgeSymbolSize: 10,
        edgeLabel: {
            position: 'middle'
        },

        draggable: false,

        roam: false,

        // Default on center of graph
        center: null,

        zoom: 1,
        // Symbol size scale ratio in roam
        nodeScaleRatio: 0.6,
        // cursor: null,

        // categories: [],

        // data: []
        // Or
        // nodes: []
        //
        // links: []
        // Or
        // edges: []

        label: {
            show: false,
            formatter: '{b}'
        },

        itemStyle: {},

        lineStyle: {
            color: '#aaa',
            width: 1,
            curveness: 0,
            opacity: 0.5
        },
        emphasis: {
            label: {
                show: true
            }
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Line path for bezier and straight line draw
 */

var straightLineProto = Line.prototype;
var bezierCurveProto = BezierCurve.prototype;

function isLine(shape) {
    return isNaN(+shape.cpx1) || isNaN(+shape.cpy1);
}

var LinePath = extendShape({

    type: 'ec-line',

    style: {
        stroke: '#000',
        fill: null
    },

    shape: {
        x1: 0,
        y1: 0,
        x2: 0,
        y2: 0,
        percent: 1,
        cpx1: null,
        cpy1: null
    },

    buildPath: function (ctx, shape) {
        this[isLine(shape) ? '_buildPathLine' : '_buildPathCurve'](ctx, shape);
    },
    _buildPathLine: straightLineProto.buildPath,
    _buildPathCurve: bezierCurveProto.buildPath,

    pointAt: function (t) {
        return this[isLine(this.shape) ? '_pointAtLine' : '_pointAtCurve'](t);
    },
    _pointAtLine: straightLineProto.pointAt,
    _pointAtCurve: bezierCurveProto.pointAt,

    tangentAt: function (t) {
        var shape = this.shape;
        var p = isLine(shape)
            ? [shape.x2 - shape.x1, shape.y2 - shape.y1]
            : this._tangentAtCurve(t);
        return normalize(p, p);
    },
    _tangentAtCurve: bezierCurveProto.tangentAt

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/chart/helper/Line
 */

var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol'];

function makeSymbolTypeKey(symbolCategory) {
    return '_' + symbolCategory + 'Type';
}
/**
 * @inner
 */
function createSymbol$1(name, lineData, idx) {
    var color = lineData.getItemVisual(idx, 'color');
    var symbolType = lineData.getItemVisual(idx, name);
    var symbolSize = lineData.getItemVisual(idx, name + 'Size');

    if (!symbolType || symbolType === 'none') {
        return;
    }

    if (!isArray(symbolSize)) {
        symbolSize = [symbolSize, symbolSize];
    }
    var symbolPath = createSymbol(
        symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
        symbolSize[0], symbolSize[1], color
    );

    symbolPath.name = name;

    return symbolPath;
}

function createLine(points) {
    var line = new LinePath({
        name: 'line',
        subPixelOptimize: true
    });
    setLinePoints(line.shape, points);
    return line;
}

function setLinePoints(targetShape, points) {
    targetShape.x1 = points[0][0];
    targetShape.y1 = points[0][1];
    targetShape.x2 = points[1][0];
    targetShape.y2 = points[1][1];
    targetShape.percent = 1;

    var cp1 = points[2];
    if (cp1) {
        targetShape.cpx1 = cp1[0];
        targetShape.cpy1 = cp1[1];
    }
    else {
        targetShape.cpx1 = NaN;
        targetShape.cpy1 = NaN;
    }
}

function updateSymbolAndLabelBeforeLineUpdate() {
    var lineGroup = this;
    var symbolFrom = lineGroup.childOfName('fromSymbol');
    var symbolTo = lineGroup.childOfName('toSymbol');
    var label = lineGroup.childOfName('label');
    // Quick reject
    if (!symbolFrom && !symbolTo && label.ignore) {
        return;
    }

    var invScale = 1;
    var parentNode = this.parent;
    while (parentNode) {
        if (parentNode.scale) {
            invScale /= parentNode.scale[0];
        }
        parentNode = parentNode.parent;
    }

    var line = lineGroup.childOfName('line');
    // If line not changed
    // FIXME Parent scale changed
    if (!this.__dirty && !line.__dirty) {
        return;
    }

    var percent = line.shape.percent;
    var fromPos = line.pointAt(0);
    var toPos = line.pointAt(percent);

    var d = sub([], toPos, fromPos);
    normalize(d, d);

    if (symbolFrom) {
        symbolFrom.attr('position', fromPos);
        var tangent = line.tangentAt(0);
        symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
            tangent[1], tangent[0]
        ));
        symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
    }
    if (symbolTo) {
        symbolTo.attr('position', toPos);
        var tangent = line.tangentAt(1);
        symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
            tangent[1], tangent[0]
        ));
        symbolTo.attr('scale', [invScale * percent, invScale * percent]);
    }

    if (!label.ignore) {
        label.attr('position', toPos);

        var textPosition;
        var textAlign;
        var textVerticalAlign;

        var distance$$1 = 5 * invScale;
        // End
        if (label.__position === 'end') {
            textPosition = [d[0] * distance$$1 + toPos[0], d[1] * distance$$1 + toPos[1]];
            textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
            textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
        }
        // Middle
        else if (label.__position === 'middle') {
            var halfPercent = percent / 2;
            var tangent = line.tangentAt(halfPercent);
            var n = [tangent[1], -tangent[0]];
            var cp = line.pointAt(halfPercent);
            if (n[1] > 0) {
                n[0] = -n[0];
                n[1] = -n[1];
            }
            textPosition = [cp[0] + n[0] * distance$$1, cp[1] + n[1] * distance$$1];
            textAlign = 'center';
            textVerticalAlign = 'bottom';
            var rotation = -Math.atan2(tangent[1], tangent[0]);
            if (toPos[0] < fromPos[0]) {
                rotation = Math.PI + rotation;
            }
            label.attr('rotation', rotation);
        }
        // Start
        else {
            textPosition = [-d[0] * distance$$1 + fromPos[0], -d[1] * distance$$1 + fromPos[1]];
            textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
            textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
        }
        label.attr({
            style: {
                // Use the user specified text align and baseline first
                textVerticalAlign: label.__verticalAlign || textVerticalAlign,
                textAlign: label.__textAlign || textAlign
            },
            position: textPosition,
            scale: [invScale, invScale]
        });
    }
}

/**
 * @constructor
 * @extends {module:zrender/graphic/Group}
 * @alias {module:echarts/chart/helper/Line}
 */
function Line$1(lineData, idx, seriesScope) {
    Group.call(this);

    this._createLine(lineData, idx, seriesScope);
}

var lineProto = Line$1.prototype;

// Update symbol position and rotation
lineProto.beforeUpdate = updateSymbolAndLabelBeforeLineUpdate;

lineProto._createLine = function (lineData, idx, seriesScope) {
    var seriesModel = lineData.hostModel;
    var linePoints = lineData.getItemLayout(idx);
    var line = createLine(linePoints);
    line.shape.percent = 0;
    initProps(line, {
        shape: {
            percent: 1
        }
    }, seriesModel, idx);

    this.add(line);

    var label = new Text({
        name: 'label',
        // FIXME
        // Temporary solution for `focusNodeAdjacency`.
        // line label do not use the opacity of lineStyle.
        lineLabelOriginalOpacity: 1
    });
    this.add(label);

    each$1(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbol = createSymbol$1(symbolCategory, lineData, idx);
        // symbols must added after line to make sure
        // it will be updated after line#update.
        // Or symbol position and rotation update in line#beforeUpdate will be one frame slow
        this.add(symbol);
        this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory);
    }, this);

    this._updateCommonStl(lineData, idx, seriesScope);
};

lineProto.updateData = function (lineData, idx, seriesScope) {
    var seriesModel = lineData.hostModel;

    var line = this.childOfName('line');
    var linePoints = lineData.getItemLayout(idx);
    var target = {
        shape: {}
    };

    setLinePoints(target.shape, linePoints);
    updateProps(line, target, seriesModel, idx);

    each$1(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbolType = lineData.getItemVisual(idx, symbolCategory);
        var key = makeSymbolTypeKey(symbolCategory);
        // Symbol changed
        if (this[key] !== symbolType) {
            this.remove(this.childOfName(symbolCategory));
            var symbol = createSymbol$1(symbolCategory, lineData, idx);
            this.add(symbol);
        }
        this[key] = symbolType;
    }, this);

    this._updateCommonStl(lineData, idx, seriesScope);
};

lineProto._updateCommonStl = function (lineData, idx, seriesScope) {
    var seriesModel = lineData.hostModel;

    var line = this.childOfName('line');

    var lineStyle = seriesScope && seriesScope.lineStyle;
    var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle;
    var labelModel = seriesScope && seriesScope.labelModel;
    var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel;

    // Optimization for large dataset
    if (!seriesScope || lineData.hasItemOption) {
        var itemModel = lineData.getItemModel(idx);

        lineStyle = itemModel.getModel('lineStyle').getLineStyle();
        hoverLineStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle();

        labelModel = itemModel.getModel('label');
        hoverLabelModel = itemModel.getModel('emphasis.label');
    }

    var visualColor = lineData.getItemVisual(idx, 'color');
    var visualOpacity = retrieve3(
        lineData.getItemVisual(idx, 'opacity'),
        lineStyle.opacity,
        1
    );

    line.useStyle(defaults(
        {
            strokeNoScale: true,
            fill: 'none',
            stroke: visualColor,
            opacity: visualOpacity
        },
        lineStyle
    ));
    line.hoverStyle = hoverLineStyle;

    // Update symbol
    each$1(SYMBOL_CATEGORIES, function (symbolCategory) {
        var symbol = this.childOfName(symbolCategory);
        if (symbol) {
            symbol.setColor(visualColor);
            symbol.setStyle({
                opacity: visualOpacity
            });
        }
    }, this);

    var showLabel = labelModel.getShallow('show');
    var hoverShowLabel = hoverLabelModel.getShallow('show');

    var label = this.childOfName('label');
    var defaultLabelColor;
    var baseText;

    // FIXME: the logic below probably should be merged to `graphic.setLabelStyle`.
    if (showLabel || hoverShowLabel) {
        defaultLabelColor = visualColor || '#000';

        baseText = seriesModel.getFormattedLabel(idx, 'normal', lineData.dataType);
        if (baseText == null) {
            var rawVal = seriesModel.getRawValue(idx);
            baseText = rawVal == null
                ? lineData.getName(idx)
                : isFinite(rawVal)
                ? round$1(rawVal)
                : rawVal;
        }
    }
    var normalText = showLabel ? baseText : null;
    var emphasisText = hoverShowLabel
        ? retrieve2(
            seriesModel.getFormattedLabel(idx, 'emphasis', lineData.dataType),
            baseText
        )
        : null;

    var labelStyle = label.style;

    // Always set `textStyle` even if `normalStyle.text` is null, because default
    // values have to be set on `normalStyle`.
    if (normalText != null || emphasisText != null) {
        setTextStyle(label.style, labelModel, {
            text: normalText
        }, {
            autoColor: defaultLabelColor
        });

        label.__textAlign = labelStyle.textAlign;
        label.__verticalAlign = labelStyle.textVerticalAlign;
        // 'start', 'middle', 'end'
        label.__position = labelModel.get('position') || 'middle';
    }

    if (emphasisText != null) {
        // Only these properties supported in this emphasis style here.
        label.hoverStyle = {
            text: emphasisText,
            textFill: hoverLabelModel.getTextColor(true),
            // For merging hover style to normal style, do not use
            // `hoverLabelModel.getFont()` here.
            fontStyle: hoverLabelModel.getShallow('fontStyle'),
            fontWeight: hoverLabelModel.getShallow('fontWeight'),
            fontSize: hoverLabelModel.getShallow('fontSize'),
            fontFamily: hoverLabelModel.getShallow('fontFamily')
        };
    }
    else {
        label.hoverStyle = {
            text: null
        };
    }

    label.ignore = !showLabel && !hoverShowLabel;

    setHoverStyle(this);
};

lineProto.highlight = function () {
    this.trigger('emphasis');
};

lineProto.downplay = function () {
    this.trigger('normal');
};

lineProto.updateLayout = function (lineData, idx) {
    this.setLinePoints(lineData.getItemLayout(idx));
};

lineProto.setLinePoints = function (points) {
    var linePath = this.childOfName('line');
    setLinePoints(linePath.shape, points);
    linePath.dirty();
};

inherits(Line$1, Group);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/chart/helper/LineDraw
 */

// import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';

/**
 * @alias module:echarts/component/marker/LineDraw
 * @constructor
 */
function LineDraw(ctor) {
    this._ctor = ctor || Line$1;

    this.group = new Group();
}

var lineDrawProto = LineDraw.prototype;

lineDrawProto.isPersistent = function () {
    return true;
};

/**
 * @param {module:echarts/data/List} lineData
 */
lineDrawProto.updateData = function (lineData) {
    var lineDraw = this;
    var group = lineDraw.group;

    var oldLineData = lineDraw._lineData;
    lineDraw._lineData = lineData;

    // There is no oldLineData only when first rendering or switching from
    // stream mode to normal mode, where previous elements should be removed.
    if (!oldLineData) {
        group.removeAll();
    }

    var seriesScope = makeSeriesScope$1(lineData);

    lineData.diff(oldLineData)
        .add(function (idx) {
            doAdd(lineDraw, lineData, idx, seriesScope);
        })
        .update(function (newIdx, oldIdx) {
            doUpdate(lineDraw, oldLineData, lineData, oldIdx, newIdx, seriesScope);
        })
        .remove(function (idx) {
            group.remove(oldLineData.getItemGraphicEl(idx));
        })
        .execute();
};

function doAdd(lineDraw, lineData, idx, seriesScope) {
    var itemLayout = lineData.getItemLayout(idx);

    if (!lineNeedsDraw(itemLayout)) {
        return;
    }

    var el = new lineDraw._ctor(lineData, idx, seriesScope);
    lineData.setItemGraphicEl(idx, el);
    lineDraw.group.add(el);
}

function doUpdate(lineDraw, oldLineData, newLineData, oldIdx, newIdx, seriesScope) {
    var itemEl = oldLineData.getItemGraphicEl(oldIdx);

    if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) {
        lineDraw.group.remove(itemEl);
        return;
    }

    if (!itemEl) {
        itemEl = new lineDraw._ctor(newLineData, newIdx, seriesScope);
    }
    else {
        itemEl.updateData(newLineData, newIdx, seriesScope);
    }

    newLineData.setItemGraphicEl(newIdx, itemEl);

    lineDraw.group.add(itemEl);
}

lineDrawProto.updateLayout = function () {
    var lineData = this._lineData;

    // Do not support update layout in incremental mode.
    if (!lineData) {
        return;
    }

    lineData.eachItemGraphicEl(function (el, idx) {
        el.updateLayout(lineData, idx);
    }, this);
};

lineDrawProto.incrementalPrepareUpdate = function (lineData) {
    this._seriesScope = makeSeriesScope$1(lineData);
    this._lineData = null;
    this.group.removeAll();
};

lineDrawProto.incrementalUpdate = function (taskParams, lineData) {
    function updateIncrementalAndHover(el) {
        if (!el.isGroup) {
            el.incremental = el.useHoverLayer = true;
        }
    }

    for (var idx = taskParams.start; idx < taskParams.end; idx++) {
        var itemLayout = lineData.getItemLayout(idx);

        if (lineNeedsDraw(itemLayout)) {
            var el = new this._ctor(lineData, idx, this._seriesScope);
            el.traverse(updateIncrementalAndHover);

            this.group.add(el);
            lineData.setItemGraphicEl(idx, el);
        }
    }
};

function makeSeriesScope$1(lineData) {
    var hostModel = lineData.hostModel;
    return {
        lineStyle: hostModel.getModel('lineStyle').getLineStyle(),
        hoverLineStyle: hostModel.getModel('emphasis.lineStyle').getLineStyle(),
        labelModel: hostModel.getModel('label'),
        hoverLabelModel: hostModel.getModel('emphasis.label')
    };
}

lineDrawProto.remove = function () {
    this._clearIncremental();
    this._incremental = null;
    this.group.removeAll();
};

lineDrawProto._clearIncremental = function () {
    var incremental = this._incremental;
    if (incremental) {
        incremental.clearDisplaybles();
    }
};

function isPointNaN(pt) {
    return isNaN(pt[0]) || isNaN(pt[1]);
}

function lineNeedsDraw(pts) {
    return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function getNodeGlobalScale(seriesModel) {
    var coordSys = seriesModel.coordinateSystem;
    if (coordSys.type !== 'view') {
        return 1;
    }

    var nodeScaleRatio = seriesModel.option.nodeScaleRatio;

    var groupScale = coordSys.scale;
    var groupZoom = (groupScale && groupScale[0]) || 1;
    // Scale node when zoom changes
    var roamZoom = coordSys.getZoom();
    var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;

    return nodeScale / groupZoom;
}

function getSymbolSize$1(node) {
    var symbolSize = node.getVisual('symbolSize');
    if (symbolSize instanceof Array) {
        symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
    }
    return +symbolSize;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var v1 = [];
var v2 = [];
var v3 = [];
var quadraticAt$1 = quadraticAt;
var v2DistSquare = distSquare;
var mathAbs$1 = Math.abs;
function intersectCurveCircle(curvePoints, center, radius) {
    var p0 = curvePoints[0];
    var p1 = curvePoints[1];
    var p2 = curvePoints[2];

    var d = Infinity;
    var t;
    var radiusSquare = radius * radius;
    var interval = 0.1;

    for (var _t = 0.1; _t <= 0.9; _t += 0.1) {
        v1[0] = quadraticAt$1(p0[0], p1[0], p2[0], _t);
        v1[1] = quadraticAt$1(p0[1], p1[1], p2[1], _t);
        var diff = mathAbs$1(v2DistSquare(v1, center) - radiusSquare);
        if (diff < d) {
            d = diff;
            t = _t;
        }
    }

    // Assume the segment is monotone，Find root through Bisection method
    // At most 32 iteration
    for (var i = 0; i < 32; i++) {
        // var prev = t - interval;
        var next = t + interval;
        // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev);
        // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev);
        v2[0] = quadraticAt$1(p0[0], p1[0], p2[0], t);
        v2[1] = quadraticAt$1(p0[1], p1[1], p2[1], t);
        v3[0] = quadraticAt$1(p0[0], p1[0], p2[0], next);
        v3[1] = quadraticAt$1(p0[1], p1[1], p2[1], next);

        var diff = v2DistSquare(v2, center) - radiusSquare;
        if (mathAbs$1(diff) < 1e-2) {
            break;
        }

        // var prevDiff = v2DistSquare(v1, center) - radiusSquare;
        var nextDiff = v2DistSquare(v3, center) - radiusSquare;

        interval /= 2;
        if (diff < 0) {
            if (nextDiff >= 0) {
                t = t + interval;
            }
            else {
                t = t - interval;
            }
        }
        else {
            if (nextDiff >= 0) {
                t = t - interval;
            }
            else {
                t = t + interval;
            }
        }
    }

    return t;
}

// Adjust edge to avoid
var adjustEdge = function (graph, scale$$1) {
    var tmp0 = [];
    var quadraticSubdivide$$1 = quadraticSubdivide;
    var pts = [[], [], []];
    var pts2 = [[], []];
    var v = [];
    scale$$1 /= 2;

    graph.eachEdge(function (edge, idx) {
        var linePoints = edge.getLayout();
        var fromSymbol = edge.getVisual('fromSymbol');
        var toSymbol = edge.getVisual('toSymbol');

        if (!linePoints.__original) {
            linePoints.__original = [
                clone$1(linePoints[0]),
                clone$1(linePoints[1])
            ];
            if (linePoints[2]) {
                linePoints.__original.push(clone$1(linePoints[2]));
            }
        }
        var originalPoints = linePoints.__original;
        // Quadratic curve
        if (linePoints[2] != null) {
            copy(pts[0], originalPoints[0]);
            copy(pts[1], originalPoints[2]);
            copy(pts[2], originalPoints[1]);
            if (fromSymbol && fromSymbol !== 'none') {
                var symbolSize = getSymbolSize$1(edge.node1);

                var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale$$1);
                // Subdivide and get the second
                quadraticSubdivide$$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
                pts[0][0] = tmp0[3];
                pts[1][0] = tmp0[4];
                quadraticSubdivide$$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
                pts[0][1] = tmp0[3];
                pts[1][1] = tmp0[4];
            }
            if (toSymbol && toSymbol !== 'none') {
                var symbolSize = getSymbolSize$1(edge.node2);

                var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale$$1);
                // Subdivide and get the first
                quadraticSubdivide$$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
                pts[1][0] = tmp0[1];
                pts[2][0] = tmp0[2];
                quadraticSubdivide$$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
                pts[1][1] = tmp0[1];
                pts[2][1] = tmp0[2];
            }
            // Copy back to layout
            copy(linePoints[0], pts[0]);
            copy(linePoints[1], pts[2]);
            copy(linePoints[2], pts[1]);
        }
        // Line
        else {
            copy(pts2[0], originalPoints[0]);
            copy(pts2[1], originalPoints[1]);

            sub(v, pts2[1], pts2[0]);
            normalize(v, v);
            if (fromSymbol && fromSymbol !== 'none') {

                var symbolSize = getSymbolSize$1(edge.node1);

                scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale$$1);
            }
            if (toSymbol && toSymbol !== 'none') {
                var symbolSize = getSymbolSize$1(edge.node2);

                scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale$$1);
            }
            copy(linePoints[0], pts2[0]);
            copy(linePoints[1], pts2[1]);
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var FOCUS_ADJACENCY = '__focusNodeAdjacency';
var UNFOCUS_ADJACENCY = '__unfocusNodeAdjacency';

var nodeOpacityPath = ['itemStyle', 'opacity'];
var lineOpacityPath = ['lineStyle', 'opacity'];

function getItemOpacity(item, opacityPath) {
    var opacity = item.getVisual('opacity');
    return opacity != null ? opacity : item.getModel().get(opacityPath);
}

function fadeOutItem(item, opacityPath, opacityRatio) {
    var el = item.getGraphicEl();
    var opacity = getItemOpacity(item, opacityPath);

    if (opacityRatio != null) {
        opacity == null && (opacity = 1);
        opacity *= opacityRatio;
    }

    el.downplay && el.downplay();
    el.traverse(function (child) {
        if (!child.isGroup) {
            var opct = child.lineLabelOriginalOpacity;
            if (opct == null || opacityRatio != null) {
                opct = opacity;
            }
            child.setStyle('opacity', opct);
        }
    });
}

function fadeInItem(item, opacityPath) {
    var opacity = getItemOpacity(item, opacityPath);
    var el = item.getGraphicEl();
    // Should go back to normal opacity first, consider hoverLayer,
    // where current state is copied to elMirror, and support
    // emphasis opacity here.
    el.traverse(function (child) {
        !child.isGroup && child.setStyle('opacity', opacity);
    });
    el.highlight && el.highlight();
}

extendChartView({

    type: 'graph',

    init: function (ecModel, api) {
        var symbolDraw = new SymbolDraw();
        var lineDraw = new LineDraw();
        var group = this.group;

        this._controller = new RoamController(api.getZr());
        this._controllerHost = {target: group};

        group.add(symbolDraw.group);
        group.add(lineDraw.group);

        this._symbolDraw = symbolDraw;
        this._lineDraw = lineDraw;

        this._firstRender = true;
    },

    render: function (seriesModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;

        this._model = seriesModel;

        var symbolDraw = this._symbolDraw;
        var lineDraw = this._lineDraw;

        var group = this.group;

        if (coordSys.type === 'view') {
            var groupNewProp = {
                position: coordSys.position,
                scale: coordSys.scale
            };
            if (this._firstRender) {
                group.attr(groupNewProp);
            }
            else {
                updateProps(group, groupNewProp, seriesModel);
            }
        }
        // Fix edge contact point with node
        adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));

        var data = seriesModel.getData();
        symbolDraw.updateData(data);

        var edgeData = seriesModel.getEdgeData();
        lineDraw.updateData(edgeData);

        this._updateNodeAndLinkScale();

        this._updateController(seriesModel, ecModel, api);

        clearTimeout(this._layoutTimeout);
        var forceLayout = seriesModel.forceLayout;
        var layoutAnimation = seriesModel.get('force.layoutAnimation');
        if (forceLayout) {
            this._startForceLayoutIteration(forceLayout, layoutAnimation);
        }

        data.eachItemGraphicEl(function (el, idx) {
            var itemModel = data.getItemModel(idx);
            // Update draggable
            el.off('drag').off('dragend');
            var draggable = itemModel.get('draggable');
            if (draggable) {
                el.on('drag', function () {
                    if (forceLayout) {
                        forceLayout.warmUp();
                        !this._layouting
                            && this._startForceLayoutIteration(forceLayout, layoutAnimation);
                        forceLayout.setFixed(idx);
                        // Write position back to layout
                        data.setItemLayout(idx, el.position);
                    }
                }, this).on('dragend', function () {
                    if (forceLayout) {
                        forceLayout.setUnfixed(idx);
                    }
                }, this);
            }
            el.setDraggable(draggable && forceLayout);

            el[FOCUS_ADJACENCY] && el.off('mouseover', el[FOCUS_ADJACENCY]);
            el[UNFOCUS_ADJACENCY] && el.off('mouseout', el[UNFOCUS_ADJACENCY]);

            if (itemModel.get('focusNodeAdjacency')) {
                el.on('mouseover', el[FOCUS_ADJACENCY] = function () {
                    api.dispatchAction({
                        type: 'focusNodeAdjacency',
                        seriesId: seriesModel.id,
                        dataIndex: el.dataIndex
                    });
                });
                el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () {
                    api.dispatchAction({
                        type: 'unfocusNodeAdjacency',
                        seriesId: seriesModel.id
                    });
                });
            }

        }, this);

        data.graph.eachEdge(function (edge) {
            var el = edge.getGraphicEl();

            el[FOCUS_ADJACENCY] && el.off('mouseover', el[FOCUS_ADJACENCY]);
            el[UNFOCUS_ADJACENCY] && el.off('mouseout', el[UNFOCUS_ADJACENCY]);

            if (edge.getModel().get('focusNodeAdjacency')) {
                el.on('mouseover', el[FOCUS_ADJACENCY] = function () {
                    api.dispatchAction({
                        type: 'focusNodeAdjacency',
                        seriesId: seriesModel.id,
                        edgeDataIndex: edge.dataIndex
                    });
                });
                el.on('mouseout', el[UNFOCUS_ADJACENCY] = function () {
                    api.dispatchAction({
                        type: 'unfocusNodeAdjacency',
                        seriesId: seriesModel.id
                    });
                });
            }
        });

        var circularRotateLabel = seriesModel.get('layout') === 'circular'
            && seriesModel.get('circular.rotateLabel');
        var cx = data.getLayout('cx');
        var cy = data.getLayout('cy');
        data.eachItemGraphicEl(function (el, idx) {
            var itemModel = data.getItemModel(idx);
            var labelRotate = itemModel.get('label.rotate') || 0;
            var symbolPath = el.getSymbolPath();
            if (circularRotateLabel) {
                var pos = data.getItemLayout(idx);
                var rad = Math.atan2(pos[1] - cy, pos[0] - cx);
                if (rad < 0) {
                    rad = Math.PI * 2 + rad;
                }
                var isLeft = pos[0] < cx;
                if (isLeft) {
                    rad = rad - Math.PI;
                }
                var textPosition = isLeft ? 'left' : 'right';
                modifyLabelStyle(
                    symbolPath,
                    {
                        textRotation: -rad,
                        textPosition: textPosition,
                        textOrigin: 'center'
                    },
                    {
                        textPosition: textPosition
                    }
                );
            }
            else {
                modifyLabelStyle(
                    symbolPath,
                    {
                        textRotation: labelRotate *= Math.PI / 180
                    }
                );
            }
        });

        this._firstRender = false;
    },

    dispose: function () {
        this._controller && this._controller.dispose();
        this._controllerHost = {};
    },

    focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var data = this._model.getData();
        var graph = data.graph;
        var dataIndex = payload.dataIndex;
        var edgeDataIndex = payload.edgeDataIndex;

        var node = graph.getNodeByIndex(dataIndex);
        var edge = graph.getEdgeByIndex(edgeDataIndex);

        if (!node && !edge) {
            return;
        }

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath, 0.1);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath, 0.1);
        });

        if (node) {
            fadeInItem(node, nodeOpacityPath);
            each$1(node.edges, function (adjacentEdge) {
                if (adjacentEdge.dataIndex < 0) {
                    return;
                }
                fadeInItem(adjacentEdge, lineOpacityPath);
                fadeInItem(adjacentEdge.node1, nodeOpacityPath);
                fadeInItem(adjacentEdge.node2, nodeOpacityPath);
            });
        }
        if (edge) {
            fadeInItem(edge, lineOpacityPath);
            fadeInItem(edge.node1, nodeOpacityPath);
            fadeInItem(edge.node2, nodeOpacityPath);
        }
    },

    unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var graph = this._model.getData().graph;

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath);
        });
    },

    _startForceLayoutIteration: function (forceLayout, layoutAnimation) {
        var self = this;
        (function step() {
            forceLayout.step(function (stopped) {
                self.updateLayout(self._model);
                (self._layouting = !stopped) && (
                    layoutAnimation
                        ? (self._layoutTimeout = setTimeout(step, 16))
                        : step()
                );
            });
        })();
    },

    _updateController: function (seriesModel, ecModel, api) {
        var controller = this._controller;
        var controllerHost = this._controllerHost;
        var group = this.group;

        controller.setPointerChecker(function (e, x, y) {
            var rect = group.getBoundingRect();
            rect.applyTransform(group.transform);
            return rect.contain(x, y)
                && !onIrrelevantElement(e, api, seriesModel);
        });

        if (seriesModel.coordinateSystem.type !== 'view') {
            controller.disable();
            return;
        }
        controller.enable(seriesModel.get('roam'));
        controllerHost.zoomLimit = seriesModel.get('scaleLimit');
        controllerHost.zoom = seriesModel.coordinateSystem.getZoom();

        controller
            .off('pan')
            .off('zoom')
            .on('pan', function (e) {
                updateViewOnPan(controllerHost, e.dx, e.dy);
                api.dispatchAction({
                    seriesId: seriesModel.id,
                    type: 'graphRoam',
                    dx: e.dx,
                    dy: e.dy
                });
            })
            .on('zoom', function (e) {
                updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
                api.dispatchAction({
                    seriesId: seriesModel.id,
                    type: 'graphRoam',
                    zoom: e.scale,
                    originX: e.originX,
                    originY: e.originY
                });
                this._updateNodeAndLinkScale();
                adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));
                this._lineDraw.updateLayout();
            }, this);
    },

    _updateNodeAndLinkScale: function () {
        var seriesModel = this._model;
        var data = seriesModel.getData();

        var nodeScale = getNodeGlobalScale(seriesModel);
        var invScale = [nodeScale, nodeScale];

        data.eachItemGraphicEl(function (el, idx) {
            el.attr('scale', invScale);
        });
    },

    updateLayout: function (seriesModel) {
        adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel));

        this._symbolDraw.updateLayout();
        this._lineDraw.updateLayout();
    },

    remove: function (ecModel, api) {
        this._symbolDraw && this._symbolDraw.remove();
        this._lineDraw && this._lineDraw.remove();
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @payload
 * @property {number} [seriesIndex]
 * @property {string} [seriesId]
 * @property {string} [seriesName]
 * @property {number} [dataIndex]
 */
registerAction({
    type: 'focusNodeAdjacency',
    event: 'focusNodeAdjacency',
    update: 'series:focusNodeAdjacency'
}, function () {});

/**
 * @payload
 * @property {number} [seriesIndex]
 * @property {string} [seriesId]
 * @property {string} [seriesName]
 */
registerAction({
    type: 'unfocusNodeAdjacency',
    event: 'unfocusNodeAdjacency',
    update: 'series:unfocusNodeAdjacency'
}, function () {});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var actionInfo = {
    type: 'graphRoam',
    event: 'graphRoam',
    update: 'none'
};

/**
 * @payload
 * @property {string} name Series name
 * @property {number} [dx]
 * @property {number} [dy]
 * @property {number} [zoom]
 * @property {number} [originX]
 * @property {number} [originY]
 */
registerAction(actionInfo, function (payload, ecModel) {
    ecModel.eachComponent({mainType: 'series', query: payload}, function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;

        var res = updateCenterAndZoom(coordSys, payload);

        seriesModel.setCenter
            && seriesModel.setCenter(res.center);

        seriesModel.setZoom
            && seriesModel.setZoom(res.zoom);
    });
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var categoryFilter = function (ecModel) {
    var legendModels = ecModel.findComponents({
        mainType: 'legend'
    });
    if (!legendModels || !legendModels.length) {
        return;
    }
    ecModel.eachSeriesByType('graph', function (graphSeries) {
        var categoriesData = graphSeries.getCategoriesData();
        var graph = graphSeries.getGraph();
        var data = graph.data;

        var categoryNames = categoriesData.mapArray(categoriesData.getName);

        data.filterSelf(function (idx) {
            var model = data.getItemModel(idx);
            var category = model.getShallow('category');
            if (category != null) {
                if (typeof category === 'number') {
                    category = categoryNames[category];
                }
                // If in any legend component the status is not selected.
                for (var i = 0; i < legendModels.length; i++) {
                    if (!legendModels[i].isSelected(category)) {
                        return false;
                    }
                }
            }
            return true;
        });
    }, this);
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var categoryVisual = function (ecModel) {

    var paletteScope = {};
    ecModel.eachSeriesByType('graph', function (seriesModel) {
        var categoriesData = seriesModel.getCategoriesData();
        var data = seriesModel.getData();

        var categoryNameIdxMap = {};

        categoriesData.each(function (idx) {
            var name = categoriesData.getName(idx);
            // Add prefix to avoid conflict with Object.prototype.
            categoryNameIdxMap['ec-' + name] = idx;
            var itemModel = categoriesData.getItemModel(idx);

            var color = itemModel.get('itemStyle.color')
                || seriesModel.getColorFromPalette(name, paletteScope);
            categoriesData.setItemVisual(idx, 'color', color);

            var itemStyleList = ['opacity', 'symbol', 'symbolSize', 'symbolKeepAspect'];
            for (var i = 0; i < itemStyleList.length; i++) {
                var itemStyle = itemModel.getShallow(itemStyleList[i], true);
                if (itemStyle != null) {
                    categoriesData.setItemVisual(idx, itemStyleList[i], itemStyle);
                }
            }
        });

        // Assign category color to visual
        if (categoriesData.count()) {
            data.each(function (idx) {
                var model = data.getItemModel(idx);
                var category = model.getShallow('category');
                if (category != null) {
                    if (typeof category === 'string') {
                        category = categoryNameIdxMap['ec-' + category];
                    }

                    var itemStyleList = ['color', 'opacity', 'symbol', 'symbolSize', 'symbolKeepAspect'];

                    for (var i = 0; i < itemStyleList.length; i++) {
                        if (data.getItemVisual(idx, itemStyleList[i], true) == null) {
                            data.setItemVisual(
                                idx, itemStyleList[i],
                                categoriesData.getItemVisual(category, itemStyleList[i])
                            );
                        }
                    }
                }
            });
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


function normalize$1(a) {
    if (!(a instanceof Array)) {
        a = [a, a];
    }
    return a;
}

var edgeVisual = function (ecModel) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
        var graph = seriesModel.getGraph();
        var edgeData = seriesModel.getEdgeData();
        var symbolType = normalize$1(seriesModel.get('edgeSymbol'));
        var symbolSize = normalize$1(seriesModel.get('edgeSymbolSize'));

        var colorQuery = 'lineStyle.color'.split('.');
        var opacityQuery = 'lineStyle.opacity'.split('.');

        edgeData.setVisual('fromSymbol', symbolType && symbolType[0]);
        edgeData.setVisual('toSymbol', symbolType && symbolType[1]);
        edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
        edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
        edgeData.setVisual('color', seriesModel.get(colorQuery));
        edgeData.setVisual('opacity', seriesModel.get(opacityQuery));

        edgeData.each(function (idx) {
            var itemModel = edgeData.getItemModel(idx);
            var edge = graph.getEdgeByIndex(idx);
            var symbolType = normalize$1(itemModel.getShallow('symbol', true));
            var symbolSize = normalize$1(itemModel.getShallow('symbolSize', true));
            // Edge visual must after node visual
            var color = itemModel.get(colorQuery);
            var opacity = itemModel.get(opacityQuery);
            switch (color) {
                case 'source':
                    color = edge.node1.getVisual('color');
                    break;
                case 'target':
                    color = edge.node2.getVisual('color');
                    break;
            }

            symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]);
            symbolType[1] && edge.setVisual('toSymbol', symbolType[1]);
            symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]);
            symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]);

            edge.setVisual('color', color);
            edge.setVisual('opacity', opacity);
        });
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function simpleLayout$1(seriesModel) {
    var coordSys = seriesModel.coordinateSystem;
    if (coordSys && coordSys.type !== 'view') {
        return;
    }
    var graph = seriesModel.getGraph();

    graph.eachNode(function (node) {
        var model = node.getModel();
        node.setLayout([+model.get('x'), +model.get('y')]);
    });

    simpleLayoutEdge(graph);
}

function simpleLayoutEdge(graph) {
    graph.eachEdge(function (edge) {
        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
        var p1 = clone$1(edge.node1.getLayout());
        var p2 = clone$1(edge.node2.getLayout());
        var points = [p1, p2];
        if (+curveness) {
            points.push([
                (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness,
                (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness
            ]);
        }
        edge.setLayout(points);
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var simpleLayout = function (ecModel, api) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
        var layout = seriesModel.get('layout');
        var coordSys = seriesModel.coordinateSystem;
        if (coordSys && coordSys.type !== 'view') {
            var data = seriesModel.getData();

            var dimensions = [];
            each$1(coordSys.dimensions, function (coordDim) {
                dimensions = dimensions.concat(data.mapDimension(coordDim, true));
            });

            for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) {
                var value = [];
                var hasValue = false;
                for (var i = 0; i < dimensions.length; i++) {
                    var val = data.get(dimensions[i], dataIndex);
                    if (!isNaN(val)) {
                        hasValue = true;
                    }
                    value.push(val);
                }
                if (hasValue) {
                    data.setItemLayout(dataIndex, coordSys.dataToPoint(value));
                }
                else {
                    // Also {Array.<number>}, not undefined to avoid if...else... statement
                    data.setItemLayout(dataIndex, [NaN, NaN]);
                }
            }

            simpleLayoutEdge(data.graph);
        }
        else if (!layout || layout === 'none') {
            simpleLayout$1(seriesModel);
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PI$3 = Math.PI;

var _symbolRadiansHalf = [];

/**
 * `basedOn` can be:
 * 'value':
 *     This layout is not accurate and have same bad case. For example,
 *     if the min value is very smaller than the max value, the nodes
 *     with the min value probably overlap even though there is enough
 *     space to layout them. So we only use this approach in the as the
 *     init layout of the force layout.
 *     FIXME
 *     Probably we do not need this method any more but use
 *     `basedOn: 'symbolSize'` in force layout if
 *     delay its init operations to GraphView.
 * 'symbolSize':
 *     This approach work only if all of the symbol size calculated.
 *     That is, the progressive rendering is not applied to graph.
 *     FIXME
 *     If progressive rendering is applied to graph some day,
 *     probably we have to use `basedOn: 'value'`.
 *
 * @param {module:echarts/src/model/Series} seriesModel
 * @param {string} basedOn 'value' or 'symbolSize'
 */
function circularLayout$1(seriesModel, basedOn) {
    var coordSys = seriesModel.coordinateSystem;
    if (coordSys && coordSys.type !== 'view') {
        return;
    }

    var rect = coordSys.getBoundingRect();

    var nodeData = seriesModel.getData();
    var graph = nodeData.graph;

    var cx = rect.width / 2 + rect.x;
    var cy = rect.height / 2 + rect.y;
    var r = Math.min(rect.width, rect.height) / 2;
    var count = nodeData.count();

    nodeData.setLayout({
        cx: cx,
        cy: cy
    });

    if (!count) {
        return;
    }

    _layoutNodesBasedOn[basedOn](seriesModel, coordSys, graph, nodeData, r, cx, cy, count);

    graph.eachEdge(function (edge) {
        var curveness = edge.getModel().get('lineStyle.curveness') || 0;
        var p1 = clone$1(edge.node1.getLayout());
        var p2 = clone$1(edge.node2.getLayout());
        var cp1;
        var x12 = (p1[0] + p2[0]) / 2;
        var y12 = (p1[1] + p2[1]) / 2;
        if (+curveness) {
            curveness *= 3;
            cp1 = [
                cx * curveness + x12 * (1 - curveness),
                cy * curveness + y12 * (1 - curveness)
            ];
        }
        edge.setLayout([p1, p2, cp1]);
    });
}

var _layoutNodesBasedOn = {

    value: function (seriesModel, coordSys, graph, nodeData, r, cx, cy, count) {
        var angle = 0;
        var sum = nodeData.getSum('value');
        var unitAngle = Math.PI * 2 / (sum || count);

        graph.eachNode(function (node) {
            var value = node.getValue('value');
            var radianHalf = unitAngle * (sum ? value : 1) / 2;

            angle += radianHalf;
            node.setLayout([
                r * Math.cos(angle) + cx,
                r * Math.sin(angle) + cy
            ]);
            angle += radianHalf;
        });
    },

    symbolSize: function (seriesModel, coordSys, graph, nodeData, r, cx, cy, count) {
        var sumRadian = 0;
        _symbolRadiansHalf.length = count;

        var nodeScale = getNodeGlobalScale(seriesModel);

        graph.eachNode(function (node) {
            var symbolSize = getSymbolSize$1(node);

            // Normally this case will not happen, but we still add
            // some the defensive code (2px is an arbitrary value).
            isNaN(symbolSize) && (symbolSize = 2);
            symbolSize < 0 && (symbolSize = 0);

            symbolSize *= nodeScale;

            var symbolRadianHalf = Math.asin(symbolSize / 2 / r);
            // when `symbolSize / 2` is bigger than `r`.
            isNaN(symbolRadianHalf) && (symbolRadianHalf = PI$3 / 2);
            _symbolRadiansHalf[node.dataIndex] = symbolRadianHalf;
            sumRadian += symbolRadianHalf * 2;
        });

        var halfRemainRadian = (2 * PI$3 - sumRadian) / count / 2;

        var angle = 0;
        graph.eachNode(function (node) {
            var radianHalf = halfRemainRadian + _symbolRadiansHalf[node.dataIndex];

            angle += radianHalf;
            node.setLayout([
                r * Math.cos(angle) + cx,
                r * Math.sin(angle) + cy
            ]);
            angle += radianHalf;
        });
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var circularLayout = function (ecModel) {
    ecModel.eachSeriesByType('graph', function (seriesModel) {
        if (seriesModel.get('layout') === 'circular') {
            circularLayout$1(seriesModel, 'symbolSize');
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* A third-party license is embeded for some of the code in this file:
* Some formulas were originally copied from "d3.js" with some
* modifications made for this project.
* (See more details in the comment of the method "step" below.)
* The use of the source code of this file is also subject to the terms
* and consitions of the license of "d3.js" (BSD-3Clause, see
* </licenses/LICENSE-d3>).
*/

var scaleAndAdd$2 = scaleAndAdd;

// function adjacentNode(n, e) {
//     return e.n1 === n ? e.n2 : e.n1;
// }

function forceLayout$1(nodes, edges, opts) {
    var rect = opts.rect;
    var width = rect.width;
    var height = rect.height;
    var center = [rect.x + width / 2, rect.y + height / 2];
    // var scale = opts.scale || 1;
    var gravity = opts.gravity == null ? 0.1 : opts.gravity;

    // for (var i = 0; i < edges.length; i++) {
    //     var e = edges[i];
    //     var n1 = e.n1;
    //     var n2 = e.n2;
    //     n1.edges = n1.edges || [];
    //     n2.edges = n2.edges || [];
    //     n1.edges.push(e);
    //     n2.edges.push(e);
    // }
    // Init position
    for (var i = 0; i < nodes.length; i++) {
        var n = nodes[i];
        if (!n.p) {
            n.p = create(
                width * (Math.random() - 0.5) + center[0],
                height * (Math.random() - 0.5) + center[1]
            );
        }
        n.pp = clone$1(n.p);
        n.edges = null;
    }

    // Formula in 'Graph Drawing by Force-directed Placement'
    // var k = scale * Math.sqrt(width * height / nodes.length);
    // var k2 = k * k;

    var initialFriction = opts.friction == null ? 0.6 : opts.friction;
    var friction = initialFriction;

    return {
        warmUp: function () {
            friction = initialFriction * 0.8;
        },

        setFixed: function (idx) {
            nodes[idx].fixed = true;
        },

        setUnfixed: function (idx) {
            nodes[idx].fixed = false;
        },

        /**
         * Some formulas were originally copied from "d3.js"
         * https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/layout/force.js
         * with some modifications made for this project.
         * See the license statement at the head of this file.
         */
        step: function (cb) {
            var v12 = [];
            var nLen = nodes.length;
            for (var i = 0; i < edges.length; i++) {
                var e = edges[i];
                if (e.ignoreForceLayout) {
                    continue;
                }
                var n1 = e.n1;
                var n2 = e.n2;

                sub(v12, n2.p, n1.p);
                var d = len(v12) - e.d;
                var w = n2.w / (n1.w + n2.w);

                if (isNaN(w)) {
                    w = 0;
                }

                normalize(v12, v12);

                !n1.fixed && scaleAndAdd$2(n1.p, n1.p, v12, w * d * friction);
                !n2.fixed && scaleAndAdd$2(n2.p, n2.p, v12, -(1 - w) * d * friction);
            }
            // Gravity
            for (var i = 0; i < nLen; i++) {
                var n = nodes[i];
                if (!n.fixed) {
                    sub(v12, center, n.p);
                    // var d = vec2.len(v12);
                    // vec2.scale(v12, v12, 1 / d);
                    // var gravityFactor = gravity;
                    scaleAndAdd$2(n.p, n.p, v12, gravity * friction);
                }
            }

            // Repulsive
            // PENDING
            for (var i = 0; i < nLen; i++) {
                var n1 = nodes[i];
                for (var j = i + 1; j < nLen; j++) {
                    var n2 = nodes[j];
                    sub(v12, n2.p, n1.p);
                    var d = len(v12);
                    if (d === 0) {
                        // Random repulse
                        set(v12, Math.random() - 0.5, Math.random() - 0.5);
                        d = 1;
                    }
                    var repFact = (n1.rep + n2.rep) / d / d;
                    !n1.fixed && scaleAndAdd$2(n1.pp, n1.pp, v12, repFact);
                    !n2.fixed && scaleAndAdd$2(n2.pp, n2.pp, v12, -repFact);
                }
            }
            var v = [];
            for (var i = 0; i < nLen; i++) {
                var n = nodes[i];
                if (!n.fixed) {
                    sub(v, n.p, n.pp);
                    scaleAndAdd$2(n.p, n.p, v, friction);
                    copy(n.pp, n.p);
                }
            }

            friction = friction * 0.992;

            cb && cb(nodes, edges, friction < 0.01);
        }
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var forceLayout = function (ecModel) {
    ecModel.eachSeriesByType('graph', function (graphSeries) {
        var coordSys = graphSeries.coordinateSystem;
        if (coordSys && coordSys.type !== 'view') {
            return;
        }
        if (graphSeries.get('layout') === 'force') {
            var preservedPoints = graphSeries.preservedPoints || {};
            var graph = graphSeries.getGraph();
            var nodeData = graph.data;
            var edgeData = graph.edgeData;
            var forceModel = graphSeries.getModel('force');
            var initLayout = forceModel.get('initLayout');
            if (graphSeries.preservedPoints) {
                nodeData.each(function (idx) {
                    var id = nodeData.getId(idx);
                    nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]);
                });
            }
            else if (!initLayout || initLayout === 'none') {
                simpleLayout$1(graphSeries);
            }
            else if (initLayout === 'circular') {
                circularLayout$1(graphSeries, 'value');
            }

            var nodeDataExtent = nodeData.getDataExtent('value');
            var edgeDataExtent = edgeData.getDataExtent('value');
            // var edgeDataExtent = edgeData.getDataExtent('value');
            var repulsion = forceModel.get('repulsion');
            var edgeLength = forceModel.get('edgeLength');
            if (!isArray(repulsion)) {
                repulsion = [repulsion, repulsion];
            }
            if (!isArray(edgeLength)) {
                edgeLength = [edgeLength, edgeLength];
            }
            // Larger value has smaller length
            edgeLength = [edgeLength[1], edgeLength[0]];

            var nodes = nodeData.mapArray('value', function (value, idx) {
                var point = nodeData.getItemLayout(idx);
                var rep = linearMap(value, nodeDataExtent, repulsion);
                if (isNaN(rep)) {
                    rep = (repulsion[0] + repulsion[1]) / 2;
                }
                return {
                    w: rep,
                    rep: rep,
                    fixed: nodeData.getItemModel(idx).get('fixed'),
                    p: (!point || isNaN(point[0]) || isNaN(point[1])) ? null : point
                };
            });
            var edges = edgeData.mapArray('value', function (value, idx) {
                var edge = graph.getEdgeByIndex(idx);
                var d = linearMap(value, edgeDataExtent, edgeLength);
                if (isNaN(d)) {
                    d = (edgeLength[0] + edgeLength[1]) / 2;
                }
                var edgeModel = edge.getModel();
                return {
                    n1: nodes[edge.node1.dataIndex],
                    n2: nodes[edge.node2.dataIndex],
                    d: d,
                    curveness: edgeModel.get('lineStyle.curveness') || 0,
                    ignoreForceLayout: edgeModel.get('ignoreForceLayout')
                };
            });

            var coordSys = graphSeries.coordinateSystem;
            var rect = coordSys.getBoundingRect();
            var forceInstance = forceLayout$1(nodes, edges, {
                rect: rect,
                gravity: forceModel.get('gravity'),
                friction: forceModel.get('friction')
            });
            var oldStep = forceInstance.step;
            forceInstance.step = function (cb) {
                for (var i = 0, l = nodes.length; i < l; i++) {
                    if (nodes[i].fixed) {
                        // Write back to layout instance
                        copy(nodes[i].p, graph.getNodeByIndex(i).getLayout());
                    }
                }
                oldStep(function (nodes, edges, stopped) {
                    for (var i = 0, l = nodes.length; i < l; i++) {
                        if (!nodes[i].fixed) {
                            graph.getNodeByIndex(i).setLayout(nodes[i].p);
                        }
                        preservedPoints[nodeData.getId(i)] = nodes[i].p;
                    }
                    for (var i = 0, l = edges.length; i < l; i++) {
                        var e = edges[i];
                        var edge = graph.getEdgeByIndex(i);
                        var p1 = e.n1.p;
                        var p2 = e.n2.p;
                        var points = edge.getLayout();
                        points = points ? points.slice() : [];
                        points[0] = points[0] || [];
                        points[1] = points[1] || [];
                        copy(points[0], p1);
                        copy(points[1], p2);
                        if (+e.curveness) {
                            points[2] = [
                                (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness,
                                (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness
                            ];
                        }
                        edge.setLayout(points);
                    }
                    // Update layout

                    cb && cb(stopped);
                });
            };
            graphSeries.forceLayout = forceInstance;
            graphSeries.preservedPoints = preservedPoints;

            // Step to get the layout
            forceInstance.step();
        }
        else {
            // Remove prev injected forceLayout instance
            graphSeries.forceLayout = null;
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME Where to create the simple view coordinate system
function getViewRect$1(seriesModel, api, aspect) {
    var option = seriesModel.getBoxLayoutParams();
    option.aspect = aspect;
    return getLayoutRect(option, {
        width: api.getWidth(),
        height: api.getHeight()
    });
}

var createView = function (ecModel, api) {
    var viewList = [];
    ecModel.eachSeriesByType('graph', function (seriesModel) {
        var coordSysType = seriesModel.get('coordinateSystem');
        if (!coordSysType || coordSysType === 'view') {

            var data = seriesModel.getData();
            var positions = data.mapArray(function (idx) {
                var itemModel = data.getItemModel(idx);
                return [+itemModel.get('x'), +itemModel.get('y')];
            });

            var min = [];
            var max = [];

            fromPoints(positions, min, max);

            // If width or height is 0
            if (max[0] - min[0] === 0) {
                max[0] += 1;
                min[0] -= 1;
            }
            if (max[1] - min[1] === 0) {
                max[1] += 1;
                min[1] -= 1;
            }
            var aspect = (max[0] - min[0]) / (max[1] - min[1]);
            // FIXME If get view rect after data processed?
            var viewRect = getViewRect$1(seriesModel, api, aspect);
            // Position may be NaN, use view rect instead
            if (isNaN(aspect)) {
                min = [viewRect.x, viewRect.y];
                max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height];
            }

            var bbWidth = max[0] - min[0];
            var bbHeight = max[1] - min[1];

            var viewWidth = viewRect.width;
            var viewHeight = viewRect.height;

            var viewCoordSys = seriesModel.coordinateSystem = new View();
            viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');

            viewCoordSys.setBoundingRect(
                min[0], min[1], bbWidth, bbHeight
            );
            viewCoordSys.setViewRect(
                viewRect.x, viewRect.y, viewWidth, viewHeight
            );

            // Update roam info
            viewCoordSys.setCenter(seriesModel.get('center'));
            viewCoordSys.setZoom(seriesModel.get('zoom'));

            viewList.push(viewCoordSys);
        }
    });

    return viewList;
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerProcessor(categoryFilter);

registerVisual(visualSymbol('graph', 'circle', null));
registerVisual(categoryVisual);
registerVisual(edgeVisual);

registerLayout(simpleLayout);
registerLayout(PRIORITY.VISUAL.POST_CHART_LAYOUT, circularLayout);
registerLayout(forceLayout);

// Graph view coordinate system
registerCoordinateSystem('graphView', {
    create: createView
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var GaugeSeries = SeriesModel.extend({

    type: 'series.gauge',

    getInitialData: function (option, ecModel) {
        return createListSimply(this, ['value']);
    },

    defaultOption: {
        zlevel: 0,
        z: 2,
        // 默认全局居中
        center: ['50%', '50%'],
        legendHoverLink: true,
        radius: '75%',
        startAngle: 225,
        endAngle: -45,
        clockwise: true,
        // 最小值
        min: 0,
        // 最大值
        max: 100,
        // 分割段数，默认为10
        splitNumber: 10,
        // 坐标轴线
        axisLine: {
            // 默认显示，属性show控制显示与否
            show: true,
            lineStyle: {       // 属性lineStyle控制线条样式
                color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']],
                width: 30
            }
        },
        // 分隔线
        splitLine: {
            // 默认显示，属性show控制显示与否
            show: true,
            // 属性length控制线长
            length: 30,
            // 属性lineStyle（详见lineStyle）控制线条样式
            lineStyle: {
                color: '#eee',
                width: 2,
                type: 'solid'
            }
        },
        // 坐标轴小标记
        axisTick: {
            // 属性show控制显示与否，默认不显示
            show: true,
            // 每份split细分多少段
            splitNumber: 5,
            // 属性length控制线长
            length: 8,
            // 属性lineStyle控制线条样式
            lineStyle: {
                color: '#eee',
                width: 1,
                type: 'solid'
            }
        },
        axisLabel: {
            show: true,
            distance: 5,
            // formatter: null,
            color: 'auto'
        },
        pointer: {
            show: true,
            length: '80%',
            width: 8
        },
        itemStyle: {
            color: 'auto'
        },
        title: {
            show: true,
            // x, y，单位px
            offsetCenter: [0, '-40%'],
            // 其余属性默认使用全局文本样式，详见TEXTSTYLE
            color: '#333',
            fontSize: 15
        },
        detail: {
            show: true,
            backgroundColor: 'rgba(0,0,0,0)',
            borderWidth: 0,
            borderColor: '#ccc',
            width: 100,
            height: null, // self-adaption
            padding: [5, 10],
            // x, y，单位px
            offsetCenter: [0, '40%'],
            // formatter: null,
            // 其余属性默认使用全局文本样式，详见TEXTSTYLE
            color: 'auto',
            fontSize: 30
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PointerPath = Path.extend({

    type: 'echartsGaugePointer',

    shape: {
        angle: 0,

        width: 10,

        r: 10,

        x: 0,

        y: 0
    },

    buildPath: function (ctx, shape) {
        var mathCos = Math.cos;
        var mathSin = Math.sin;

        var r = shape.r;
        var width = shape.width;
        var angle = shape.angle;
        var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2);
        var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2);

        angle = shape.angle - Math.PI / 2;
        ctx.moveTo(x, y);
        ctx.lineTo(
            shape.x + mathCos(angle) * width,
            shape.y + mathSin(angle) * width
        );
        ctx.lineTo(
            shape.x + mathCos(shape.angle) * r,
            shape.y + mathSin(shape.angle) * r
        );
        ctx.lineTo(
            shape.x - mathCos(angle) * width,
            shape.y - mathSin(angle) * width
        );
        ctx.lineTo(x, y);
        return;
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function parsePosition(seriesModel, api) {
    var center = seriesModel.get('center');
    var width = api.getWidth();
    var height = api.getHeight();
    var size = Math.min(width, height);
    var cx = parsePercent$1(center[0], api.getWidth());
    var cy = parsePercent$1(center[1], api.getHeight());
    var r = parsePercent$1(seriesModel.get('radius'), size / 2);

    return {
        cx: cx,
        cy: cy,
        r: r
    };
}

function formatLabel(label, labelFormatter) {
    if (labelFormatter) {
        if (typeof labelFormatter === 'string') {
            label = labelFormatter.replace('{value}', label != null ? label : '');
        }
        else if (typeof labelFormatter === 'function') {
            label = labelFormatter(label);
        }
    }

    return label;
}

var PI2$5 = Math.PI * 2;

var GaugeView = Chart.extend({

    type: 'gauge',

    render: function (seriesModel, ecModel, api) {

        this.group.removeAll();

        var colorList = seriesModel.get('axisLine.lineStyle.color');
        var posInfo = parsePosition(seriesModel, api);

        this._renderMain(
            seriesModel, ecModel, api, colorList, posInfo
        );
    },

    dispose: function () {},

    _renderMain: function (seriesModel, ecModel, api, colorList, posInfo) {
        var group = this.group;

        var axisLineModel = seriesModel.getModel('axisLine');
        var lineStyleModel = axisLineModel.getModel('lineStyle');

        var clockwise = seriesModel.get('clockwise');
        var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
        var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;

        var angleRangeSpan = (endAngle - startAngle) % PI2$5;

        var prevEndAngle = startAngle;
        var axisLineWidth = lineStyleModel.get('width');
        var showAxis = axisLineModel.get('show');

        for (var i = 0; showAxis && i < colorList.length; i++) {
            // Clamp
            var percent = Math.min(Math.max(colorList[i][0], 0), 1);
            var endAngle = startAngle + angleRangeSpan * percent;
            var sector = new Sector({
                shape: {
                    startAngle: prevEndAngle,
                    endAngle: endAngle,
                    cx: posInfo.cx,
                    cy: posInfo.cy,
                    clockwise: clockwise,
                    r0: posInfo.r - axisLineWidth,
                    r: posInfo.r
                },
                silent: true
            });

            sector.setStyle({
                fill: colorList[i][1]
            });

            sector.setStyle(lineStyleModel.getLineStyle(
                // Because we use sector to simulate arc
                // so the properties for stroking are useless
                ['color', 'borderWidth', 'borderColor']
            ));

            group.add(sector);

            prevEndAngle = endAngle;
        }

        var getColor = function (percent) {
            // Less than 0
            if (percent <= 0) {
                return colorList[0][1];
            }
            for (var i = 0; i < colorList.length; i++) {
                if (colorList[i][0] >= percent
                    && (i === 0 ? 0 : colorList[i - 1][0]) < percent
                ) {
                    return colorList[i][1];
                }
            }
            // More than 1
            return colorList[i - 1][1];
        };

        if (!clockwise) {
            var tmp = startAngle;
            startAngle = endAngle;
            endAngle = tmp;
        }

        this._renderTicks(
            seriesModel, ecModel, api, getColor, posInfo,
            startAngle, endAngle, clockwise
        );

        this._renderPointer(
            seriesModel, ecModel, api, getColor, posInfo,
            startAngle, endAngle, clockwise
        );

        this._renderTitle(
            seriesModel, ecModel, api, getColor, posInfo
        );
        this._renderDetail(
            seriesModel, ecModel, api, getColor, posInfo
        );
    },

    _renderTicks: function (
        seriesModel, ecModel, api, getColor, posInfo,
        startAngle, endAngle, clockwise
    ) {
        var group = this.group;
        var cx = posInfo.cx;
        var cy = posInfo.cy;
        var r = posInfo.r;

        var minVal = +seriesModel.get('min');
        var maxVal = +seriesModel.get('max');

        var splitLineModel = seriesModel.getModel('splitLine');
        var tickModel = seriesModel.getModel('axisTick');
        var labelModel = seriesModel.getModel('axisLabel');

        var splitNumber = seriesModel.get('splitNumber');
        var subSplitNumber = tickModel.get('splitNumber');

        var splitLineLen = parsePercent$1(
            splitLineModel.get('length'), r
        );
        var tickLen = parsePercent$1(
            tickModel.get('length'), r
        );

        var angle = startAngle;
        var step = (endAngle - startAngle) / splitNumber;
        var subStep = step / subSplitNumber;

        var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
        var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();

        for (var i = 0; i <= splitNumber; i++) {
            var unitX = Math.cos(angle);
            var unitY = Math.sin(angle);
            // Split line
            if (splitLineModel.get('show')) {
                var splitLine = new Line({
                    shape: {
                        x1: unitX * r + cx,
                        y1: unitY * r + cy,
                        x2: unitX * (r - splitLineLen) + cx,
                        y2: unitY * (r - splitLineLen) + cy
                    },
                    style: splitLineStyle,
                    silent: true
                });
                if (splitLineStyle.stroke === 'auto') {
                    splitLine.setStyle({
                        stroke: getColor(i / splitNumber)
                    });
                }

                group.add(splitLine);
            }

            // Label
            if (labelModel.get('show')) {
                var label = formatLabel(
                    round$1(i / splitNumber * (maxVal - minVal) + minVal),
                    labelModel.get('formatter')
                );
                var distance = labelModel.get('distance');
                var autoColor = getColor(i / splitNumber);

                group.add(new Text({
                    style: setTextStyle({}, labelModel, {
                        text: label,
                        x: unitX * (r - splitLineLen - distance) + cx,
                        y: unitY * (r - splitLineLen - distance) + cy,
                        textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'),
                        textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
                    }, {autoColor: autoColor}),
                    silent: true
                }));
            }

            // Axis tick
            if (tickModel.get('show') && i !== splitNumber) {
                for (var j = 0; j <= subSplitNumber; j++) {
                    var unitX = Math.cos(angle);
                    var unitY = Math.sin(angle);
                    var tickLine = new Line({
                        shape: {
                            x1: unitX * r + cx,
                            y1: unitY * r + cy,
                            x2: unitX * (r - tickLen) + cx,
                            y2: unitY * (r - tickLen) + cy
                        },
                        silent: true,
                        style: tickLineStyle
                    });

                    if (tickLineStyle.stroke === 'auto') {
                        tickLine.setStyle({
                            stroke: getColor((i + j / subSplitNumber) / splitNumber)
                        });
                    }

                    group.add(tickLine);
                    angle += subStep;
                }
                angle -= subStep;
            }
            else {
                angle += step;
            }
        }
    },

    _renderPointer: function (
        seriesModel, ecModel, api, getColor, posInfo,
        startAngle, endAngle, clockwise
    ) {

        var group = this.group;
        var oldData = this._data;

        if (!seriesModel.get('pointer.show')) {
            // Remove old element
            oldData && oldData.eachItemGraphicEl(function (el) {
                group.remove(el);
            });
            return;
        }

        var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')];
        var angleExtent = [startAngle, endAngle];

        var data = seriesModel.getData();
        var valueDim = data.mapDimension('value');

        data.diff(oldData)
            .add(function (idx) {
                var pointer = new PointerPath({
                    shape: {
                        angle: startAngle
                    }
                });

                initProps(pointer, {
                    shape: {
                        angle: linearMap(data.get(valueDim, idx), valueExtent, angleExtent, true)
                    }
                }, seriesModel);

                group.add(pointer);
                data.setItemGraphicEl(idx, pointer);
            })
            .update(function (newIdx, oldIdx) {
                var pointer = oldData.getItemGraphicEl(oldIdx);

                updateProps(pointer, {
                    shape: {
                        angle: linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, true)
                    }
                }, seriesModel);

                group.add(pointer);
                data.setItemGraphicEl(newIdx, pointer);
            })
            .remove(function (idx) {
                var pointer = oldData.getItemGraphicEl(idx);
                group.remove(pointer);
            })
            .execute();

        data.eachItemGraphicEl(function (pointer, idx) {
            var itemModel = data.getItemModel(idx);
            var pointerModel = itemModel.getModel('pointer');

            pointer.setShape({
                x: posInfo.cx,
                y: posInfo.cy,
                width: parsePercent$1(
                    pointerModel.get('width'), posInfo.r
                ),
                r: parsePercent$1(pointerModel.get('length'), posInfo.r)
            });

            pointer.useStyle(itemModel.getModel('itemStyle').getItemStyle());

            if (pointer.style.fill === 'auto') {
                pointer.setStyle('fill', getColor(
                    linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true)
                ));
            }

            setHoverStyle(
                pointer, itemModel.getModel('emphasis.itemStyle').getItemStyle()
            );
        });

        this._data = data;
    },

    _renderTitle: function (
        seriesModel, ecModel, api, getColor, posInfo
    ) {
        var data = seriesModel.getData();
        var valueDim = data.mapDimension('value');
        var titleModel = seriesModel.getModel('title');
        if (titleModel.get('show')) {
            var offsetCenter = titleModel.get('offsetCenter');
            var x = posInfo.cx + parsePercent$1(offsetCenter[0], posInfo.r);
            var y = posInfo.cy + parsePercent$1(offsetCenter[1], posInfo.r);

            var minVal = +seriesModel.get('min');
            var maxVal = +seriesModel.get('max');
            var value = seriesModel.getData().get(valueDim, 0);
            var autoColor = getColor(
                linearMap(value, [minVal, maxVal], [0, 1], true)
            );

            this.group.add(new Text({
                silent: true,
                style: setTextStyle({}, titleModel, {
                    x: x,
                    y: y,
                    // FIXME First data name ?
                    text: data.getName(0),
                    textAlign: 'center',
                    textVerticalAlign: 'middle'
                }, {autoColor: autoColor, forceRich: true})
            }));
        }
    },

    _renderDetail: function (
        seriesModel, ecModel, api, getColor, posInfo
    ) {
        var detailModel = seriesModel.getModel('detail');
        var minVal = +seriesModel.get('min');
        var maxVal = +seriesModel.get('max');
        if (detailModel.get('show')) {
            var offsetCenter = detailModel.get('offsetCenter');
            var x = posInfo.cx + parsePercent$1(offsetCenter[0], posInfo.r);
            var y = posInfo.cy + parsePercent$1(offsetCenter[1], posInfo.r);
            var width = parsePercent$1(detailModel.get('width'), posInfo.r);
            var height = parsePercent$1(detailModel.get('height'), posInfo.r);
            var data = seriesModel.getData();
            var value = data.get(data.mapDimension('value'), 0);
            var autoColor = getColor(
                linearMap(value, [minVal, maxVal], [0, 1], true)
            );

            this.group.add(new Text({
                silent: true,
                style: setTextStyle({}, detailModel, {
                    x: x,
                    y: y,
                    text: formatLabel(
                        // FIXME First data name ?
                        value, detailModel.get('formatter')
                    ),
                    textWidth: isNaN(width) ? null : width,
                    textHeight: isNaN(height) ? null : height,
                    textAlign: 'center',
                    textVerticalAlign: 'middle'
                }, {autoColor: autoColor, forceRich: true})
            }));
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var FunnelSeries = extendSeriesModel({

    type: 'series.funnel',

    init: function (option) {
        FunnelSeries.superApply(this, 'init', arguments);

        // Enable legend selection for each data item
        // Use a function instead of direct access because data reference may changed
        this.legendDataProvider = function () {
            return this.getRawData();
        };
        // Extend labelLine emphasis
        this._defaultLabelLine(option);
    },

    getInitialData: function (option, ecModel) {
        return createListSimply(this, ['value']);
    },

    _defaultLabelLine: function (option) {
        // Extend labelLine emphasis
        defaultEmphasis(option, 'labelLine', ['show']);

        var labelLineNormalOpt = option.labelLine;
        var labelLineEmphasisOpt = option.emphasis.labelLine;
        // Not show label line if `label.normal.show = false`
        labelLineNormalOpt.show = labelLineNormalOpt.show
            && option.label.show;
        labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
            && option.emphasis.label.show;
    },

    // Overwrite
    getDataParams: function (dataIndex) {
        var data = this.getData();
        var params = FunnelSeries.superCall(this, 'getDataParams', dataIndex);
        var valueDim = data.mapDimension('value');
        var sum = data.getSum(valueDim);
        // Percent is 0 if sum is 0
        params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) / sum * 100).toFixed(2);

        params.$vars.push('percent');
        return params;
    },

    defaultOption: {
        zlevel: 0,                  // 一级层叠
        z: 2,                       // 二级层叠
        legendHoverLink: true,
        left: 80,
        top: 60,
        right: 80,
        bottom: 60,
        // width: {totalWidth} - left - right,
        // height: {totalHeight} - top - bottom,

        // 默认取数据最小最大值
        // min: 0,
        // max: 100,
        minSize: '0%',
        maxSize: '100%',
        sort: 'descending', // 'ascending', 'descending'
        gap: 0,
        funnelAlign: 'center',
        label: {
            show: true,
            position: 'outer'
            // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
        },
        labelLine: {
            show: true,
            length: 20,
            lineStyle: {
                // color: 各异,
                width: 1,
                type: 'solid'
            }
        },
        itemStyle: {
            // color: 各异,
            borderColor: '#fff',
            borderWidth: 1
        },
        emphasis: {
            label: {
                show: true
            }
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Piece of pie including Sector, Label, LabelLine
 * @constructor
 * @extends {module:zrender/graphic/Group}
 */
function FunnelPiece(data, idx) {

    Group.call(this);

    var polygon = new Polygon();
    var labelLine = new Polyline();
    var text = new Text();
    this.add(polygon);
    this.add(labelLine);
    this.add(text);

    this.highDownOnUpdate = function (fromState, toState) {
        if (toState === 'emphasis') {
            labelLine.ignore = labelLine.hoverIgnore;
            text.ignore = text.hoverIgnore;
        }
        else {
            labelLine.ignore = labelLine.normalIgnore;
            text.ignore = text.normalIgnore;
        }
    };

    this.updateData(data, idx, true);
}

var funnelPieceProto = FunnelPiece.prototype;

var opacityAccessPath = ['itemStyle', 'opacity'];
funnelPieceProto.updateData = function (data, idx, firstCreate) {

    var polygon = this.childAt(0);

    var seriesModel = data.hostModel;
    var itemModel = data.getItemModel(idx);
    var layout = data.getItemLayout(idx);
    var opacity = data.getItemModel(idx).get(opacityAccessPath);
    opacity = opacity == null ? 1 : opacity;

    // Reset style
    polygon.useStyle({});

    if (firstCreate) {
        polygon.setShape({
            points: layout.points
        });
        polygon.setStyle({opacity: 0});
        initProps(polygon, {
            style: {
                opacity: opacity
            }
        }, seriesModel, idx);
    }
    else {
        updateProps(polygon, {
            style: {
                opacity: opacity
            },
            shape: {
                points: layout.points
            }
        }, seriesModel, idx);
    }

    // Update common style
    var itemStyleModel = itemModel.getModel('itemStyle');
    var visualColor = data.getItemVisual(idx, 'color');

    polygon.setStyle(
        defaults(
            {
                lineJoin: 'round',
                fill: visualColor
            },
            itemStyleModel.getItemStyle(['opacity'])
        )
    );
    polygon.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle();

    this._updateLabel(data, idx);

    setHoverStyle(this);
};

funnelPieceProto._updateLabel = function (data, idx) {

    var labelLine = this.childAt(1);
    var labelText = this.childAt(2);

    var seriesModel = data.hostModel;
    var itemModel = data.getItemModel(idx);
    var layout = data.getItemLayout(idx);
    var labelLayout = layout.label;
    var visualColor = data.getItemVisual(idx, 'color');

    updateProps(labelLine, {
        shape: {
            points: labelLayout.linePoints || labelLayout.linePoints
        }
    }, seriesModel, idx);

    updateProps(labelText, {
        style: {
            x: labelLayout.x,
            y: labelLayout.y
        }
    }, seriesModel, idx);
    labelText.attr({
        rotation: labelLayout.rotation,
        origin: [labelLayout.x, labelLayout.y],
        z2: 10
    });

    var labelModel = itemModel.getModel('label');
    var labelHoverModel = itemModel.getModel('emphasis.label');
    var labelLineModel = itemModel.getModel('labelLine');
    var labelLineHoverModel = itemModel.getModel('emphasis.labelLine');
    var visualColor = data.getItemVisual(idx, 'color');

    setLabelStyle(
        labelText.style, labelText.hoverStyle = {}, labelModel, labelHoverModel,
        {
            labelFetcher: data.hostModel,
            labelDataIndex: idx,
            defaultText: data.getName(idx),
            autoColor: visualColor,
            useInsideStyle: !!labelLayout.inside
        },
        {
            textAlign: labelLayout.textAlign,
            textVerticalAlign: labelLayout.verticalAlign
        }
    );

    labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
    labelText.hoverIgnore = !labelHoverModel.get('show');

    labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
    labelLine.hoverIgnore = !labelLineHoverModel.get('show');

    // Default use item visual color
    labelLine.setStyle({
        stroke: visualColor
    });
    labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());

    labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
};

inherits(FunnelPiece, Group);


var FunnelView = Chart.extend({

    type: 'funnel',

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var oldData = this._data;

        var group = this.group;

        data.diff(oldData)
            .add(function (idx) {
                var funnelPiece = new FunnelPiece(data, idx);

                data.setItemGraphicEl(idx, funnelPiece);

                group.add(funnelPiece);
            })
            .update(function (newIdx, oldIdx) {
                var piePiece = oldData.getItemGraphicEl(oldIdx);

                piePiece.updateData(data, newIdx);

                group.add(piePiece);
                data.setItemGraphicEl(newIdx, piePiece);
            })
            .remove(function (idx) {
                var piePiece = oldData.getItemGraphicEl(idx);
                group.remove(piePiece);
            })
            .execute();

        this._data = data;
    },

    remove: function () {
        this.group.removeAll();
        this._data = null;
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function getViewRect$2(seriesModel, api) {
    return getLayoutRect(
        seriesModel.getBoxLayoutParams(), {
            width: api.getWidth(),
            height: api.getHeight()
        }
    );
}

function getSortedIndices(data, sort) {
    var valueDim = data.mapDimension('value');
    var valueArr = data.mapArray(valueDim, function (val) {
        return val;
    });
    var indices = [];
    var isAscending = sort === 'ascending';
    for (var i = 0, len = data.count(); i < len; i++) {
        indices[i] = i;
    }

    // Add custom sortable function & none sortable opetion by "options.sort"
    if (typeof sort === 'function') {
        indices.sort(sort);
    }
    else if (sort !== 'none') {
        indices.sort(function (a, b) {
            return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a];
        });
    }
    return indices;
}

function labelLayout$1(data) {
    data.each(function (idx) {
        var itemModel = data.getItemModel(idx);
        var labelModel = itemModel.getModel('label');
        var labelPosition = labelModel.get('position');

        var labelLineModel = itemModel.getModel('labelLine');

        var layout = data.getItemLayout(idx);
        var points = layout.points;

        var isLabelInside = labelPosition === 'inner'
            || labelPosition === 'inside' || labelPosition === 'center'
            || labelPosition === 'insideLeft' || labelPosition === 'insideRight';

        var textAlign;
        var textX;
        var textY;
        var linePoints;

        if (isLabelInside) {
            if (labelPosition === 'insideLeft') {
                textX = (points[0][0] + points[3][0]) / 2 + 5;
                textY = (points[0][1] + points[3][1]) / 2;
                textAlign = 'left';
            }
            else if (labelPosition === 'insideRight') {
                textX = (points[1][0] + points[2][0]) / 2 - 5;
                textY = (points[1][1] + points[2][1]) / 2;
                textAlign = 'right';
            }
            else {
                textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
                textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
                textAlign = 'center';
            }
            linePoints = [
                [textX, textY], [textX, textY]
            ];
        }
        else {
            var x1;
            var y1;
            var x2;
            var labelLineLen = labelLineModel.get('length');
            if (labelPosition === 'left') {
                // Left side
                x1 = (points[3][0] + points[0][0]) / 2;
                y1 = (points[3][1] + points[0][1]) / 2;
                x2 = x1 - labelLineLen;
                textX = x2 - 5;
                textAlign = 'right';
            }
            else if (labelPosition === 'right') {
                // Right side
                x1 = (points[1][0] + points[2][0]) / 2;
                y1 = (points[1][1] + points[2][1]) / 2;
                x2 = x1 + labelLineLen;
                textX = x2 + 5;
                textAlign = 'left';
            }
            else if (labelPosition === 'rightTop') {
                // RightTop side
                x1 = points[1][0];
                y1 = points[1][1];
                x2 = x1 + labelLineLen;
                textX = x2 + 5;
                textAlign = 'top';
            }
            else if (labelPosition === 'rightBottom') {
                // RightBottom side
                x1 = points[2][0];
                y1 = points[2][1];
                x2 = x1 + labelLineLen;
                textX = x2 + 5;
                textAlign = 'bottom';
            }
            else if (labelPosition === 'leftTop') {
                // LeftTop side
                x1 = points[0][0];
                y1 = points[1][1];
                x2 = x1 - labelLineLen;
                textX = x2 - 5;
                textAlign = 'right';
            }
            else if (labelPosition === 'leftBottom') {
                // LeftBottom side
                x1 = points[3][0];
                y1 = points[2][1];
                x2 = x1 - labelLineLen;
                textX = x2 - 5;
                textAlign = 'right';
            }
            else {
                // Right side
                x1 = (points[1][0] + points[2][0]) / 2;
                y1 = (points[1][1] + points[2][1]) / 2;
                x2 = x1 + labelLineLen;
                textX = x2 + 5;
                textAlign = 'left';
            }
            var y2 = y1;

            linePoints = [[x1, y1], [x2, y2]];
            textY = y2;
        }

        layout.label = {
            linePoints: linePoints,
            x: textX,
            y: textY,
            verticalAlign: 'middle',
            textAlign: textAlign,
            inside: isLabelInside
        };
    });
}

var funnelLayout = function (ecModel, api, payload) {
    ecModel.eachSeriesByType('funnel', function (seriesModel) {
        var data = seriesModel.getData();
        var valueDim = data.mapDimension('value');
        var sort = seriesModel.get('sort');
        var viewRect = getViewRect$2(seriesModel, api);
        var indices = getSortedIndices(data, sort);

        var sizeExtent = [
            parsePercent$1(seriesModel.get('minSize'), viewRect.width),
            parsePercent$1(seriesModel.get('maxSize'), viewRect.width)
        ];
        var dataExtent = data.getDataExtent(valueDim);
        var min = seriesModel.get('min');
        var max = seriesModel.get('max');
        if (min == null) {
            min = Math.min(dataExtent[0], 0);
        }
        if (max == null) {
            max = dataExtent[1];
        }

        var funnelAlign = seriesModel.get('funnelAlign');
        var gap = seriesModel.get('gap');
        var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();

        var y = viewRect.y;

        var getLinePoints = function (idx, offY) {
            // End point index is data.count() and we assign it 0
            var val = data.get(valueDim, idx) || 0;
            var itemWidth = linearMap(val, [min, max], sizeExtent, true);
            var x0;
            switch (funnelAlign) {
                case 'left':
                    x0 = viewRect.x;
                    break;
                case 'center':
                    x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
                    break;
                case 'right':
                    x0 = viewRect.x + viewRect.width - itemWidth;
                    break;
            }
            return [
                [x0, offY],
                [x0 + itemWidth, offY]
            ];
        };

        if (sort === 'ascending') {
            // From bottom to top
            itemHeight = -itemHeight;
            gap = -gap;
            y += viewRect.height;
            indices = indices.reverse();
        }

        for (var i = 0; i < indices.length; i++) {
            var idx = indices[i];
            var nextIdx = indices[i + 1];

            var itemModel = data.getItemModel(idx);
            var height = itemModel.get('itemStyle.height');
            if (height == null) {
                height = itemHeight;
            }
            else {
                height = parsePercent$1(height, viewRect.height);
                if (sort === 'ascending') {
                    height = -height;
                }
            }

            var start = getLinePoints(idx, y);
            var end = getLinePoints(nextIdx, y + height);

            y += height + gap;

            data.setItemLayout(idx, {
                points: start.concat(end.slice().reverse())
            });
        }

        labelLayout$1(data);
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(dataColor('funnel'));
registerLayout(funnelLayout);
registerProcessor(dataFilter('funnel'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var parallelPreprocessor = function (option) {
    createParallelIfNeeded(option);
    mergeAxisOptionFromParallel(option);
};

/**
 * Create a parallel coordinate if not exists.
 * @inner
 */
function createParallelIfNeeded(option) {
    if (option.parallel) {
        return;
    }

    var hasParallelSeries = false;

    each$1(option.series, function (seriesOpt) {
        if (seriesOpt && seriesOpt.type === 'parallel') {
            hasParallelSeries = true;
        }
    });

    if (hasParallelSeries) {
        option.parallel = [{}];
    }
}

/**
 * Merge aixs definition from parallel option (if exists) to axis option.
 * @inner
 */
function mergeAxisOptionFromParallel(option) {
    var axes = normalizeToArray(option.parallelAxis);

    each$1(axes, function (axisOption) {
        if (!isObject$1(axisOption)) {
            return;
        }

        var parallelIndex = axisOption.parallelIndex || 0;
        var parallelOption = normalizeToArray(option.parallel)[parallelIndex];

        if (parallelOption && parallelOption.parallelAxisDefault) {
            merge(axisOption, parallelOption.parallelAxisDefault, false);
        }
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @constructor module:echarts/coord/parallel/ParallelAxis
 * @extends {module:echarts/coord/Axis}
 * @param {string} dim
 * @param {*} scale
 * @param {Array.<number>} coordExtent
 * @param {string} axisType
 */
var ParallelAxis = function (dim, scale, coordExtent, axisType, axisIndex) {

    Axis.call(this, dim, scale, coordExtent);

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = axisType || 'value';

    /**
     * @type {number}
     * @readOnly
     */
    this.axisIndex = axisIndex;
};

ParallelAxis.prototype = {

    constructor: ParallelAxis,

    /**
     * Axis model
     * @param {module:echarts/coord/parallel/AxisModel}
     */
    model: null,

    /**
     * @override
     */
    isHorizontal: function () {
        return this.coordinateSystem.getModel().get('layout') !== 'horizontal';
    }

};

inherits(ParallelAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Calculate slider move result.
 * Usage:
 * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as
 * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`.
 * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`.
 *
 * @param {number} delta Move length.
 * @param {Array.<number>} handleEnds handleEnds[0] can be bigger then handleEnds[1].
 *              handleEnds will be modified in this method.
 * @param {Array.<number>} extent handleEnds is restricted by extent.
 *              extent[0] should less or equals than extent[1].
 * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds.
 * @param {number} [minSpan] The range of dataZoom can not be smaller than that.
 *              If not set, handle0 and cross handle1. If set as a non-negative
 *              number (including `0`), handles will push each other when reaching
 *              the minSpan.
 * @param {number} [maxSpan] The range of dataZoom can not be larger than that.
 * @return {Array.<number>} The input handleEnds.
 */
var sliderMove = function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) {

    delta = delta || 0;

    var extentSpan = extent[1] - extent[0];

    // Notice maxSpan and minSpan can be null/undefined.
    if (minSpan != null) {
        minSpan = restrict$1(minSpan, [0, extentSpan]);
    }
    if (maxSpan != null) {
        maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0);
    }
    if (handleIndex === 'all') {
        var handleSpan = Math.abs(handleEnds[1] - handleEnds[0]);
        handleSpan = restrict$1(handleSpan, [0, extentSpan]);
        minSpan = maxSpan = restrict$1(handleSpan, [minSpan, maxSpan]);
        handleIndex = 0;
    }

    handleEnds[0] = restrict$1(handleEnds[0], extent);
    handleEnds[1] = restrict$1(handleEnds[1], extent);

    var originalDistSign = getSpanSign(handleEnds, handleIndex);

    handleEnds[handleIndex] += delta;

    // Restrict in extent.
    var extentMinSpan = minSpan || 0;
    var realExtent = extent.slice();
    originalDistSign.sign < 0 ? (realExtent[0] += extentMinSpan) : (realExtent[1] -= extentMinSpan);
    handleEnds[handleIndex] = restrict$1(handleEnds[handleIndex], realExtent);

    // Expand span.
    var currDistSign = getSpanSign(handleEnds, handleIndex);
    if (minSpan != null && (
        currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan
    )) {
        // If minSpan exists, 'cross' is forbidden.
        handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan;
    }

    // Shrink span.
    var currDistSign = getSpanSign(handleEnds, handleIndex);
    if (maxSpan != null && currDistSign.span > maxSpan) {
        handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan;
    }

    return handleEnds;
};

function getSpanSign(handleEnds, handleIndex) {
    var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex];
    // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0]
    // is at left of handleEnds[1] for non-cross case.
    return {span: Math.abs(dist), sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1};
}

function restrict$1(value, extend) {
    return Math.min(
        extend[1] != null ? extend[1] : Infinity,
        Math.max(extend[0] != null ? extend[0] : -Infinity, value)
    );
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Parallel Coordinates
 * <https://en.wikipedia.org/wiki/Parallel_coordinates>
 */

var each$11 = each$1;
var mathMin$6 = Math.min;
var mathMax$6 = Math.max;
var mathFloor$2 = Math.floor;
var mathCeil$2 = Math.ceil;
var round$2 = round$1;

var PI$4 = Math.PI;

function Parallel(parallelModel, ecModel, api) {

    /**
     * key: dimension
     * @type {Object.<string, module:echarts/coord/parallel/Axis>}
     * @private
     */
    this._axesMap = createHashMap();

    /**
     * key: dimension
     * value: {position: [], rotation, }
     * @type {Object.<string, Object>}
     * @private
     */
    this._axesLayout = {};

    /**
     * Always follow axis order.
     * @type {Array.<string>}
     * @readOnly
     */
    this.dimensions = parallelModel.dimensions;

    /**
     * @type {module:zrender/core/BoundingRect}
     */
    this._rect;

    /**
     * @type {module:echarts/coord/parallel/ParallelModel}
     */
    this._model = parallelModel;

    this._init(parallelModel, ecModel, api);
}

Parallel.prototype = {

    type: 'parallel',

    constructor: Parallel,

    /**
     * Initialize cartesian coordinate systems
     * @private
     */
    _init: function (parallelModel, ecModel, api) {

        var dimensions = parallelModel.dimensions;
        var parallelAxisIndex = parallelModel.parallelAxisIndex;

        each$11(dimensions, function (dim, idx) {

            var axisIndex = parallelAxisIndex[idx];
            var axisModel = ecModel.getComponent('parallelAxis', axisIndex);

            var axis = this._axesMap.set(dim, new ParallelAxis(
                dim,
                createScaleByModel(axisModel),
                [0, 0],
                axisModel.get('type'),
                axisIndex
            ));

            var isCategory = axis.type === 'category';
            axis.onBand = isCategory && axisModel.get('boundaryGap');
            axis.inverse = axisModel.get('inverse');

            // Injection
            axisModel.axis = axis;
            axis.model = axisModel;
            axis.coordinateSystem = axisModel.coordinateSystem = this;

        }, this);
    },

    /**
     * Update axis scale after data processed
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    update: function (ecModel, api) {
        this._updateAxesFromSeries(this._model, ecModel);
    },

    /**
     * @override
     */
    containPoint: function (point) {
        var layoutInfo = this._makeLayoutInfo();
        var axisBase = layoutInfo.axisBase;
        var layoutBase = layoutInfo.layoutBase;
        var pixelDimIndex = layoutInfo.pixelDimIndex;
        var pAxis = point[1 - pixelDimIndex];
        var pLayout = point[pixelDimIndex];

        return pAxis >= axisBase
            && pAxis <= axisBase + layoutInfo.axisLength
            && pLayout >= layoutBase
            && pLayout <= layoutBase + layoutInfo.layoutLength;
    },

    getModel: function () {
        return this._model;
    },

    /**
     * Update properties from series
     * @private
     */
    _updateAxesFromSeries: function (parallelModel, ecModel) {
        ecModel.eachSeries(function (seriesModel) {

            if (!parallelModel.contains(seriesModel, ecModel)) {
                return;
            }

            var data = seriesModel.getData();

            each$11(this.dimensions, function (dim) {
                var axis = this._axesMap.get(dim);
                axis.scale.unionExtentFromData(data, data.mapDimension(dim));
                niceScaleExtent(axis.scale, axis.model);
            }, this);
        }, this);
    },

    /**
     * Resize the parallel coordinate system.
     * @param {module:echarts/coord/parallel/ParallelModel} parallelModel
     * @param {module:echarts/ExtensionAPI} api
     */
    resize: function (parallelModel, api) {
        this._rect = getLayoutRect(
            parallelModel.getBoxLayoutParams(),
            {
                width: api.getWidth(),
                height: api.getHeight()
            }
        );

        this._layoutAxes();
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getRect: function () {
        return this._rect;
    },

    /**
     * @private
     */
    _makeLayoutInfo: function () {
        var parallelModel = this._model;
        var rect = this._rect;
        var xy = ['x', 'y'];
        var wh = ['width', 'height'];
        var layout = parallelModel.get('layout');
        var pixelDimIndex = layout === 'horizontal' ? 0 : 1;
        var layoutLength = rect[wh[pixelDimIndex]];
        var layoutExtent = [0, layoutLength];
        var axisCount = this.dimensions.length;

        var axisExpandWidth = restrict(parallelModel.get('axisExpandWidth'), layoutExtent);
        var axisExpandCount = restrict(parallelModel.get('axisExpandCount') || 0, [0, axisCount]);
        var axisExpandable = parallelModel.get('axisExpandable')
            && axisCount > 3
            && axisCount > axisExpandCount
            && axisExpandCount > 1
            && axisExpandWidth > 0
            && layoutLength > 0;

        // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength],
        // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow),
        // where collapsed axes should be overlapped.
        var axisExpandWindow = parallelModel.get('axisExpandWindow');
        var winSize;
        if (!axisExpandWindow) {
            winSize = restrict(axisExpandWidth * (axisExpandCount - 1), layoutExtent);
            var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor$2(axisCount / 2);
            axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2];
            axisExpandWindow[1] = axisExpandWindow[0] + winSize;
        }
        else {
                winSize = restrict(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent);
                axisExpandWindow[1] = axisExpandWindow[0] + winSize;
        }

        var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount);
        // Avoid axisCollapseWidth is too small.
        axisCollapseWidth < 3 && (axisCollapseWidth = 0);

        // Find the first and last indices > ewin[0] and < ewin[1].
        var winInnerIndices = [
            mathFloor$2(round$2(axisExpandWindow[0] / axisExpandWidth, 1)) + 1,
            mathCeil$2(round$2(axisExpandWindow[1] / axisExpandWidth, 1)) - 1
        ];

        // Pos in ec coordinates.
        var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0];

        return {
            layout: layout,
            pixelDimIndex: pixelDimIndex,
            layoutBase: rect[xy[pixelDimIndex]],
            layoutLength: layoutLength,
            axisBase: rect[xy[1 - pixelDimIndex]],
            axisLength: rect[wh[1 - pixelDimIndex]],
            axisExpandable: axisExpandable,
            axisExpandWidth: axisExpandWidth,
            axisCollapseWidth: axisCollapseWidth,
            axisExpandWindow: axisExpandWindow,
            axisCount: axisCount,
            winInnerIndices: winInnerIndices,
            axisExpandWindow0Pos: axisExpandWindow0Pos
        };
    },

    /**
     * @private
     */
    _layoutAxes: function () {
        var rect = this._rect;
        var axes = this._axesMap;
        var dimensions = this.dimensions;
        var layoutInfo = this._makeLayoutInfo();
        var layout = layoutInfo.layout;

        axes.each(function (axis) {
            var axisExtent = [0, layoutInfo.axisLength];
            var idx = axis.inverse ? 1 : 0;
            axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
        });

        each$11(dimensions, function (dim, idx) {
            var posInfo = (layoutInfo.axisExpandable
                ? layoutAxisWithExpand : layoutAxisWithoutExpand
            )(idx, layoutInfo);

            var positionTable = {
                horizontal: {
                    x: posInfo.position,
                    y: layoutInfo.axisLength
                },
                vertical: {
                    x: 0,
                    y: posInfo.position
                }
            };
            var rotationTable = {
                horizontal: PI$4 / 2,
                vertical: 0
            };

            var position = [
                positionTable[layout].x + rect.x,
                positionTable[layout].y + rect.y
            ];

            var rotation = rotationTable[layout];
            var transform = create$1();
            rotate(transform, transform, rotation);
            translate(transform, transform, position);

            // TODO
            // tick等排布信息。

            // TODO
            // 根据axis order 更新 dimensions顺序。

            this._axesLayout[dim] = {
                position: position,
                rotation: rotation,
                transform: transform,
                axisNameAvailableWidth: posInfo.axisNameAvailableWidth,
                axisLabelShow: posInfo.axisLabelShow,
                nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth,
                tickDirection: 1,
                labelDirection: 1
            };
        }, this);
    },

    /**
     * Get axis by dim.
     * @param {string} dim
     * @return {module:echarts/coord/parallel/ParallelAxis} [description]
     */
    getAxis: function (dim) {
        return this._axesMap.get(dim);
    },

    /**
     * Convert a dim value of a single item of series data to Point.
     * @param {*} value
     * @param {string} dim
     * @return {Array}
     */
    dataToPoint: function (value, dim) {
        return this.axisCoordToPoint(
            this._axesMap.get(dim).dataToCoord(value),
            dim
        );
    },

    /**
     * Travel data for one time, get activeState of each data item.
     * @param {module:echarts/data/List} data
     * @param {Functio} cb param: {string} activeState 'active' or 'inactive' or 'normal'
     *                            {number} dataIndex
     * @param {number} [start=0] the start dataIndex that travel from.
     * @param {number} [end=data.count()] the next dataIndex of the last dataIndex will be travel.
     */
    eachActiveState: function (data, callback, start, end) {
        start == null && (start = 0);
        end == null && (end = data.count());

        var axesMap = this._axesMap;
        var dimensions = this.dimensions;
        var dataDimensions = [];
        var axisModels = [];

        each$1(dimensions, function (axisDim) {
            dataDimensions.push(data.mapDimension(axisDim));
            axisModels.push(axesMap.get(axisDim).model);
        });

        var hasActiveSet = this.hasAxisBrushed();

        for (var dataIndex = start; dataIndex < end; dataIndex++) {
            var activeState;

            if (!hasActiveSet) {
                activeState = 'normal';
            }
            else {
                activeState = 'active';
                var values = data.getValues(dataDimensions, dataIndex);
                for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
                    var state = axisModels[j].getActiveState(values[j]);

                    if (state === 'inactive') {
                        activeState = 'inactive';
                        break;
                    }
                }
            }

            callback(activeState, dataIndex);
        }
    },

    /**
     * Whether has any activeSet.
     * @return {boolean}
     */
    hasAxisBrushed: function () {
        var dimensions = this.dimensions;
        var axesMap = this._axesMap;
        var hasActiveSet = false;

        for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
            if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') {
                hasActiveSet = true;
            }
        }

        return hasActiveSet;
    },

    /**
     * Convert coords of each axis to Point.
     *  Return point. For example: [10, 20]
     * @param {Array.<number>} coords
     * @param {string} dim
     * @return {Array.<number>}
     */
    axisCoordToPoint: function (coord, dim) {
        var axisLayout = this._axesLayout[dim];
        return applyTransform$1([coord, 0], axisLayout.transform);
    },

    /**
     * Get axis layout.
     */
    getAxisLayout: function (dim) {
        return clone(this._axesLayout[dim]);
    },

    /**
     * @param {Array.<number>} point
     * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}.
     */
    getSlidedAxisExpandWindow: function (point) {
        var layoutInfo = this._makeLayoutInfo();
        var pixelDimIndex = layoutInfo.pixelDimIndex;
        var axisExpandWindow = layoutInfo.axisExpandWindow.slice();
        var winSize = axisExpandWindow[1] - axisExpandWindow[0];
        var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)];

        // Out of the area of coordinate system.
        if (!this.containPoint(point)) {
            return {behavior: 'none', axisExpandWindow: axisExpandWindow};
        }

        // Conver the point from global to expand coordinates.
        var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos;

        // For dragging operation convenience, the window should not be
        // slided when mouse is the center area of the window.
        var delta;
        var behavior = 'slide';
        var axisCollapseWidth = layoutInfo.axisCollapseWidth;
        var triggerArea = this._model.get('axisExpandSlideTriggerArea');
        // But consider touch device, jump is necessary.
        var useJump = triggerArea[0] != null;

        if (axisCollapseWidth) {
            if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) {
                behavior = 'jump';
                delta = pointCoord - winSize * triggerArea[2];
            }
            else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) {
                behavior = 'jump';
                delta = pointCoord - winSize * (1 - triggerArea[2]);
            }
            else {
                (delta = pointCoord - winSize * triggerArea[1]) >= 0
                    && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0
                    && (delta = 0);
            }
            delta *= layoutInfo.axisExpandWidth / axisCollapseWidth;
            delta
                ? sliderMove(delta, axisExpandWindow, extent, 'all')
                // Avoid nonsense triger on mousemove.
                : (behavior = 'none');
        }
        // When screen is too narrow, make it visible and slidable, although it is hard to interact.
        else {
            var winSize = axisExpandWindow[1] - axisExpandWindow[0];
            var pos = extent[1] * pointCoord / winSize;
            axisExpandWindow = [mathMax$6(0, pos - winSize / 2)];
            axisExpandWindow[1] = mathMin$6(extent[1], axisExpandWindow[0] + winSize);
            axisExpandWindow[0] = axisExpandWindow[1] - winSize;
        }

        return {
            axisExpandWindow: axisExpandWindow,
            behavior: behavior
        };
    }
};

function restrict(len, extent) {
    return mathMin$6(mathMax$6(len, extent[0]), extent[1]);
}

function layoutAxisWithoutExpand(axisIndex, layoutInfo) {
    var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1);
    return {
        position: step * axisIndex,
        axisNameAvailableWidth: step,
        axisLabelShow: true
    };
}

function layoutAxisWithExpand(axisIndex, layoutInfo) {
    var layoutLength = layoutInfo.layoutLength;
    var axisExpandWidth = layoutInfo.axisExpandWidth;
    var axisCount = layoutInfo.axisCount;
    var axisCollapseWidth = layoutInfo.axisCollapseWidth;
    var winInnerIndices = layoutInfo.winInnerIndices;

    var position;
    var axisNameAvailableWidth = axisCollapseWidth;
    var axisLabelShow = false;
    var nameTruncateMaxWidth;

    if (axisIndex < winInnerIndices[0]) {
        position = axisIndex * axisCollapseWidth;
        nameTruncateMaxWidth = axisCollapseWidth;
    }
    else if (axisIndex <= winInnerIndices[1]) {
        position = layoutInfo.axisExpandWindow0Pos
            + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0];
        axisNameAvailableWidth = axisExpandWidth;
        axisLabelShow = true;
    }
    else {
        position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth;
        nameTruncateMaxWidth = axisCollapseWidth;
    }

    return {
        position: position,
        axisNameAvailableWidth: axisNameAvailableWidth,
        axisLabelShow: axisLabelShow,
        nameTruncateMaxWidth: nameTruncateMaxWidth
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Parallel coordinate system creater.
 */

function create$2(ecModel, api) {
    var coordSysList = [];

    ecModel.eachComponent('parallel', function (parallelModel, idx) {
        var coordSys = new Parallel(parallelModel, ecModel, api);

        coordSys.name = 'parallel_' + idx;
        coordSys.resize(parallelModel, api);

        parallelModel.coordinateSystem = coordSys;
        coordSys.model = parallelModel;

        coordSysList.push(coordSys);
    });

    // Inject the coordinateSystems into seriesModel
    ecModel.eachSeries(function (seriesModel) {
        if (seriesModel.get('coordinateSystem') === 'parallel') {
            var parallelModel = ecModel.queryComponents({
                mainType: 'parallel',
                index: seriesModel.get('parallelIndex'),
                id: seriesModel.get('parallelId')
            })[0];
            seriesModel.coordinateSystem = parallelModel.coordinateSystem;
        }
    });

    return coordSysList;
}

CoordinateSystemManager.register('parallel', {create: create$2});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AxisModel$2 = ComponentModel.extend({

    type: 'baseParallelAxis',

    /**
     * @type {module:echarts/coord/parallel/Axis}
     */
    axis: null,

    /**
     * @type {Array.<Array.<number>}
     * @readOnly
     */
    activeIntervals: [],

    /**
     * @return {Object}
     */
    getAreaSelectStyle: function () {
        return makeStyleMapper(
            [
                ['fill', 'color'],
                ['lineWidth', 'borderWidth'],
                ['stroke', 'borderColor'],
                ['width', 'width'],
                ['opacity', 'opacity']
            ]
        )(this.getModel('areaSelectStyle'));
    },

    /**
     * The code of this feature is put on AxisModel but not ParallelAxis,
     * because axisModel can be alive after echarts updating but instance of
     * ParallelAxis having been disposed. this._activeInterval should be kept
     * when action dispatched (i.e. legend click).
     *
     * @param {Array.<Array<number>>} intervals interval.length === 0
     *                                          means set all active.
     * @public
     */
    setActiveIntervals: function (intervals) {
        var activeIntervals = this.activeIntervals = clone(intervals);

        // Normalize
        if (activeIntervals) {
            for (var i = activeIntervals.length - 1; i >= 0; i--) {
                asc(activeIntervals[i]);
            }
        }
    },

    /**
     * @param {number|string} [value] When attempting to detect 'no activeIntervals set',
     *                         value can not be input.
     * @return {string} 'normal': no activeIntervals set,
     *                  'active',
     *                  'inactive'.
     * @public
     */
    getActiveState: function (value) {
        var activeIntervals = this.activeIntervals;

        if (!activeIntervals.length) {
            return 'normal';
        }

        if (value == null || isNaN(value)) {
            return 'inactive';
        }

        // Simple optimization
        if (activeIntervals.length === 1) {
            var interval = activeIntervals[0];
            if (interval[0] <= value && value <= interval[1]) {
                return 'active';
            }
        }
        else {
            for (var i = 0, len = activeIntervals.length; i < len; i++) {
                if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) {
                    return 'active';
                }
            }
        }

        return 'inactive';
    }

});

var defaultOption$1 = {

    type: 'value',

    /**
     * @type {Array.<number>}
     */
    dim: null, // 0, 1, 2, ...

    // parallelIndex: null,

    areaSelectStyle: {
        width: 20,
        borderWidth: 1,
        borderColor: 'rgba(160,197,232)',
        color: 'rgba(160,197,232)',
        opacity: 0.3
    },

    realtime: true, // Whether realtime update view when select.

    z: 10
};

merge(AxisModel$2.prototype, axisModelCommonMixin);

function getAxisType$1(axisName, option) {
    return option.type || (option.data ? 'category' : 'value');
}

axisModelCreator('parallel', AxisModel$2, getAxisType$1, defaultOption$1);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

ComponentModel.extend({

    type: 'parallel',

    dependencies: ['parallelAxis'],

    /**
     * @type {module:echarts/coord/parallel/Parallel}
     */
    coordinateSystem: null,

    /**
     * Each item like: 'dim0', 'dim1', 'dim2', ...
     * @type {Array.<string>}
     * @readOnly
     */
    dimensions: null,

    /**
     * Coresponding to dimensions.
     * @type {Array.<number>}
     * @readOnly
     */
    parallelAxisIndex: null,

    layoutMode: 'box',

    defaultOption: {
        zlevel: 0,
        z: 0,
        left: 80,
        top: 60,
        right: 80,
        bottom: 60,
        // width: {totalWidth} - left - right,
        // height: {totalHeight} - top - bottom,

        layout: 'horizontal',      // 'horizontal' or 'vertical'

        // FIXME
        // naming?
        axisExpandable: false,
        axisExpandCenter: null,
        axisExpandCount: 0,
        axisExpandWidth: 50,      // FIXME '10%' ?
        axisExpandRate: 17,
        axisExpandDebounce: 50,
        // [out, in, jumpTarget]. In percentage. If use [null, 0.05], null means full.
        // Do not doc to user until necessary.
        axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4],
        axisExpandTriggerOn: 'click', // 'mousemove' or 'click'

        parallelAxisDefault: null
    },

    /**
     * @override
     */
    init: function () {
        ComponentModel.prototype.init.apply(this, arguments);

        this.mergeOption({});
    },

    /**
     * @override
     */
    mergeOption: function (newOption) {
        var thisOption = this.option;

        newOption && merge(thisOption, newOption, true);

        this._initDimensions();
    },

    /**
     * Whether series or axis is in this coordinate system.
     * @param {module:echarts/model/Series|module:echarts/coord/parallel/AxisModel} model
     * @param {module:echarts/model/Global} ecModel
     */
    contains: function (model, ecModel) {
        var parallelIndex = model.get('parallelIndex');
        return parallelIndex != null
            && ecModel.getComponent('parallel', parallelIndex) === this;
    },

    setAxisExpand: function (opt) {
        each$1(
            ['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'],
            function (name) {
                if (opt.hasOwnProperty(name)) {
                    this.option[name] = opt[name];
                }
            },
            this
        );
    },

    /**
     * @private
     */
    _initDimensions: function () {
        var dimensions = this.dimensions = [];
        var parallelAxisIndex = this.parallelAxisIndex = [];

        var axisModels = filter(this.dependentModels.parallelAxis, function (axisModel) {
            // Can not use this.contains here, because
            // initialization has not been completed yet.
            return (axisModel.get('parallelIndex') || 0) === this.componentIndex;
        }, this);

        each$1(axisModels, function (axisModel) {
            dimensions.push('dim' + axisModel.get('dim'));
            parallelAxisIndex.push(axisModel.componentIndex);
        });
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @payload
 * @property {string} parallelAxisId
 * @property {Array.<Array.<number>>} intervals
 */
var actionInfo$1 = {
    type: 'axisAreaSelect',
    event: 'axisAreaSelected'
    // update: 'updateVisual'
};

registerAction(actionInfo$1, function (payload, ecModel) {
    ecModel.eachComponent(
        {mainType: 'parallelAxis', query: payload},
        function (parallelAxisModel) {
            parallelAxisModel.axis.model.setActiveIntervals(payload.intervals);
        }
    );
});

/**
 * @payload
 */
registerAction('parallelAxisExpand', function (payload, ecModel) {
    ecModel.eachComponent(
        {mainType: 'parallel', query: payload},
        function (parallelModel) {
            parallelModel.setAxisExpand(payload);
        }
    );

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var curry$2 = curry;
var each$12 = each$1;
var map$2 = map;
var mathMin$7 = Math.min;
var mathMax$7 = Math.max;
var mathPow$2 = Math.pow;

var COVER_Z = 10000;
var UNSELECT_THRESHOLD = 6;
var MIN_RESIZE_LINE_WIDTH = 6;
var MUTEX_RESOURCE_KEY = 'globalPan';

var DIRECTION_MAP = {
    w: [0, 0],
    e: [0, 1],
    n: [1, 0],
    s: [1, 1]
};
var CURSOR_MAP = {
    w: 'ew',
    e: 'ew',
    n: 'ns',
    s: 'ns',
    ne: 'nesw',
    sw: 'nesw',
    nw: 'nwse',
    se: 'nwse'
};
var DEFAULT_BRUSH_OPT = {
    brushStyle: {
        lineWidth: 2,
        stroke: 'rgba(0,0,0,0.3)',
        fill: 'rgba(0,0,0,0.1)'
    },
    transformable: true,
    brushMode: 'single',
    removeOnClick: false
};

var baseUID = 0;

/**
 * @alias module:echarts/component/helper/BrushController
 * @constructor
 * @mixin {module:zrender/mixin/Eventful}
 * @event module:echarts/component/helper/BrushController#brush
 *        params:
 *            areas: Array.<Array>, coord relates to container group,
 *                                    If no container specified, to global.
 *            opt {
 *                isEnd: boolean,
 *                removeOnClick: boolean
 *            }
 *
 * @param {module:zrender/zrender~ZRender} zr
 */
function BrushController(zr) {

    if (__DEV__) {
        assert$1(zr);
    }

    Eventful.call(this);

    /**
     * @type {module:zrender/zrender~ZRender}
     * @private
     */
    this._zr = zr;

    /**
     * @type {module:zrender/container/Group}
     * @readOnly
     */
    this.group = new Group();

    /**
     * Only for drawing (after enabledBrush).
     *     'line', 'rect', 'polygon' or false
     *     If passing false/null/undefined, disable brush.
     *     If passing 'auto', determined by panel.defaultBrushType
     * @private
     * @type {string}
     */
    this._brushType;

    /**
     * Only for drawing (after enabledBrush).
     *
     * @private
     * @type {Object}
     */
    this._brushOption;

    /**
     * @private
     * @type {Object}
     */
    this._panels;

    /**
     * @private
     * @type {Array.<nubmer>}
     */
    this._track = [];

    /**
     * @private
     * @type {boolean}
     */
    this._dragging;

    /**
     * @private
     * @type {Object}
     */
    this._lastMouseMovePoint = {};

    /**
     * @private
     * @type {Array}
     */
    this._covers = [];

    /**
     * @private
     * @type {moudule:zrender/container/Group}
     */
    this._creatingCover;

    /**
     * `true` means global panel
     * @private
     * @type {module:zrender/container/Group|boolean}
     */
    this._creatingPanel;

    /**
     * @private
     * @type {boolean}
     */
    this._enableGlobalPan;

    /**
     * @private
     * @type {boolean}
     */
    if (__DEV__) {
        this._mounted;
    }

    /**
     * @private
     * @type {string}
     */
    this._uid = 'brushController_' + baseUID++;

    /**
     * @private
     * @type {Object}
     */
    this._handlers = {};
    each$12(mouseHandlers, function (handler, eventName) {
        this._handlers[eventName] = bind(handler, this);
    }, this);
}

BrushController.prototype = {

    constructor: BrushController,

    /**
     * If set to null/undefined/false, select disabled.
     * @param {Object} brushOption
     * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false
     *                          If passing false/null/undefined, disable brush.
     *                          If passing 'auto', determined by panel.defaultBrushType.
     *                              ('auto' can not be used in global panel)
     * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple'
     * @param {boolean} [brushOption.transformable=true]
     * @param {boolean} [brushOption.removeOnClick=false]
     * @param {Object} [brushOption.brushStyle]
     * @param {number} [brushOption.brushStyle.width]
     * @param {number} [brushOption.brushStyle.lineWidth]
     * @param {string} [brushOption.brushStyle.stroke]
     * @param {string} [brushOption.brushStyle.fill]
     * @param {number} [brushOption.z]
     */
    enableBrush: function (brushOption) {
        if (__DEV__) {
            assert$1(this._mounted);
        }

        this._brushType && doDisableBrush(this);
        brushOption.brushType && doEnableBrush(this, brushOption);

        return this;
    },

    /**
     * @param {Array.<Object>} panelOpts If not pass, it is global brush.
     *        Each items: {
     *            panelId, // mandatory.
     *            clipPath, // mandatory. function.
     *            isTargetByCursor, // mandatory. function.
     *            defaultBrushType, // optional, only used when brushType is 'auto'.
     *            getLinearBrushOtherExtent, // optional. function.
     *        }
     */
    setPanels: function (panelOpts) {
        if (panelOpts && panelOpts.length) {
            var panels = this._panels = {};
            each$1(panelOpts, function (panelOpts) {
                panels[panelOpts.panelId] = clone(panelOpts);
            });
        }
        else {
            this._panels = null;
        }
        return this;
    },

    /**
     * @param {Object} [opt]
     * @return {boolean} [opt.enableGlobalPan=false]
     */
    mount: function (opt) {
        opt = opt || {};

        if (__DEV__) {
            this._mounted = true; // should be at first.
        }

        this._enableGlobalPan = opt.enableGlobalPan;

        var thisGroup = this.group;
        this._zr.add(thisGroup);

        thisGroup.attr({
            position: opt.position || [0, 0],
            rotation: opt.rotation || 0,
            scale: opt.scale || [1, 1]
        });
        this._transform = thisGroup.getLocalTransform();

        return this;
    },

    eachCover: function (cb, context) {
        each$12(this._covers, cb, context);
    },

    /**
     * Update covers.
     * @param {Array.<Object>} brushOptionList Like:
     *        [
     *            {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable},
     *            {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]},
     *            ...
     *        ]
     *        `brushType` is required in each cover info. (can not be 'auto')
     *        `id` is not mandatory.
     *        `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.
     *        If brushOptionList is null/undefined, all covers removed.
     */
    updateCovers: function (brushOptionList) {
        if (__DEV__) {
            assert$1(this._mounted);
        }

        brushOptionList = map(brushOptionList, function (brushOption) {
            return merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
        });

        var tmpIdPrefix = '\0-brush-index-';
        var oldCovers = this._covers;
        var newCovers = this._covers = [];
        var controller = this;
        var creatingCover = this._creatingCover;

        (new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey))
            .add(addOrUpdate)
            .update(addOrUpdate)
            .remove(remove)
            .execute();

        return this;

        function getKey(brushOption, index) {
            return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index)
                + '-' + brushOption.brushType;
        }

        function oldGetKey(cover, index) {
            return getKey(cover.__brushOption, index);
        }

        function addOrUpdate(newIndex, oldIndex) {
            var newBrushOption = brushOptionList[newIndex];
            // Consider setOption in event listener of brushSelect,
            // where updating cover when creating should be forbiden.
            if (oldIndex != null && oldCovers[oldIndex] === creatingCover) {
                newCovers[newIndex] = oldCovers[oldIndex];
            }
            else {
                var cover = newCovers[newIndex] = oldIndex != null
                    ? (
                        oldCovers[oldIndex].__brushOption = newBrushOption,
                        oldCovers[oldIndex]
                    )
                    : endCreating(controller, createCover(controller, newBrushOption));
                updateCoverAfterCreation(controller, cover);
            }
        }

        function remove(oldIndex) {
            if (oldCovers[oldIndex] !== creatingCover) {
                controller.group.remove(oldCovers[oldIndex]);
            }
        }
    },

    unmount: function () {
        if (__DEV__) {
            if (!this._mounted) {
                return;
            }
        }

        this.enableBrush(false);

        // container may 'removeAll' outside.
        clearCovers(this);
        this._zr.remove(this.group);

        if (__DEV__) {
            this._mounted = false; // should be at last.
        }

        return this;
    },

    dispose: function () {
        this.unmount();
        this.off();
    }
};

mixin(BrushController, Eventful);

function doEnableBrush(controller, brushOption) {
    var zr = controller._zr;

    // Consider roam, which takes globalPan too.
    if (!controller._enableGlobalPan) {
        take(zr, MUTEX_RESOURCE_KEY, controller._uid);
    }

    each$12(controller._handlers, function (handler, eventName) {
        zr.on(eventName, handler);
    });

    controller._brushType = brushOption.brushType;
    controller._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
}

function doDisableBrush(controller) {
    var zr = controller._zr;

    release(zr, MUTEX_RESOURCE_KEY, controller._uid);

    each$12(controller._handlers, function (handler, eventName) {
        zr.off(eventName, handler);
    });

    controller._brushType = controller._brushOption = null;
}

function createCover(controller, brushOption) {
    var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
    cover.__brushOption = brushOption;
    updateZ$1(cover, brushOption);
    controller.group.add(cover);
    return cover;
}

function endCreating(controller, creatingCover) {
    var coverRenderer = getCoverRenderer(creatingCover);
    if (coverRenderer.endCreating) {
        coverRenderer.endCreating(controller, creatingCover);
        updateZ$1(creatingCover, creatingCover.__brushOption);
    }
    return creatingCover;
}

function updateCoverShape(controller, cover) {
    var brushOption = cover.__brushOption;
    getCoverRenderer(cover).updateCoverShape(
        controller, cover, brushOption.range, brushOption
    );
}

function updateZ$1(cover, brushOption) {
    var z = brushOption.z;
    z == null && (z = COVER_Z);
    cover.traverse(function (el) {
        el.z = z;
        el.z2 = z; // Consider in given container.
    });
}

function updateCoverAfterCreation(controller, cover) {
    getCoverRenderer(cover).updateCommon(controller, cover);
    updateCoverShape(controller, cover);
}

function getCoverRenderer(cover) {
    return coverRenderers[cover.__brushOption.brushType];
}

// return target panel or `true` (means global panel)
function getPanelByPoint(controller, e, localCursorPoint) {
    var panels = controller._panels;
    if (!panels) {
        return true; // Global panel
    }
    var panel;
    var transform = controller._transform;
    each$12(panels, function (pn) {
        pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn);
    });
    return panel;
}

// Return a panel or true
function getPanelByCover(controller, cover) {
    var panels = controller._panels;
    if (!panels) {
        return true; // Global panel
    }
    var panelId = cover.__brushOption.panelId;
    // User may give cover without coord sys info,
    // which is then treated as global panel.
    return panelId != null ? panels[panelId] : true;
}

function clearCovers(controller) {
    var covers = controller._covers;
    var originalLength = covers.length;
    each$12(covers, function (cover) {
        controller.group.remove(cover);
    }, controller);
    covers.length = 0;

    return !!originalLength;
}

function trigger$1(controller, opt) {
    var areas = map$2(controller._covers, function (cover) {
        var brushOption = cover.__brushOption;
        var range = clone(brushOption.range);
        return {
            brushType: brushOption.brushType,
            panelId: brushOption.panelId,
            range: range
        };
    });

    controller.trigger('brush', areas, {
        isEnd: !!opt.isEnd,
        removeOnClick: !!opt.removeOnClick
    });
}

function shouldShowCover(controller) {
    var track = controller._track;

    if (!track.length) {
        return false;
    }

    var p2 = track[track.length - 1];
    var p1 = track[0];
    var dx = p2[0] - p1[0];
    var dy = p2[1] - p1[1];
    var dist = mathPow$2(dx * dx + dy * dy, 0.5);

    return dist > UNSELECT_THRESHOLD;
}

function getTrackEnds(track) {
    var tail = track.length - 1;
    tail < 0 && (tail = 0);
    return [track[0], track[tail]];
}

function createBaseRectCover(doDrift, controller, brushOption, edgeNames) {
    var cover = new Group();

    cover.add(new Rect({
        name: 'main',
        style: makeStyle(brushOption),
        silent: true,
        draggable: true,
        cursor: 'move',
        drift: curry$2(doDrift, controller, cover, 'nswe'),
        ondragend: curry$2(trigger$1, controller, {isEnd: true})
    }));

    each$12(
        edgeNames,
        function (name) {
            cover.add(new Rect({
                name: name,
                style: {opacity: 0},
                draggable: true,
                silent: true,
                invisible: true,
                drift: curry$2(doDrift, controller, cover, name),
                ondragend: curry$2(trigger$1, controller, {isEnd: true})
            }));
        }
    );

    return cover;
}

function updateBaseRect(controller, cover, localRange, brushOption) {
    var lineWidth = brushOption.brushStyle.lineWidth || 0;
    var handleSize = mathMax$7(lineWidth, MIN_RESIZE_LINE_WIDTH);
    var x = localRange[0][0];
    var y = localRange[1][0];
    var xa = x - lineWidth / 2;
    var ya = y - lineWidth / 2;
    var x2 = localRange[0][1];
    var y2 = localRange[1][1];
    var x2a = x2 - handleSize + lineWidth / 2;
    var y2a = y2 - handleSize + lineWidth / 2;
    var width = x2 - x;
    var height = y2 - y;
    var widtha = width + lineWidth;
    var heighta = height + lineWidth;

    updateRectShape(controller, cover, 'main', x, y, width, height);

    if (brushOption.transformable) {
        updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta);
        updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta);
        updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize);
        updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize);

        updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize);
        updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize);
        updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize);
        updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize);
    }
}

function updateCommon(controller, cover) {
    var brushOption = cover.__brushOption;
    var transformable = brushOption.transformable;

    var mainEl = cover.childAt(0);
    mainEl.useStyle(makeStyle(brushOption));
    mainEl.attr({
        silent: !transformable,
        cursor: transformable ? 'move' : 'default'
    });

    each$12(
        ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'],
        function (name) {
            var el = cover.childOfName(name);
            var globalDir = getGlobalDirection(controller, name);

            el && el.attr({
                silent: !transformable,
                invisible: !transformable,
                cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null
            });
        }
    );
}

function updateRectShape(controller, cover, name, x, y, w, h) {
    var el = cover.childOfName(name);
    el && el.setShape(pointsToRect(
        clipByPanel(controller, cover, [[x, y], [x + w, y + h]])
    ));
}

function makeStyle(brushOption) {
    return defaults({strokeNoScale: true}, brushOption.brushStyle);
}

function formatRectRange(x, y, x2, y2) {
    var min = [mathMin$7(x, x2), mathMin$7(y, y2)];
    var max = [mathMax$7(x, x2), mathMax$7(y, y2)];

    return [
        [min[0], max[0]], // x range
        [min[1], max[1]] // y range
    ];
}

function getTransform$1(controller) {
    return getTransform(controller.group);
}

function getGlobalDirection(controller, localDirection) {
    if (localDirection.length > 1) {
        localDirection = localDirection.split('');
        var globalDir = [
            getGlobalDirection(controller, localDirection[0]),
            getGlobalDirection(controller, localDirection[1])
        ];
        (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse();
        return globalDir.join('');
    }
    else {
        var map$$1 = {w: 'left', e: 'right', n: 'top', s: 'bottom'};
        var inverseMap = {left: 'w', right: 'e', top: 'n', bottom: 's'};
        var globalDir = transformDirection(
            map$$1[localDirection], getTransform$1(controller)
        );
        return inverseMap[globalDir];
    }
}

function driftRect(toRectRange, fromRectRange, controller, cover, name, dx, dy, e) {
    var brushOption = cover.__brushOption;
    var rectRange = toRectRange(brushOption.range);
    var localDelta = toLocalDelta(controller, dx, dy);

    each$12(name.split(''), function (namePart) {
        var ind = DIRECTION_MAP[namePart];
        rectRange[ind[0]][ind[1]] += localDelta[ind[0]];
    });

    brushOption.range = fromRectRange(formatRectRange(
        rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]
    ));

    updateCoverAfterCreation(controller, cover);
    trigger$1(controller, {isEnd: false});
}

function driftPolygon(controller, cover, dx, dy, e) {
    var range = cover.__brushOption.range;
    var localDelta = toLocalDelta(controller, dx, dy);

    each$12(range, function (point) {
        point[0] += localDelta[0];
        point[1] += localDelta[1];
    });

    updateCoverAfterCreation(controller, cover);
    trigger$1(controller, {isEnd: false});
}

function toLocalDelta(controller, dx, dy) {
    var thisGroup = controller.group;
    var localD = thisGroup.transformCoordToLocal(dx, dy);
    var localZero = thisGroup.transformCoordToLocal(0, 0);

    return [localD[0] - localZero[0], localD[1] - localZero[1]];
}

function clipByPanel(controller, cover, data) {
    var panel = getPanelByCover(controller, cover);

    return (panel && panel !== true)
        ? panel.clipPath(data, controller._transform)
        : clone(data);
}

function pointsToRect(points) {
    var xmin = mathMin$7(points[0][0], points[1][0]);
    var ymin = mathMin$7(points[0][1], points[1][1]);
    var xmax = mathMax$7(points[0][0], points[1][0]);
    var ymax = mathMax$7(points[0][1], points[1][1]);

    return {
        x: xmin,
        y: ymin,
        width: xmax - xmin,
        height: ymax - ymin
    };
}

function resetCursor(controller, e, localCursorPoint) {
    // Check active
    if (!controller._brushType) {
        return;
    }

    var zr = controller._zr;
    var covers = controller._covers;
    var currPanel = getPanelByPoint(controller, e, localCursorPoint);

    // Check whether in covers.
    if (!controller._dragging) {
        for (var i = 0; i < covers.length; i++) {
            var brushOption = covers[i].__brushOption;
            if (currPanel
                && (currPanel === true || brushOption.panelId === currPanel.panelId)
                && coverRenderers[brushOption.brushType].contain(
                    covers[i], localCursorPoint[0], localCursorPoint[1]
                )
            ) {
                // Use cursor style set on cover.
                return;
            }
        }
    }

    currPanel && zr.setCursorStyle('crosshair');
}

function preventDefault(e) {
    var rawE = e.event;
    rawE.preventDefault && rawE.preventDefault();
}

function mainShapeContain(cover, x, y) {
    return cover.childOfName('main').contain(x, y);
}

function updateCoverByMouse(controller, e, localCursorPoint, isEnd) {
    var creatingCover = controller._creatingCover;
    var panel = controller._creatingPanel;
    var thisBrushOption = controller._brushOption;
    var eventParams;

    controller._track.push(localCursorPoint.slice());

    if (shouldShowCover(controller) || creatingCover) {

        if (panel && !creatingCover) {
            thisBrushOption.brushMode === 'single' && clearCovers(controller);
            var brushOption = clone(thisBrushOption);
            brushOption.brushType = determineBrushType(brushOption.brushType, panel);
            brushOption.panelId = panel === true ? null : panel.panelId;
            creatingCover = controller._creatingCover = createCover(controller, brushOption);
            controller._covers.push(creatingCover);
        }

        if (creatingCover) {
            var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)];
            var coverBrushOption = creatingCover.__brushOption;

            coverBrushOption.range = coverRenderer.getCreatingRange(
                clipByPanel(controller, creatingCover, controller._track)
            );

            if (isEnd) {
                endCreating(controller, creatingCover);
                coverRenderer.updateCommon(controller, creatingCover);
            }

            updateCoverShape(controller, creatingCover);

            eventParams = {isEnd: isEnd};
        }
    }
    else if (
        isEnd
        && thisBrushOption.brushMode === 'single'
        && thisBrushOption.removeOnClick
    ) {
        // Help user to remove covers easily, only by a tiny drag, in 'single' mode.
        // But a single click do not clear covers, because user may have casual
        // clicks (for example, click on other component and do not expect covers
        // disappear).
        // Only some cover removed, trigger action, but not every click trigger action.
        if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) {
            eventParams = {isEnd: isEnd, removeOnClick: true};
        }
    }

    return eventParams;
}

function determineBrushType(brushType, panel) {
    if (brushType === 'auto') {
        if (__DEV__) {
            assert$1(
                panel && panel.defaultBrushType,
                'MUST have defaultBrushType when brushType is "atuo"'
            );
        }
        return panel.defaultBrushType;
    }
    return brushType;
}

var mouseHandlers = {

    mousedown: function (e) {
        if (this._dragging) {
            // In case some browser do not support globalOut,
            // and release mose out side the browser.
            handleDragEnd(this, e);
        }
        else if (!e.target || !e.target.draggable) {

            preventDefault(e);

            var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);

            this._creatingCover = null;
            var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint);

            if (panel) {
                this._dragging = true;
                this._track = [localCursorPoint.slice()];
            }
        }
    },

    mousemove: function (e) {
        var lastPoint = this._lastMouseMovePoint;
        lastPoint.x = e.offsetX;
        lastPoint.y = e.offsetY;

        var localCursorPoint = this.group.transformCoordToLocal(lastPoint.x, lastPoint.y);

        resetCursor(this, e, localCursorPoint);

        if (this._dragging) {

            preventDefault(e);

            var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);

            eventParams && trigger$1(this, eventParams);
        }
    },

    mouseup: function (e) {
        handleDragEnd(this, e);
    },

    globalout: function (e) {
        handleDragEnd(this, e, true);
    }
};

function handleDragEnd(controller, e, isGlobalOut) {
    if (controller._dragging) {

        // Just be worried about bring some side effect to the world
        // out of echarts, we do not `preventDefault` for globalout.
        !isGlobalOut && preventDefault(e);

        var pointerX = e.offsetX;
        var pointerY = e.offsetY;
        var lastPoint = controller._lastMouseMovePoint;
        if (isGlobalOut) {
            pointerX = lastPoint.x;
            pointerY = lastPoint.y;
        }

        var localCursorPoint = controller.group.transformCoordToLocal(pointerX, pointerY);
        // FIXME
        // Here `e` is used only in `onIrrelevantElement` finally. And it's OK
        // that pass the `e` of `globalout` to `onIrrelevantElement`. But it is
        // not a good design of these interfaces. However, we do not refactor
        // these code now because the implementation of `onIrrelevantElement`
        // need to be discussed and probably be changed in future, becuase it
        // slows down the performance of zrender in some cases.
        var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);

        controller._dragging = false;
        controller._track = [];
        controller._creatingCover = null;

        // trigger event shoule be at final, after procedure will be nested.
        eventParams && trigger$1(controller, eventParams);
    }
}

/**
 * key: brushType
 * @type {Object}
 */
var coverRenderers = {

    lineX: getLineRenderer(0),

    lineY: getLineRenderer(1),

    rect: {
        createCover: function (controller, brushOption) {
            return createBaseRectCover(
                curry$2(
                    driftRect,
                    function (range) {
                        return range;
                    },
                    function (range) {
                        return range;
                    }
                ),
                controller,
                brushOption,
                ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw']
            );
        },
        getCreatingRange: function (localTrack) {
            var ends = getTrackEnds(localTrack);
            return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);
        },
        updateCoverShape: function (controller, cover, localRange, brushOption) {
            updateBaseRect(controller, cover, localRange, brushOption);
        },
        updateCommon: updateCommon,
        contain: mainShapeContain
    },

    polygon: {
        createCover: function (controller, brushOption) {
            var cover = new Group();

            // Do not use graphic.Polygon because graphic.Polyline do not close the
            // border of the shape when drawing, which is a better experience for user.
            cover.add(new Polyline({
                name: 'main',
                style: makeStyle(brushOption),
                silent: true
            }));

            return cover;
        },
        getCreatingRange: function (localTrack) {
            return localTrack;
        },
        endCreating: function (controller, cover) {
            cover.remove(cover.childAt(0));
            // Use graphic.Polygon close the shape.
            cover.add(new Polygon({
                name: 'main',
                draggable: true,
                drift: curry$2(driftPolygon, controller, cover),
                ondragend: curry$2(trigger$1, controller, {isEnd: true})
            }));
        },
        updateCoverShape: function (controller, cover, localRange, brushOption) {
            cover.childAt(0).setShape({
                points: clipByPanel(controller, cover, localRange)
            });
        },
        updateCommon: updateCommon,
        contain: mainShapeContain
    }
};

function getLineRenderer(xyIndex) {
    return {
        createCover: function (controller, brushOption) {
            return createBaseRectCover(
                curry$2(
                    driftRect,
                    function (range) {
                        var rectRange = [range, [0, 100]];
                        xyIndex && rectRange.reverse();
                        return rectRange;
                    },
                    function (rectRange) {
                        return rectRange[xyIndex];
                    }
                ),
                controller,
                brushOption,
                [['w', 'e'], ['n', 's']][xyIndex]
            );
        },
        getCreatingRange: function (localTrack) {
            var ends = getTrackEnds(localTrack);
            var min = mathMin$7(ends[0][xyIndex], ends[1][xyIndex]);
            var max = mathMax$7(ends[0][xyIndex], ends[1][xyIndex]);

            return [min, max];
        },
        updateCoverShape: function (controller, cover, localRange, brushOption) {
            var otherExtent;
            // If brushWidth not specified, fit the panel.
            var panel = getPanelByCover(controller, cover);
            if (panel !== true && panel.getLinearBrushOtherExtent) {
                otherExtent = panel.getLinearBrushOtherExtent(
                    xyIndex, controller._transform
                );
            }
            else {
                var zr = controller._zr;
                otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]];
            }
            var rectRange = [localRange, otherExtent];
            xyIndex && rectRange.reverse();

            updateBaseRect(controller, cover, rectRange, brushOption);
        },
        updateCommon: updateCommon,
        contain: mainShapeContain
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function makeRectPanelClipPath(rect) {
    rect = normalizeRect(rect);
    return function (localPoints, transform) {
        return clipPointsByRect(localPoints, rect);
    };
}

function makeLinearBrushOtherExtent(rect, specifiedXYIndex) {
    rect = normalizeRect(rect);
    return function (xyIndex) {
        var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex;
        var brushWidth = idx ? rect.width : rect.height;
        var base = idx ? rect.x : rect.y;
        return [base, base + (brushWidth || 0)];
    };
}

function makeRectIsTargetByCursor(rect, api, targetModel) {
    rect = normalizeRect(rect);
    return function (e, localCursorPoint, transform) {
        return rect.contain(localCursorPoint[0], localCursorPoint[1])
            && !onIrrelevantElement(e, api, targetModel);
    };
}

// Consider width/height is negative.
function normalizeRect(rect) {
    return BoundingRect.create(rect);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var elementList = ['axisLine', 'axisTickLabel', 'axisName'];

var AxisView$2 = extendComponentView({

    type: 'parallelAxis',

    /**
     * @override
     */
    init: function (ecModel, api) {
        AxisView$2.superApply(this, 'init', arguments);

        /**
         * @type {module:echarts/component/helper/BrushController}
         */
        (this._brushController = new BrushController(api.getZr()))
            .on('brush', bind(this._onBrush, this));
    },

    /**
     * @override
     */
    render: function (axisModel, ecModel, api, payload) {
        if (fromAxisAreaSelect(axisModel, ecModel, payload)) {
            return;
        }

        this.axisModel = axisModel;
        this.api = api;

        this.group.removeAll();

        var oldAxisGroup = this._axisGroup;
        this._axisGroup = new Group();
        this.group.add(this._axisGroup);

        if (!axisModel.get('show')) {
            return;
        }

        var coordSysModel = getCoordSysModel(axisModel, ecModel);
        var coordSys = coordSysModel.coordinateSystem;

        var areaSelectStyle = axisModel.getAreaSelectStyle();
        var areaWidth = areaSelectStyle.width;

        var dim = axisModel.axis.dim;
        var axisLayout = coordSys.getAxisLayout(dim);

        var builderOpt = extend(
            {strokeContainThreshold: areaWidth},
            axisLayout
        );

        var axisBuilder = new AxisBuilder(axisModel, builderOpt);

        each$1(elementList, axisBuilder.add, axisBuilder);

        this._axisGroup.add(axisBuilder.getGroup());

        this._refreshBrushController(
            builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api
        );

        var animationModel = (payload && payload.animation === false) ? null : axisModel;
        groupTransition(oldAxisGroup, this._axisGroup, animationModel);
    },

    // /**
    //  * @override
    //  */
    // updateVisual: function (axisModel, ecModel, api, payload) {
    //     this._brushController && this._brushController
    //         .updateCovers(getCoverInfoList(axisModel));
    // },

    _refreshBrushController: function (
        builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api
    ) {
        // After filtering, axis may change, select area needs to be update.
        var extent = axisModel.axis.getExtent();
        var extentLen = extent[1] - extent[0];
        var extra = Math.min(30, Math.abs(extentLen) * 0.1); // Arbitrary value.

        // width/height might be negative, which will be
        // normalized in BoundingRect.
        var rect = BoundingRect.create({
            x: extent[0],
            y: -areaWidth / 2,
            width: extentLen,
            height: areaWidth
        });
        rect.x -= extra;
        rect.width += 2 * extra;

        this._brushController
            .mount({
                enableGlobalPan: true,
                rotation: builderOpt.rotation,
                position: builderOpt.position
            })
            .setPanels([{
                panelId: 'pl',
                clipPath: makeRectPanelClipPath(rect),
                isTargetByCursor: makeRectIsTargetByCursor(rect, api, coordSysModel),
                getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect, 0)
            }])
            .enableBrush({
                brushType: 'lineX',
                brushStyle: areaSelectStyle,
                removeOnClick: true
            })
            .updateCovers(getCoverInfoList(axisModel));
    },

    _onBrush: function (coverInfoList, opt) {
        // Do not cache these object, because the mey be changed.
        var axisModel = this.axisModel;
        var axis = axisModel.axis;
        var intervals = map(coverInfoList, function (coverInfo) {
            return [
                axis.coordToData(coverInfo.range[0], true),
                axis.coordToData(coverInfo.range[1], true)
            ];
        });

        // If realtime is true, action is not dispatched on drag end, because
        // the drag end emits the same params with the last drag move event,
        // and may have some delay when using touch pad.
        if (!axisModel.option.realtime === opt.isEnd || opt.removeOnClick) { // jshint ignore:line
            this.api.dispatchAction({
                type: 'axisAreaSelect',
                parallelAxisId: axisModel.id,
                intervals: intervals
            });
        }
    },

    /**
     * @override
     */
    dispose: function () {
        this._brushController.dispose();
    }
});

function fromAxisAreaSelect(axisModel, ecModel, payload) {
    return payload
        && payload.type === 'axisAreaSelect'
        && ecModel.findComponents(
            {mainType: 'parallelAxis', query: payload}
        )[0] === axisModel;
}

function getCoverInfoList(axisModel) {
    var axis = axisModel.axis;
    return map(axisModel.activeIntervals, function (interval) {
        return {
            brushType: 'lineX',
            panelId: 'pl',
            range: [
                axis.dataToCoord(interval[0], true),
                axis.dataToCoord(interval[1], true)
            ]
        };
    });
}

function getCoordSysModel(axisModel, ecModel) {
    return ecModel.getComponent(
        'parallel', axisModel.get('parallelIndex')
    );
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var CLICK_THRESHOLD = 5; // > 4

// Parallel view
extendComponentView({
    type: 'parallel',

    render: function (parallelModel, ecModel, api) {
        this._model = parallelModel;
        this._api = api;

        if (!this._handlers) {
            this._handlers = {};
            each$1(handlers, function (handler, eventName) {
                api.getZr().on(eventName, this._handlers[eventName] = bind(handler, this));
            }, this);
        }

        createOrUpdate(
            this,
            '_throttledDispatchExpand',
            parallelModel.get('axisExpandRate'),
            'fixRate'
        );
    },

    dispose: function (ecModel, api) {
        each$1(this._handlers, function (handler, eventName) {
            api.getZr().off(eventName, handler);
        });
        this._handlers = null;
    },

    /**
     * @param {Object} [opt] If null, cancle the last action triggering for debounce.
     */
    _throttledDispatchExpand: function (opt) {
        this._dispatchExpand(opt);
    },

    _dispatchExpand: function (opt) {
        opt && this._api.dispatchAction(
            extend({type: 'parallelAxisExpand'}, opt)
        );
    }

});

var handlers = {

    mousedown: function (e) {
        if (checkTrigger(this, 'click')) {
            this._mouseDownPoint = [e.offsetX, e.offsetY];
        }
    },

    mouseup: function (e) {
        var mouseDownPoint = this._mouseDownPoint;

        if (checkTrigger(this, 'click') && mouseDownPoint) {
            var point = [e.offsetX, e.offsetY];
            var dist = Math.pow(mouseDownPoint[0] - point[0], 2)
                + Math.pow(mouseDownPoint[1] - point[1], 2);

            if (dist > CLICK_THRESHOLD) {
                return;
            }

            var result = this._model.coordinateSystem.getSlidedAxisExpandWindow(
                [e.offsetX, e.offsetY]
            );

            result.behavior !== 'none' && this._dispatchExpand({
                axisExpandWindow: result.axisExpandWindow
            });
        }

        this._mouseDownPoint = null;
    },

    mousemove: function (e) {
        // Should do nothing when brushing.
        if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) {
            return;
        }
        var model = this._model;
        var result = model.coordinateSystem.getSlidedAxisExpandWindow(
            [e.offsetX, e.offsetY]
        );

        var behavior = result.behavior;
        behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce'));
        this._throttledDispatchExpand(
            behavior === 'none'
                ? null // Cancle the last trigger, in case that mouse slide out of the area quickly.
                : {
                    axisExpandWindow: result.axisExpandWindow,
                    // Jumping uses animation, and sliding suppresses animation.
                    animation: behavior === 'jump' ? null : false
                }
        );
    }
};

function checkTrigger(view, triggerOn) {
    var model = view._model;
    return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn;
}

registerPreprocessor(parallelPreprocessor);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.parallel',

    dependencies: ['parallel'],

    visualColorAccessPath: 'lineStyle.color',

    getInitialData: function (option, ecModel) {
        var source = this.getSource();

        setEncodeAndDimensions(source, this);

        return createListFromArray(source, this);
    },

    /**
     * User can get data raw indices on 'axisAreaSelected' event received.
     *
     * @public
     * @param {string} activeState 'active' or 'inactive' or 'normal'
     * @return {Array.<number>} Raw indices
     */
    getRawIndicesByActiveState: function (activeState) {
        var coordSys = this.coordinateSystem;
        var data = this.getData();
        var indices = [];

        coordSys.eachActiveState(data, function (theActiveState, dataIndex) {
            if (activeState === theActiveState) {
                indices.push(data.getRawIndex(dataIndex));
            }
        });

        return indices;
    },

    defaultOption: {
        zlevel: 0,                  // 一级层叠
        z: 2,                       // 二级层叠

        coordinateSystem: 'parallel',
        parallelIndex: 0,

        label: {
            show: false
        },

        inactiveOpacity: 0.05,
        activeOpacity: 1,

        lineStyle: {
            width: 1,
            opacity: 0.45,
            type: 'solid'
        },
        emphasis: {
            label: {
                show: false
            }
        },

        progressive: 500,
        smooth: false, // true | false | number

        animationEasing: 'linear'
    }
});

function setEncodeAndDimensions(source, seriesModel) {
    // The mapping of parallelAxis dimension to data dimension can
    // be specified in parallelAxis.option.dim. For example, if
    // parallelAxis.option.dim is 'dim3', it mapping to the third
    // dimension of data. But `data.encode` has higher priority.
    // Moreover, parallelModel.dimension should not be regarded as data
    // dimensions. Consider dimensions = ['dim4', 'dim2', 'dim6'];

    if (source.encodeDefine) {
        return;
    }

    var parallelModel = seriesModel.ecModel.getComponent(
        'parallel', seriesModel.get('parallelIndex')
    );
    if (!parallelModel) {
        return;
    }

    var encodeDefine = source.encodeDefine = createHashMap();
    each$1(parallelModel.dimensions, function (axisDim) {
        var dataDimIndex = convertDimNameToNumber(axisDim);
        encodeDefine.set(axisDim, dataDimIndex);
    });
}

function convertDimNameToNumber(dimName) {
    return +dimName.replace('dim', '');
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DEFAULT_SMOOTH = 0.3;

var ParallelView = Chart.extend({

    type: 'parallel',

    init: function () {

        /**
         * @type {module:zrender/container/Group}
         * @private
         */
        this._dataGroup = new Group();

        this.group.add(this._dataGroup);

        /**
         * @type {module:echarts/data/List}
         */
        this._data;

        /**
         * @type {boolean}
         */
        this._initialized;
    },

    /**
     * @override
     */
    render: function (seriesModel, ecModel, api, payload) {
        var dataGroup = this._dataGroup;
        var data = seriesModel.getData();
        var oldData = this._data;
        var coordSys = seriesModel.coordinateSystem;
        var dimensions = coordSys.dimensions;
        var seriesScope = makeSeriesScope$2(seriesModel);

        data.diff(oldData)
            .add(add)
            .update(update)
            .remove(remove)
            .execute();

        function add(newDataIndex) {
            var line = addEl(data, dataGroup, newDataIndex, dimensions, coordSys);
            updateElCommon(line, data, newDataIndex, seriesScope);
        }

        function update(newDataIndex, oldDataIndex) {
            var line = oldData.getItemGraphicEl(oldDataIndex);
            var points = createLinePoints(data, newDataIndex, dimensions, coordSys);
            data.setItemGraphicEl(newDataIndex, line);
            var animationModel = (payload && payload.animation === false) ? null : seriesModel;
            updateProps(line, {shape: {points: points}}, animationModel, newDataIndex);

            updateElCommon(line, data, newDataIndex, seriesScope);
        }

        function remove(oldDataIndex) {
            var line = oldData.getItemGraphicEl(oldDataIndex);
            dataGroup.remove(line);
        }

        // First create
        if (!this._initialized) {
            this._initialized = true;
            var clipPath = createGridClipShape(
                coordSys, seriesModel, function () {
                    // Callback will be invoked immediately if there is no animation
                    setTimeout(function () {
                        dataGroup.removeClipPath();
                    });
                }
            );
            dataGroup.setClipPath(clipPath);
        }

        this._data = data;
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        this._initialized = true;
        this._data = null;
        this._dataGroup.removeAll();
    },

    incrementalRender: function (taskParams, seriesModel, ecModel) {
        var data = seriesModel.getData();
        var coordSys = seriesModel.coordinateSystem;
        var dimensions = coordSys.dimensions;
        var seriesScope = makeSeriesScope$2(seriesModel);

        for (var dataIndex = taskParams.start; dataIndex < taskParams.end; dataIndex++) {
            var line = addEl(data, this._dataGroup, dataIndex, dimensions, coordSys);
            line.incremental = true;
            updateElCommon(line, data, dataIndex, seriesScope);
        }
    },

    dispose: function () {},

    // _renderForProgressive: function (seriesModel) {
    //     var dataGroup = this._dataGroup;
    //     var data = seriesModel.getData();
    //     var oldData = this._data;
    //     var coordSys = seriesModel.coordinateSystem;
    //     var dimensions = coordSys.dimensions;
    //     var option = seriesModel.option;
    //     var progressive = option.progressive;
    //     var smooth = option.smooth ? SMOOTH : null;

    //     // In progressive animation is disabled, so use simple data diff,
    //     // which effects performance less.
    //     // (Typically performance for data with length 7000+ like:
    //     // simpleDiff: 60ms, addEl: 184ms,
    //     // in RMBP 2.4GHz intel i7, OSX 10.9 chrome 50.0.2661.102 (64-bit))
    //     if (simpleDiff(oldData, data, dimensions)) {
    //         dataGroup.removeAll();
    //         data.each(function (dataIndex) {
    //             addEl(data, dataGroup, dataIndex, dimensions, coordSys);
    //         });
    //     }

    //     updateElCommon(data, progressive, smooth);

    //     // Consider switch between progressive and not.
    //     data.__plProgressive = true;
    //     this._data = data;
    // },

    /**
     * @override
     */
    remove: function () {
        this._dataGroup && this._dataGroup.removeAll();
        this._data = null;
    }
});

function createGridClipShape(coordSys, seriesModel, cb) {
    var parallelModel = coordSys.model;
    var rect = coordSys.getRect();
    var rectEl = new Rect({
        shape: {
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
        }
    });

    var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height';
    rectEl.setShape(dim, 0);
    initProps(rectEl, {
        shape: {
            width: rect.width,
            height: rect.height
        }
    }, seriesModel, cb);
    return rectEl;
}

function createLinePoints(data, dataIndex, dimensions, coordSys) {
    var points = [];
    for (var i = 0; i < dimensions.length; i++) {
        var dimName = dimensions[i];
        var value = data.get(data.mapDimension(dimName), dataIndex);
        if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) {
            points.push(coordSys.dataToPoint(value, dimName));
        }
    }
    return points;
}

function addEl(data, dataGroup, dataIndex, dimensions, coordSys) {
    var points = createLinePoints(data, dataIndex, dimensions, coordSys);
    var line = new Polyline({
        shape: {points: points},
        silent: true,
        z2: 10
    });
    dataGroup.add(line);
    data.setItemGraphicEl(dataIndex, line);
    return line;
}

function makeSeriesScope$2(seriesModel) {
    var smooth = seriesModel.get('smooth', true);
    smooth === true && (smooth = DEFAULT_SMOOTH);
    return {
        lineStyle: seriesModel.getModel('lineStyle').getLineStyle(),
        smooth: smooth != null ? smooth : DEFAULT_SMOOTH
    };
}

function updateElCommon(el, data, dataIndex, seriesScope) {
    var lineStyle = seriesScope.lineStyle;

    if (data.hasItemOption) {
        var lineStyleModel = data.getItemModel(dataIndex).getModel('lineStyle');
        lineStyle = lineStyleModel.getLineStyle();
    }

    el.useStyle(lineStyle);

    var elStyle = el.style;
    elStyle.fill = null;
    // lineStyle.color have been set to itemVisual in module:echarts/visual/seriesColor.
    elStyle.stroke = data.getItemVisual(dataIndex, 'color');
    // lineStyle.opacity have been set to itemVisual in parallelVisual.
    elStyle.opacity = data.getItemVisual(dataIndex, 'opacity');

    seriesScope.smooth && (el.shape.smooth = seriesScope.smooth);
}

// function simpleDiff(oldData, newData, dimensions) {
//     var oldLen;
//     if (!oldData
//         || !oldData.__plProgressive
//         || (oldLen = oldData.count()) !== newData.count()
//     ) {
//         return true;
//     }

//     var dimLen = dimensions.length;
//     for (var i = 0; i < oldLen; i++) {
//         for (var j = 0; j < dimLen; j++) {
//             if (oldData.get(dimensions[j], i) !== newData.get(dimensions[j], i)) {
//                 return true;
//             }
//         }
//     }

//     return false;
// }

// FIXME
// 公用方法?
function isEmptyValue(val, axisType) {
    return axisType === 'category'
        ? val == null
        : (val == null || isNaN(val)); // axisType === 'value'
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var opacityAccessPath$1 = ['lineStyle', 'normal', 'opacity'];

var parallelVisual = {

    seriesType: 'parallel',

    reset: function (seriesModel, ecModel, api) {

        var itemStyleModel = seriesModel.getModel('itemStyle');
        var lineStyleModel = seriesModel.getModel('lineStyle');
        var globalColors = ecModel.get('color');

        var color = lineStyleModel.get('color')
            || itemStyleModel.get('color')
            || globalColors[seriesModel.seriesIndex % globalColors.length];
        var inactiveOpacity = seriesModel.get('inactiveOpacity');
        var activeOpacity = seriesModel.get('activeOpacity');
        var lineStyle = seriesModel.getModel('lineStyle').getLineStyle();

        var coordSys = seriesModel.coordinateSystem;
        var data = seriesModel.getData();

        var opacityMap = {
            normal: lineStyle.opacity,
            active: activeOpacity,
            inactive: inactiveOpacity
        };

        data.setVisual('color', color);

        function progress(params, data) {
            coordSys.eachActiveState(data, function (activeState, dataIndex) {
                var opacity = opacityMap[activeState];
                if (activeState === 'normal' && data.hasItemOption) {
                    var itemOpacity = data.getItemModel(dataIndex).get(opacityAccessPath$1, true);
                    itemOpacity != null && (opacity = itemOpacity);
                }
                data.setItemVisual(dataIndex, 'opacity', opacity);
            }, params.start, params.end);
        }

        return {progress: progress};
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(parallelVisual);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var SankeySeries = SeriesModel.extend({

    type: 'series.sankey',

    layoutInfo: null,

    levelModels: null,

    /**
     * Init a graph data structure from data in option series
     *
     * @param  {Object} option  the object used to config echarts view
     * @return {module:echarts/data/List} storage initial data
     */
    getInitialData: function (option, ecModel) {
        var links = option.edges || option.links;
        var nodes = option.data || option.nodes;
        var levels = option.levels;
        var levelModels = this.levelModels = {};

        for (var i = 0; i < levels.length; i++) {
            if (levels[i].depth != null && levels[i].depth >= 0) {
                levelModels[levels[i].depth] = new Model(levels[i], this, ecModel);
            }
            else {
                if (__DEV__) {
                    throw new Error('levels[i].depth is mandatory and should be natural number');
                }
            }
        }
        if (nodes && links) {
            var graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink);
            return graph.data;
        }
        function beforeLink(nodeData, edgeData) {
            nodeData.wrapMethod('getItemModel', function (model, idx) {
                model.customizeGetParent(function (path) {
                    var parentModel = this.parentModel;
                    var nodeDepth = parentModel.getData().getItemLayout(idx).depth;
                    var levelModel = parentModel.levelModels[nodeDepth];
                    return levelModel || this.parentModel;
                });
                return model;
            });

            edgeData.wrapMethod('getItemModel', function (model, idx) {
                model.customizeGetParent(function (path) {
                    var parentModel = this.parentModel;
                    var edge = parentModel.getGraph().getEdgeByIndex(idx);
                    var depth = edge.node1.getLayout().depth;
                    var levelModel = parentModel.levelModels[depth];
                    return levelModel || this.parentModel;
                });
                return model;
            });
        }
    },

    setNodePosition: function (dataIndex, localPosition) {
        var dataItem = this.option.data[dataIndex];
        dataItem.localX = localPosition[0];
        dataItem.localY = localPosition[1];
    },

    /**
     * Return the graphic data structure
     *
     * @return {module:echarts/data/Graph} graphic data structure
     */
    getGraph: function () {
        return this.getData().graph;
    },

    /**
     * Get edge data of graphic data structure
     *
     * @return {module:echarts/data/List} data structure of list
     */
    getEdgeData: function () {
        return this.getGraph().edgeData;
    },

    /**
     * @override
     */
    formatTooltip: function (dataIndex, multipleSeries, dataType) {
        // dataType === 'node' or empty do not show tooltip by default
        if (dataType === 'edge') {
            var params = this.getDataParams(dataIndex, dataType);
            var rawDataOpt = params.data;
            var html = rawDataOpt.source + ' -- ' + rawDataOpt.target;
            if (params.value) {
                html += ' : ' + params.value;
            }
            return encodeHTML(html);
        }
        else if (dataType === 'node') {
            var node = this.getGraph().getNodeByIndex(dataIndex);
            var value = node.getLayout().value;
            var name = this.getDataParams(dataIndex, dataType).data.name;
            if (value) {
                var html = name + ' : ' + value;
            }
            return encodeHTML(html);
        }
        return SankeySeries.superCall(this, 'formatTooltip', dataIndex, multipleSeries);
    },

    optionUpdated: function () {
        var option = this.option;
        if (option.focusNodeAdjacency === true) {
            option.focusNodeAdjacency = 'allEdges';
        }
    },

    defaultOption: {
        zlevel: 0,
        z: 2,

        coordinateSystem: 'view',

        layout: null,

        // The position of the whole view
        left: '5%',
        top: '5%',
        right: '20%',
        bottom: '5%',

        // Value can be 'vertical'
        orient: 'horizontal',

        // The dx of the node
        nodeWidth: 20,

        // The vertical distance between two nodes
        nodeGap: 8,

        // Control if the node can move or not
        draggable: true,

        // Value can be 'inEdges', 'outEdges', 'allEdges', true (the same as 'allEdges').
        focusNodeAdjacency: false,

        // The number of iterations to change the position of the node
        layoutIterations: 32,

        label: {
            show: true,
            position: 'right',
            color: '#000',
            fontSize: 12
        },

        levels: [],

        // Value can be 'left' or 'right'
        nodeAlign: 'justify',

        itemStyle: {
            borderWidth: 1,
            borderColor: '#333'
        },

        lineStyle: {
            color: '#314656',
            opacity: 0.2,
            curveness: 0.5
        },

        emphasis: {
            label: {
                show: true
            },
            lineStyle: {
                opacity: 0.6
            }
        },

        animationEasing: 'linear',

        animationDuration: 1000
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var nodeOpacityPath$1 = ['itemStyle', 'opacity'];
var lineOpacityPath$1 = ['lineStyle', 'opacity'];

function getItemOpacity$1(item, opacityPath) {
    return item.getVisual('opacity') || item.getModel().get(opacityPath);
}

function fadeOutItem$1(item, opacityPath, opacityRatio) {
    var el = item.getGraphicEl();

    var opacity = getItemOpacity$1(item, opacityPath);
    if (opacityRatio != null) {
        opacity == null && (opacity = 1);
        opacity *= opacityRatio;
    }

    el.downplay && el.downplay();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

function fadeInItem$1(item, opacityPath) {
    var opacity = getItemOpacity$1(item, opacityPath);
    var el = item.getGraphicEl();

    el.highlight && el.highlight();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

var SankeyShape = extendShape({
    shape: {
        x1: 0, y1: 0,
        x2: 0, y2: 0,
        cpx1: 0, cpy1: 0,
        cpx2: 0, cpy2: 0,
        extent: 0,
        orient: ''
    },

    buildPath: function (ctx, shape) {
        var extent = shape.extent;
        ctx.moveTo(shape.x1, shape.y1);
        ctx.bezierCurveTo(
            shape.cpx1, shape.cpy1,
            shape.cpx2, shape.cpy2,
            shape.x2, shape.y2
        );
        if (shape.orient === 'vertical') {
            ctx.lineTo(shape.x2 + extent, shape.y2);
            ctx.bezierCurveTo(
                shape.cpx2 + extent, shape.cpy2,
                shape.cpx1 + extent, shape.cpy1,
                shape.x1 + extent, shape.y1
            );
        }
        else {
            ctx.lineTo(shape.x2, shape.y2 + extent);
            ctx.bezierCurveTo(
                shape.cpx2, shape.cpy2 + extent,
                shape.cpx1, shape.cpy1 + extent,
                shape.x1, shape.y1 + extent
            );
        }
        ctx.closePath();
    }
});

extendChartView({

    type: 'sankey',

    /**
     * @private
     * @type {module:echarts/chart/sankey/SankeySeries}
     */
    _model: null,

    /**
     * @private
     * @type {boolean}
     */
    _focusAdjacencyDisabled: false,

    render: function (seriesModel, ecModel, api) {
        var sankeyView = this;
        var graph = seriesModel.getGraph();
        var group = this.group;
        var layoutInfo = seriesModel.layoutInfo;
        // view width
        var width = layoutInfo.width;
        // view height
        var height = layoutInfo.height;
        var nodeData = seriesModel.getData();
        var edgeData = seriesModel.getData('edge');
        var orient = seriesModel.get('orient');

        this._model = seriesModel;

        group.removeAll();

        group.attr('position', [layoutInfo.x, layoutInfo.y]);

        // generate a bezire Curve for each edge
        graph.eachEdge(function (edge) {
            var curve = new SankeyShape();
            curve.dataIndex = edge.dataIndex;
            curve.seriesIndex = seriesModel.seriesIndex;
            curve.dataType = 'edge';
            var lineStyleModel = edge.getModel('lineStyle');
            var curvature = lineStyleModel.get('curveness');
            var n1Layout = edge.node1.getLayout();
            var node1Model = edge.node1.getModel();
            var dragX1 = node1Model.get('localX');
            var dragY1 = node1Model.get('localY');
            var n2Layout = edge.node2.getLayout();
            var node2Model = edge.node2.getModel();
            var dragX2 = node2Model.get('localX');
            var dragY2 = node2Model.get('localY');
            var edgeLayout = edge.getLayout();
            var x1;
            var y1;
            var x2;
            var y2;
            var cpx1;
            var cpy1;
            var cpx2;
            var cpy2;

            curve.shape.extent = Math.max(1, edgeLayout.dy);
            curve.shape.orient = orient;

            if (orient === 'vertical') {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy;
                x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty;
                y2 = dragY2 != null ? dragY2 * height : n2Layout.y;
                cpx1 = x1;
                cpy1 = y1 * (1 - curvature) + y2 * curvature;
                cpx2 = x2;
                cpy2 = y1 * curvature + y2 * (1 - curvature);
            }
            else {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy;
                x2 = dragX2 != null ? dragX2 * width : n2Layout.x;
                y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty;
                cpx1 = x1 * (1 - curvature) + x2 * curvature;
                cpy1 = y1;
                cpx2 = x1 * curvature + x2 * (1 - curvature);
                cpy2 = y2;
            }

            curve.setShape({
                x1: x1,
                y1: y1,
                x2: x2,
                y2: y2,
                cpx1: cpx1,
                cpy1: cpy1,
                cpx2: cpx2,
                cpy2: cpy2
            });

            curve.setStyle(lineStyleModel.getItemStyle());
            // Special color, use source node color or target node color
            switch (curve.style.fill) {
                case 'source':
                    curve.style.fill = edge.node1.getVisual('color');
                    break;
                case 'target':
                    curve.style.fill = edge.node2.getVisual('color');
                    break;
            }

            setHoverStyle(curve, edge.getModel('emphasis.lineStyle').getItemStyle());

            group.add(curve);

            edgeData.setItemGraphicEl(edge.dataIndex, curve);
        });

        // Generate a rect for each node
        graph.eachNode(function (node) {
            var layout = node.getLayout();
            var itemModel = node.getModel();
            var dragX = itemModel.get('localX');
            var dragY = itemModel.get('localY');
            var labelModel = itemModel.getModel('label');
            var labelHoverModel = itemModel.getModel('emphasis.label');

            var rect = new Rect({
                shape: {
                    x: dragX != null ? dragX * width : layout.x,
                    y: dragY != null ? dragY * height : layout.y,
                    width: layout.dx,
                    height: layout.dy
                },
                style: itemModel.getModel('itemStyle').getItemStyle()
            });

            var hoverStyle = node.getModel('emphasis.itemStyle').getItemStyle();

            setLabelStyle(
                rect.style, hoverStyle, labelModel, labelHoverModel,
                {
                    labelFetcher: seriesModel,
                    labelDataIndex: node.dataIndex,
                    defaultText: node.id,
                    isRectText: true
                }
            );

            rect.setStyle('fill', node.getVisual('color'));

            setHoverStyle(rect, hoverStyle);

            group.add(rect);

            nodeData.setItemGraphicEl(node.dataIndex, rect);

            rect.dataType = 'node';
        });

        nodeData.eachItemGraphicEl(function (el, dataIndex) {
            var itemModel = nodeData.getItemModel(dataIndex);
            if (itemModel.get('draggable')) {
                el.drift = function (dx, dy) {
                    sankeyView._focusAdjacencyDisabled = true;
                    this.shape.x += dx;
                    this.shape.y += dy;
                    this.dirty();
                    api.dispatchAction({
                        type: 'dragNode',
                        seriesId: seriesModel.id,
                        dataIndex: nodeData.getRawIndex(dataIndex),
                        localX: this.shape.x / width,
                        localY: this.shape.y / height
                    });
                };
                el.ondragend = function () {
                    sankeyView._focusAdjacencyDisabled = false;
                };
                el.draggable = true;
                el.cursor = 'move';
            }

            if (itemModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            dataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        api.dispatchAction({
                            type: 'unfocusNodeAdjacency',
                            seriesId: seriesModel.id
                        });
                    }
                });
            }
        });

        edgeData.eachItemGraphicEl(function (el, dataIndex) {
            var edgeModel = edgeData.getItemModel(dataIndex);
            if (edgeModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            edgeDataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        api.dispatchAction({
                            type: 'unfocusNodeAdjacency',
                            seriesId: seriesModel.id
                        });
                    }
                });
            }
        });

        if (!this._data && seriesModel.get('animation')) {
            group.setClipPath(createGridClipShape$1(group.getBoundingRect(), seriesModel, function () {
                group.removeClipPath();
            }));
        }

        this._data = seriesModel.getData();
    },

    dispose: function () {},

    focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var data = this._model.getData();
        var graph = data.graph;
        var dataIndex = payload.dataIndex;
        var itemModel = data.getItemModel(dataIndex);
        var edgeDataIndex = payload.edgeDataIndex;

        if (dataIndex == null && edgeDataIndex == null) {
            return;
        }
        var node = graph.getNodeByIndex(dataIndex);
        var edge = graph.getEdgeByIndex(edgeDataIndex);

        graph.eachNode(function (node) {
            fadeOutItem$1(node, nodeOpacityPath$1, 0.1);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem$1(edge, lineOpacityPath$1, 0.1);
        });

        if (node) {
            fadeInItem$1(node, nodeOpacityPath$1);
            var focusNodeAdj = itemModel.get('focusNodeAdjacency');
            if (focusNodeAdj === 'outEdges') {
                each$1(node.outEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem$1(edge, lineOpacityPath$1);
                    fadeInItem$1(edge.node2, nodeOpacityPath$1);
                });
            }
            else if (focusNodeAdj === 'inEdges') {
                each$1(node.inEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem$1(edge, lineOpacityPath$1);
                    fadeInItem$1(edge.node1, nodeOpacityPath$1);
                });
            }
            else if (focusNodeAdj === 'allEdges') {
                each$1(node.edges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem$1(edge, lineOpacityPath$1);
                    fadeInItem$1(edge.node1, nodeOpacityPath$1);
                    fadeInItem$1(edge.node2, nodeOpacityPath$1);
                });
            }
        }
        if (edge) {
            fadeInItem$1(edge, lineOpacityPath$1);
            fadeInItem$1(edge.node1, nodeOpacityPath$1);
            fadeInItem$1(edge.node2, nodeOpacityPath$1);
        }
    },

    unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var graph = this._model.getGraph();

        graph.eachNode(function (node) {
            fadeOutItem$1(node, nodeOpacityPath$1);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem$1(edge, lineOpacityPath$1);
        });
    }
});

// Add animation to the view
function createGridClipShape$1(rect, seriesModel, cb) {
    var rectEl = new Rect({
        shape: {
            x: rect.x - 10,
            y: rect.y - 10,
            width: 0,
            height: rect.height + 20
        }
    });
    initProps(rectEl, {
        shape: {
            width: rect.width + 20,
            height: rect.height + 20
        }
    }, seriesModel, cb);

    return rectEl;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerAction({
    type: 'dragNode',
    event: 'dragnode',
    // here can only use 'update' now, other value is not support in echarts.
    update: 'update'
}, function (payload, ecModel) {
    ecModel.eachComponent({mainType: 'series', subType: 'sankey', query: payload}, function (seriesModel) {
        seriesModel.setNodePosition(payload.dataIndex, [payload.localX, payload.localY]);
    });
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var sankeyLayout = function (ecModel, api, payload) {

    ecModel.eachSeriesByType('sankey', function (seriesModel) {

        var nodeWidth = seriesModel.get('nodeWidth');
        var nodeGap = seriesModel.get('nodeGap');

        var layoutInfo = getViewRect$3(seriesModel, api);

        seriesModel.layoutInfo = layoutInfo;

        var width = layoutInfo.width;
        var height = layoutInfo.height;

        var graph = seriesModel.getGraph();

        var nodes = graph.nodes;
        var edges = graph.edges;

        computeNodeValues(nodes);

        var filteredNodes = filter(nodes, function (node) {
            return node.getLayout().value === 0;
        });

        var iterations = filteredNodes.length !== 0 ? 0 : seriesModel.get('layoutIterations');

        var orient = seriesModel.get('orient');

        var nodeAlign = seriesModel.get('nodeAlign');

        layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign);
    });
};

/**
 * Get the layout position of the whole view
 *
 * @param {module:echarts/model/Series} seriesModel  the model object of sankey series
 * @param {module:echarts/ExtensionAPI} api  provide the API list that the developer can call
 * @return {module:zrender/core/BoundingRect}  size of rect to draw the sankey view
 */
function getViewRect$3(seriesModel, api) {
    return getLayoutRect(
        seriesModel.getBoxLayoutParams(), {
            width: api.getWidth(),
            height: api.getHeight()
        }
    );
}

function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign) {
    computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign);
    computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient);
    computeEdgeDepths(nodes, orient);
}

/**
 * Compute the value of each node by summing the associated edge's value
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 */
function computeNodeValues(nodes) {
    each$1(nodes, function (node) {
        var value1 = sum(node.outEdges, getEdgeValue);
        var value2 = sum(node.inEdges, getEdgeValue);
        var value = Math.max(value1, value2);
        node.setLayout({value: value}, true);
    });
}

/**
 * Compute the x-position for each node.
 *
 * Here we use Kahn algorithm to detect cycle when we traverse
 * the node to computer the initial x position.
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 * @param  {number} nodeWidth  the dx of the node
 * @param  {number} width  the whole width of the area to draw the view
 */
function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign) {
    // Used to mark whether the edge is deleted. if it is deleted,
    // the value is 0, otherwise it is 1.
    var remainEdges = [];
    // Storage each node's indegree.
    var indegreeArr = [];
    //Used to storage the node with indegree is equal to 0.
    var zeroIndegrees = [];
    var nextTargetNode = [];
    var x = 0;
    var kx = 0;

    for (var i = 0; i < edges.length; i++) {
        remainEdges[i] = 1;
    }
    for (i = 0; i < nodes.length; i++) {
        indegreeArr[i] = nodes[i].inEdges.length;
        if (indegreeArr[i] === 0) {
            zeroIndegrees.push(nodes[i]);
        }
    }
    var maxNodeDepth = -1;
    // Traversing nodes using topological sorting to calculate the
    // horizontal(if orient === 'horizontal') or vertical(if orient === 'vertical')
    // position of the nodes.
    while (zeroIndegrees.length) {
        for (var idx = 0; idx < zeroIndegrees.length; idx++) {
            var node = zeroIndegrees[idx];
            var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
            var isItemDepth = item.depth != null && item.depth >= 0;
            if (isItemDepth && item.depth > maxNodeDepth) {
                maxNodeDepth = item.depth;
            }
            node.setLayout({depth: isItemDepth ? item.depth : x}, true);
            orient === 'vertical'
                ? node.setLayout({dy: nodeWidth}, true)
                : node.setLayout({dx: nodeWidth}, true);

            for (var edgeIdx = 0; edgeIdx < node.outEdges.length; edgeIdx++) {
                var edge = node.outEdges[edgeIdx];
                var indexEdge = edges.indexOf(edge);
                remainEdges[indexEdge] = 0;
                var targetNode = edge.node2;
                var nodeIndex = nodes.indexOf(targetNode);
                if (--indegreeArr[nodeIndex] === 0 && nextTargetNode.indexOf(targetNode) < 0) {
                    nextTargetNode.push(targetNode);
                }
            }
        }
        ++x;
        zeroIndegrees = nextTargetNode;
        nextTargetNode = [];
    }

    for (i = 0; i < remainEdges.length; i++) {
        if (remainEdges[i] === 1) {
            throw new Error('Sankey is a DAG, the original data has cycle!');
        }
    }

    var maxDepth = maxNodeDepth > x - 1 ? maxNodeDepth : x - 1;
    if (nodeAlign && nodeAlign !== 'left') {
        adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth);
    }
    var kx = orient === 'vertical'
                ? (height - nodeWidth) / maxDepth
                : (width - nodeWidth) / maxDepth;

    scaleNodeBreadths(nodes, kx, orient);
}

function isNodeDepth(node) {
    var item = node.hostGraph.data.getRawDataItem(node.dataIndex);
    return item.depth != null && item.depth >= 0;
}

function adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth) {
    if (nodeAlign === 'right') {
        var nextSourceNode = [];
        var remainNodes = nodes;
        var nodeHeight = 0;
        while (remainNodes.length) {
            for (var i = 0; i < remainNodes.length; i++) {
                var node = remainNodes[i];
                node.setLayout({skNodeHeight: nodeHeight}, true);
                for (var j = 0; j < node.inEdges.length; j++) {
                    var edge = node.inEdges[j];
                    if (nextSourceNode.indexOf(edge.node1) < 0) {
                        nextSourceNode.push(edge.node1);
                    }
                }
            }
            remainNodes = nextSourceNode;
            nextSourceNode = [];
            ++nodeHeight;
        }

        each$1(nodes, function (node) {
            if (!isNodeDepth(node)) {
                node.setLayout({depth: Math.max(0, maxDepth - node.getLayout().skNodeHeight)}, true);
            }
        });
    }
    else if (nodeAlign === 'justify') {
        moveSinksRight(nodes, maxDepth);
    }
}

/**
 * All the node without outEgdes are assigned maximum x-position and
 *     be aligned in the last column.
 *
 * @param {module:echarts/data/Graph~Node} nodes.  node of sankey view.
 * @param {number} maxDepth.  use to assign to node without outEdges as x-position.
 */
function moveSinksRight(nodes, maxDepth) {
    each$1(nodes, function (node) {
        if (!isNodeDepth(node) && !node.outEdges.length) {
            node.setLayout({depth: maxDepth}, true);
        }
    });
}

/**
 * Scale node x-position to the width
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 * @param {number} kx   multiple used to scale nodes
 */
function scaleNodeBreadths(nodes, kx, orient) {
    each$1(nodes, function (node) {
        var nodeDepth = node.getLayout().depth * kx;
        orient === 'vertical'
            ? node.setLayout({y: nodeDepth}, true)
            : node.setLayout({x: nodeDepth}, true);
    });
}

/**
 * Using Gauss-Seidel iterations method to compute the node depth(y-position)
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 * @param {module:echarts/data/Graph~Edge} edges  edge of sankey view
 * @param {number} height  the whole height of the area to draw the view
 * @param {number} nodeGap  the vertical distance between two nodes
 *     in the same column.
 * @param {number} iterations  the number of iterations for the algorithm
 */
function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) {
    var nodesByBreadth = prepareNodesByBreadth(nodes, orient);

    initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient);
    resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);

    for (var alpha = 1; iterations > 0; iterations--) {
        // 0.99 is a experience parameter, ensure that each iterations of
        // changes as small as possible.
        alpha *= 0.99;
        relaxRightToLeft(nodesByBreadth, alpha, orient);
        resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
        relaxLeftToRight(nodesByBreadth, alpha, orient);
        resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
    }
}

function prepareNodesByBreadth(nodes, orient) {
    var nodesByBreadth = [];
    var keyAttr = orient === 'vertical' ? 'y' : 'x';

    var groupResult = groupData(nodes, function (node) {
        return node.getLayout()[keyAttr];
    });
    groupResult.keys.sort(function (a, b) {
        return a - b;
    });
    each$1(groupResult.keys, function (key) {
        nodesByBreadth.push(groupResult.buckets.get(key));
    });

    return nodesByBreadth;
}

/**
 * Compute the original y-position for each node
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
 *     group by the array of all sankey nodes based on the nodes x-position.
 * @param {module:echarts/data/Graph~Edge} edges  edge of sankey view
 * @param {number} height  the whole height of the area to draw the view
 * @param {number} nodeGap  the vertical distance between two nodes
 */
function initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient) {
    var minKy = Infinity;
    each$1(nodesByBreadth, function (nodes) {
        var n = nodes.length;
        var sum = 0;
        each$1(nodes, function (node) {
            sum += node.getLayout().value;
        });
        var ky = orient === 'vertical'
                    ? (width - (n - 1) * nodeGap) / sum
                    : (height - (n - 1) * nodeGap) / sum;

        if (ky < minKy) {
            minKy = ky;
        }
    });

    each$1(nodesByBreadth, function (nodes) {
        each$1(nodes, function (node, i) {
            var nodeDy = node.getLayout().value * minKy;
            if (orient === 'vertical') {
                node.setLayout({x: i}, true);
                node.setLayout({dx: nodeDy}, true);
            }
            else {
                node.setLayout({y: i}, true);
                node.setLayout({dy: nodeDy}, true);
            }
        });
    });

    each$1(edges, function (edge) {
        var edgeDy = +edge.getValue() * minKy;
        edge.setLayout({dy: edgeDy}, true);
    });
}

/**
 * Resolve the collision of initialized depth (y-position)
 *
 * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
 *     group by the array of all sankey nodes based on the nodes x-position.
 * @param {number} nodeGap  the vertical distance between two nodes
 * @param {number} height  the whole height of the area to draw the view
 */
function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) {
    var keyAttr = orient === 'vertical' ? 'x' : 'y';
    each$1(nodesByBreadth, function (nodes) {
        nodes.sort(function (a, b) {
            return a.getLayout()[keyAttr] - b.getLayout()[keyAttr];
        });
        var nodeX;
        var node;
        var dy;
        var y0 = 0;
        var n = nodes.length;
        var nodeDyAttr = orient === 'vertical' ? 'dx' : 'dy';
        for (var i = 0; i < n; i++) {
            node = nodes[i];
            dy = y0 - node.getLayout()[keyAttr];
            if (dy > 0) {
                nodeX = node.getLayout()[keyAttr] + dy;
                orient === 'vertical'
                    ? node.setLayout({x: nodeX}, true)
                    : node.setLayout({y: nodeX}, true);
            }
            y0 = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap;
        }
        var viewWidth = orient === 'vertical' ? width : height;
        // If the bottommost node goes outside the bounds, push it back up
        dy = y0 - nodeGap - viewWidth;
        if (dy > 0) {
            nodeX = node.getLayout()[keyAttr] - dy;
            orient === 'vertical'
                ? node.setLayout({x: nodeX}, true)
                : node.setLayout({y: nodeX}, true);

            y0 = nodeX;
            for (i = n - 2; i >= 0; --i) {
                node = nodes[i];
                dy = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap - y0;
                if (dy > 0) {
                    nodeX = node.getLayout()[keyAttr] - dy;
                    orient === 'vertical'
                        ? node.setLayout({x: nodeX}, true)
                        : node.setLayout({y: nodeX}, true);
                }
                y0 = node.getLayout()[keyAttr];
            }
        }
    });
}

/**
 * Change the y-position of the nodes, except most the right side nodes
 *
 * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
 *     group by the array of all sankey nodes based on the node x-position.
 * @param {number} alpha  parameter used to adjust the nodes y-position
 */
function relaxRightToLeft(nodesByBreadth, alpha, orient) {
    each$1(nodesByBreadth.slice().reverse(), function (nodes) {
        each$1(nodes, function (node) {
            if (node.outEdges.length) {
                var y = sum(node.outEdges, weightedTarget, orient)
                        / sum(node.outEdges, getEdgeValue, orient);
                if (orient === 'vertical') {
                    var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha;
                    node.setLayout({x: nodeX}, true);
                }
                else {
                    var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha;
                    node.setLayout({y: nodeY}, true);
                }
            }
        });
    });
}

function weightedTarget(edge, orient) {
    return center$1(edge.node2, orient) * edge.getValue();
}

function weightedSource(edge, orient) {
    return center$1(edge.node1, orient) * edge.getValue();
}

function center$1(node, orient) {
    return orient === 'vertical'
            ? node.getLayout().x + node.getLayout().dx / 2
            : node.getLayout().y + node.getLayout().dy / 2;
}

function getEdgeValue(edge) {
    return edge.getValue();
}

function sum(array, f, orient) {
    var sum = 0;
    var len = array.length;
    var i = -1;
    while (++i < len) {
        var value = +f.call(array, array[i], orient);
        if (!isNaN(value)) {
            sum += value;
        }
    }
    return sum;
}

/**
 * Change the y-position of the nodes, except most the left side nodes
 *
 * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
 *     group by the array of all sankey nodes based on the node x-position.
 * @param {number} alpha  parameter used to adjust the nodes y-position
 */
function relaxLeftToRight(nodesByBreadth, alpha, orient) {
    each$1(nodesByBreadth, function (nodes) {
        each$1(nodes, function (node) {
            if (node.inEdges.length) {
                var y = sum(node.inEdges, weightedSource, orient)
                        / sum(node.inEdges, getEdgeValue, orient);
                if (orient === 'vertical') {
                    var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha;
                    node.setLayout({x: nodeX}, true);
                }
                else {
                    var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha;
                    node.setLayout({y: nodeY}, true);
                }
            }
        });
    });
}

/**
 * Compute the depth(y-position) of each edge
 *
 * @param {module:echarts/data/Graph~Node} nodes  node of sankey view
 */
function computeEdgeDepths(nodes, orient) {
    var keyAttr = orient === 'vertical' ? 'x' : 'y';
    each$1(nodes, function (node) {
        node.outEdges.sort(function (a, b) {
            return a.node2.getLayout()[keyAttr] - b.node2.getLayout()[keyAttr];
        });
        node.inEdges.sort(function (a, b) {
            return a.node1.getLayout()[keyAttr] - b.node1.getLayout()[keyAttr];
        });
    });
    each$1(nodes, function (node) {
        var sy = 0;
        var ty = 0;
        each$1(node.outEdges, function (edge) {
            edge.setLayout({sy: sy}, true);
            sy += edge.getLayout().dy;
        });
        each$1(node.inEdges, function (edge) {
            edge.setLayout({ty: ty}, true);
            ty += edge.getLayout().dy;
        });
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var sankeyVisual = function (ecModel, payload) {
    ecModel.eachSeriesByType('sankey', function (seriesModel) {
        var graph = seriesModel.getGraph();
        var nodes = graph.nodes;
        if (nodes.length) {
            var minValue = Infinity;
            var maxValue = -Infinity;
            each$1(nodes, function (node) {
                var nodeValue = node.getLayout().value;
                if (nodeValue < minValue) {
                    minValue = nodeValue;
                }
                if (nodeValue > maxValue) {
                    maxValue = nodeValue;
                }
            });

            each$1(nodes, function (node) {
                var mapping = new VisualMapping({
                    type: 'color',
                    mappingMethod: 'linear',
                    dataExtent: [minValue, maxValue],
                    visual: seriesModel.get('color')
                });

                var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value);
                var customColor = node.getModel().get('itemStyle.color');
                customColor != null
                    ? node.setVisual('color', customColor)
                    : node.setVisual('color', mapValueToColor);
            });
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerLayout(sankeyLayout);
registerVisual(sankeyVisual);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var seriesModelMixin = {

    /**
     * @private
     * @type {string}
     */
    _baseAxisDim: null,

    /**
     * @override
     */
    getInitialData: function (option, ecModel) {
        // When both types of xAxis and yAxis are 'value', layout is
        // needed to be specified by user. Otherwise, layout can be
        // judged by which axis is category.

        var ordinalMeta;

        var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex'));
        var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex'));
        var xAxisType = xAxisModel.get('type');
        var yAxisType = yAxisModel.get('type');
        var addOrdinal;

        // FIXME
        // 考虑时间轴

        if (xAxisType === 'category') {
            option.layout = 'horizontal';
            ordinalMeta = xAxisModel.getOrdinalMeta();
            addOrdinal = true;
        }
        else if (yAxisType === 'category') {
            option.layout = 'vertical';
            ordinalMeta = yAxisModel.getOrdinalMeta();
            addOrdinal = true;
        }
        else {
            option.layout = option.layout || 'horizontal';
        }

        var coordDims = ['x', 'y'];
        var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1;
        var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex];
        var otherAxisDim = coordDims[1 - baseAxisDimIndex];
        var axisModels = [xAxisModel, yAxisModel];
        var baseAxisType = axisModels[baseAxisDimIndex].get('type');
        var otherAxisType = axisModels[1 - baseAxisDimIndex].get('type');
        var data = option.data;

        // ??? FIXME make a stage to perform data transfrom.
        // MUST create a new data, consider setOption({}) again.
        if (data && addOrdinal) {
            var newOptionData = [];
            each$1(data, function (item, index) {
                var newItem;
                if (item.value && isArray(item.value)) {
                    newItem = item.value.slice();
                    item.value.unshift(index);
                }
                else if (isArray(item)) {
                    newItem = item.slice();
                    item.unshift(index);
                }
                else {
                    newItem = item;
                }
                newOptionData.push(newItem);
            });
            option.data = newOptionData;
        }

        var defaultValueDimensions = this.defaultValueDimensions;

        return createListSimply(
            this,
            {
                coordDimensions: [{
                    name: baseAxisDim,
                    type: getDimensionTypeByAxis(baseAxisType),
                    ordinalMeta: ordinalMeta,
                    otherDims: {
                        tooltip: false,
                        itemName: 0
                    },
                    dimsDef: ['base']
                }, {
                    name: otherAxisDim,
                    type: getDimensionTypeByAxis(otherAxisType),
                    dimsDef: defaultValueDimensions.slice()
                }],
                dimensionsCount: defaultValueDimensions.length + 1
            }
        );
    },

    /**
     * If horizontal, base axis is x, otherwise y.
     * @override
     */
    getBaseAxis: function () {
        var dim = this._baseAxisDim;
        return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis;
    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var BoxplotSeries = SeriesModel.extend({

    type: 'series.boxplot',

    dependencies: ['xAxis', 'yAxis', 'grid'],

    // TODO
    // box width represents group size, so dimension should have 'size'.

    /**
     * @see <https://en.wikipedia.org/wiki/Box_plot>
     * The meanings of 'min' and 'max' depend on user,
     * and echarts do not need to know it.
     * @readOnly
     */
    defaultValueDimensions: [
        {name: 'min', defaultTooltip: true},
        {name: 'Q1', defaultTooltip: true},
        {name: 'median', defaultTooltip: true},
        {name: 'Q3', defaultTooltip: true},
        {name: 'max', defaultTooltip: true}
    ],

    /**
     * @type {Array.<string>}
     * @readOnly
     */
    dimensions: null,

    /**
     * @override
     */
    defaultOption: {
        zlevel: 0,                  // 一级层叠
        z: 2,                       // 二级层叠
        coordinateSystem: 'cartesian2d',
        legendHoverLink: true,

        hoverAnimation: true,

        // xAxisIndex: 0,
        // yAxisIndex: 0,

        layout: null,               // 'horizontal' or 'vertical'
        boxWidth: [7, 50],       // [min, max] can be percent of band width.

        itemStyle: {
            color: '#fff',
            borderWidth: 1
        },

        emphasis: {
            itemStyle: {
                borderWidth: 2,
                shadowBlur: 5,
                shadowOffsetX: 2,
                shadowOffsetY: 2,
                shadowColor: 'rgba(0,0,0,0.4)'
            }
        },

        animationEasing: 'elasticOut',
        animationDuration: 800
    }
});

mixin(BoxplotSeries, seriesModelMixin, true);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Update common properties
var NORMAL_ITEM_STYLE_PATH = ['itemStyle'];
var EMPHASIS_ITEM_STYLE_PATH = ['emphasis', 'itemStyle'];

var BoxplotView = Chart.extend({

    type: 'boxplot',

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var group = this.group;
        var oldData = this._data;

        // There is no old data only when first rendering or switching from
        // stream mode to normal mode, where previous elements should be removed.
        if (!this._data) {
            group.removeAll();
        }

        var constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0;

        data.diff(oldData)
            .add(function (newIdx) {
                if (data.hasValue(newIdx)) {
                    var itemLayout = data.getItemLayout(newIdx);
                    var symbolEl = createNormalBox(itemLayout, data, newIdx, constDim, true);
                    data.setItemGraphicEl(newIdx, symbolEl);
                    group.add(symbolEl);
                }
            })
            .update(function (newIdx, oldIdx) {
                var symbolEl = oldData.getItemGraphicEl(oldIdx);

                // Empty data
                if (!data.hasValue(newIdx)) {
                    group.remove(symbolEl);
                    return;
                }

                var itemLayout = data.getItemLayout(newIdx);
                if (!symbolEl) {
                    symbolEl = createNormalBox(itemLayout, data, newIdx, constDim);
                }
                else {
                    updateNormalBoxData(itemLayout, symbolEl, data, newIdx);
                }

                group.add(symbolEl);

                data.setItemGraphicEl(newIdx, symbolEl);
            })
            .remove(function (oldIdx) {
                var el = oldData.getItemGraphicEl(oldIdx);
                el && group.remove(el);
            })
            .execute();

        this._data = data;
    },

    remove: function (ecModel) {
        var group = this.group;
        var data = this._data;
        this._data = null;
        data && data.eachItemGraphicEl(function (el) {
            el && group.remove(el);
        });
    },

    dispose: noop

});


var BoxPath = Path.extend({

    type: 'boxplotBoxPath',

    shape: {},

    buildPath: function (ctx, shape) {
        var ends = shape.points;

        var i = 0;
        ctx.moveTo(ends[i][0], ends[i][1]);
        i++;
        for (; i < 4; i++) {
            ctx.lineTo(ends[i][0], ends[i][1]);
        }
        ctx.closePath();

        for (; i < ends.length; i++) {
            ctx.moveTo(ends[i][0], ends[i][1]);
            i++;
            ctx.lineTo(ends[i][0], ends[i][1]);
        }
    }
});


function createNormalBox(itemLayout, data, dataIndex, constDim, isInit) {
    var ends = itemLayout.ends;

    var el = new BoxPath({
        shape: {
            points: isInit
                ? transInit(ends, constDim, itemLayout)
                : ends
        }
    });

    updateNormalBoxData(itemLayout, el, data, dataIndex, isInit);

    return el;
}

function updateNormalBoxData(itemLayout, el, data, dataIndex, isInit) {
    var seriesModel = data.hostModel;
    var updateMethod = graphic[isInit ? 'initProps' : 'updateProps'];

    updateMethod(
        el,
        {shape: {points: itemLayout.ends}},
        seriesModel,
        dataIndex
    );

    var itemModel = data.getItemModel(dataIndex);
    var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH);
    var borderColor = data.getItemVisual(dataIndex, 'color');

    // Exclude borderColor.
    var itemStyle = normalItemStyleModel.getItemStyle(['borderColor']);
    itemStyle.stroke = borderColor;
    itemStyle.strokeNoScale = true;
    el.useStyle(itemStyle);

    el.z2 = 100;

    var hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH).getItemStyle();
    setHoverStyle(el, hoverStyle);
}

function transInit(points, dim, itemLayout) {
    return map(points, function (point) {
        point = point.slice();
        point[dim] = itemLayout.initBaseline;
        return point;
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var borderColorQuery = ['itemStyle', 'borderColor'];

var boxplotVisual = function (ecModel, api) {

    var globalColors = ecModel.get('color');

    ecModel.eachRawSeriesByType('boxplot', function (seriesModel) {

        var defaulColor = globalColors[seriesModel.seriesIndex % globalColors.length];
        var data = seriesModel.getData();

        data.setVisual({
            legendSymbol: 'roundRect',
            // Use name 'color' but not 'borderColor' for legend usage and
            // visual coding from other component like dataRange.
            color: seriesModel.get(borderColorQuery) || defaulColor
        });

        // Only visible series has each data be visual encoded
        if (!ecModel.isSeriesFiltered(seriesModel)) {
            data.each(function (idx) {
                var itemModel = data.getItemModel(idx);
                data.setItemVisual(
                    idx,
                    {color: itemModel.get(borderColorQuery, true)}
                );
            });
        }
    });

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$13 = each$1;

var boxplotLayout = function (ecModel) {

    var groupResult = groupSeriesByAxis(ecModel);

    each$13(groupResult, function (groupItem) {
        var seriesModels = groupItem.seriesModels;

        if (!seriesModels.length) {
            return;
        }

        calculateBase(groupItem);

        each$13(seriesModels, function (seriesModel, idx) {
            layoutSingleSeries(
                seriesModel,
                groupItem.boxOffsetList[idx],
                groupItem.boxWidthList[idx]
            );
        });
    });
};

/**
 * Group series by axis.
 */
function groupSeriesByAxis(ecModel) {
    var result = [];
    var axisList = [];

    ecModel.eachSeriesByType('boxplot', function (seriesModel) {
        var baseAxis = seriesModel.getBaseAxis();
        var idx = indexOf(axisList, baseAxis);

        if (idx < 0) {
            idx = axisList.length;
            axisList[idx] = baseAxis;
            result[idx] = {axis: baseAxis, seriesModels: []};
        }

        result[idx].seriesModels.push(seriesModel);
    });

    return result;
}

/**
 * Calculate offset and box width for each series.
 */
function calculateBase(groupItem) {
    var extent;
    var baseAxis = groupItem.axis;
    var seriesModels = groupItem.seriesModels;
    var seriesCount = seriesModels.length;

    var boxWidthList = groupItem.boxWidthList = [];
    var boxOffsetList = groupItem.boxOffsetList = [];
    var boundList = [];

    var bandWidth;
    if (baseAxis.type === 'category') {
        bandWidth = baseAxis.getBandWidth();
    }
    else {
        var maxDataCount = 0;
        each$13(seriesModels, function (seriesModel) {
            maxDataCount = Math.max(maxDataCount, seriesModel.getData().count());
        });
        extent = baseAxis.getExtent(),
        Math.abs(extent[1] - extent[0]) / maxDataCount;
    }

    each$13(seriesModels, function (seriesModel) {
        var boxWidthBound = seriesModel.get('boxWidth');
        if (!isArray(boxWidthBound)) {
            boxWidthBound = [boxWidthBound, boxWidthBound];
        }
        boundList.push([
            parsePercent$1(boxWidthBound[0], bandWidth) || 0,
            parsePercent$1(boxWidthBound[1], bandWidth) || 0
        ]);
    });

    var availableWidth = bandWidth * 0.8 - 2;
    var boxGap = availableWidth / seriesCount * 0.3;
    var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount;
    var base = boxWidth / 2 - availableWidth / 2;

    each$13(seriesModels, function (seriesModel, idx) {
        boxOffsetList.push(base);
        base += boxGap + boxWidth;

        boxWidthList.push(
            Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])
        );
    });
}

/**
 * Calculate points location for each series.
 */
function layoutSingleSeries(seriesModel, offset, boxWidth) {
    var coordSys = seriesModel.coordinateSystem;
    var data = seriesModel.getData();
    var halfWidth = boxWidth / 2;
    var cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1;
    var vDimIdx = 1 - cDimIdx;
    var coordDims = ['x', 'y'];
    var cDim = data.mapDimension(coordDims[cDimIdx]);
    var vDims = data.mapDimension(coordDims[vDimIdx], true);

    if (cDim == null || vDims.length < 5) {
        return;
    }

    for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) {
        var axisDimVal = data.get(cDim, dataIndex);

        var median = getPoint(axisDimVal, vDims[2], dataIndex);
        var end1 = getPoint(axisDimVal, vDims[0], dataIndex);
        var end2 = getPoint(axisDimVal, vDims[1], dataIndex);
        var end4 = getPoint(axisDimVal, vDims[3], dataIndex);
        var end5 = getPoint(axisDimVal, vDims[4], dataIndex);

        var ends = [];
        addBodyEnd(ends, end2, 0);
        addBodyEnd(ends, end4, 1);

        ends.push(end1, end2, end5, end4);
        layEndLine(ends, end1);
        layEndLine(ends, end5);
        layEndLine(ends, median);

        data.setItemLayout(dataIndex, {
            initBaseline: median[vDimIdx],
            ends: ends
        });
    }

    function getPoint(axisDimVal, dimIdx, dataIndex) {
        var val = data.get(dimIdx, dataIndex);
        var p = [];
        p[cDimIdx] = axisDimVal;
        p[vDimIdx] = val;
        var point;
        if (isNaN(axisDimVal) || isNaN(val)) {
            point = [NaN, NaN];
        }
        else {
            point = coordSys.dataToPoint(p);
            point[cDimIdx] += offset;
        }
        return point;
    }

    function addBodyEnd(ends, point, start) {
        var point1 = point.slice();
        var point2 = point.slice();
        point1[cDimIdx] += halfWidth;
        point2[cDimIdx] -= halfWidth;
        start
            ? ends.push(point1, point2)
            : ends.push(point2, point1);
    }

    function layEndLine(ends, endCenter) {
        var from = endCenter.slice();
        var to = endCenter.slice();
        from[cDimIdx] -= halfWidth;
        to[cDimIdx] += halfWidth;
        ends.push(from, to);
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(boxplotVisual);
registerLayout(boxplotLayout);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var CandlestickSeries = SeriesModel.extend({

    type: 'series.candlestick',

    dependencies: ['xAxis', 'yAxis', 'grid'],

    /**
     * @readOnly
     */
    defaultValueDimensions: [
        {name: 'open', defaultTooltip: true},
        {name: 'close', defaultTooltip: true},
        {name: 'lowest', defaultTooltip: true},
        {name: 'highest', defaultTooltip: true}
    ],

    /**
     * @type {Array.<string>}
     * @readOnly
     */
    dimensions: null,

    /**
     * @override
     */
    defaultOption: {
        zlevel: 0,
        z: 2,
        coordinateSystem: 'cartesian2d',
        legendHoverLink: true,

        hoverAnimation: true,

        // xAxisIndex: 0,
        // yAxisIndex: 0,

        layout: null, // 'horizontal' or 'vertical'

        clip: true,

        itemStyle: {
            color: '#c23531', // 阳线 positive
            color0: '#314656', // 阴线 negative     '#c23531', '#314656'
            borderWidth: 1,
            // FIXME
            // ec2中使用的是lineStyle.color 和 lineStyle.color0
            borderColor: '#c23531',
            borderColor0: '#314656'
        },

        emphasis: {
            itemStyle: {
                borderWidth: 2
            }
        },

        barMaxWidth: null,
        barMinWidth: null,
        barWidth: null,

        large: true,
        largeThreshold: 600,

        progressive: 3e3,
        progressiveThreshold: 1e4,
        progressiveChunkMode: 'mod',

        animationUpdate: false,
        animationEasing: 'linear',
        animationDuration: 300
    },

    /**
     * Get dimension for shadow in dataZoom
     * @return {string} dimension name
     */
    getShadowDim: function () {
        return 'open';
    },

    brushSelector: function (dataIndex, data, selectors) {
        var itemLayout = data.getItemLayout(dataIndex);
        return itemLayout && selectors.rect(itemLayout.brushRect);
    }

});

mixin(CandlestickSeries, seriesModelMixin, true);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var NORMAL_ITEM_STYLE_PATH$1 = ['itemStyle'];
var EMPHASIS_ITEM_STYLE_PATH$1 = ['emphasis', 'itemStyle'];
var SKIP_PROPS = ['color', 'color0', 'borderColor', 'borderColor0'];

var CandlestickView = Chart.extend({

    type: 'candlestick',

    render: function (seriesModel, ecModel, api) {
        // If there is clipPath created in large mode. Remove it.
        this.group.removeClipPath();

        this._updateDrawMode(seriesModel);

        this._isLargeDraw
            ? this._renderLarge(seriesModel)
            : this._renderNormal(seriesModel);
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        this._clear();
        this._updateDrawMode(seriesModel);
    },

    incrementalRender: function (params, seriesModel, ecModel, api) {
        this._isLargeDraw
             ? this._incrementalRenderLarge(params, seriesModel)
             : this._incrementalRenderNormal(params, seriesModel);
    },

    _updateDrawMode: function (seriesModel) {
        var isLargeDraw = seriesModel.pipelineContext.large;
        if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) {
            this._isLargeDraw = isLargeDraw;
            this._clear();
        }
    },

    _renderNormal: function (seriesModel) {
        var data = seriesModel.getData();
        var oldData = this._data;
        var group = this.group;
        var isSimpleBox = data.getLayout('isSimpleBox');

        var needsClip = seriesModel.get('clip', true);
        var coord = seriesModel.coordinateSystem;
        var clipArea = coord.getArea && coord.getArea();

        // There is no old data only when first rendering or switching from
        // stream mode to normal mode, where previous elements should be removed.
        if (!this._data) {
            group.removeAll();
        }

        data.diff(oldData)
            .add(function (newIdx) {
                if (data.hasValue(newIdx)) {
                    var el;

                    var itemLayout = data.getItemLayout(newIdx);

                    if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
                        return;
                    }

                    el = createNormalBox$1(itemLayout, newIdx, true);
                    initProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);

                    setBoxCommon(el, data, newIdx, isSimpleBox);

                    group.add(el);

                    data.setItemGraphicEl(newIdx, el);
                }
            })
            .update(function (newIdx, oldIdx) {
                var el = oldData.getItemGraphicEl(oldIdx);

                // Empty data
                if (!data.hasValue(newIdx)) {
                    group.remove(el);
                    return;
                }

                var itemLayout = data.getItemLayout(newIdx);
                if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
                    group.remove(el);
                    return;
                }

                if (!el) {
                    el = createNormalBox$1(itemLayout, newIdx);
                }
                else {
                    updateProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);
                }

                setBoxCommon(el, data, newIdx, isSimpleBox);

                group.add(el);
                data.setItemGraphicEl(newIdx, el);
            })
            .remove(function (oldIdx) {
                var el = oldData.getItemGraphicEl(oldIdx);
                el && group.remove(el);
            })
            .execute();

        this._data = data;
    },

    _renderLarge: function (seriesModel) {
        this._clear();

        createLarge$1(seriesModel, this.group);

        var clipPath = seriesModel.get('clip', true)
            ? createClipPath(seriesModel.coordinateSystem, false, seriesModel)
            : null;
        if (clipPath) {
            this.group.setClipPath(clipPath);
        }
        else {
            this.group.removeClipPath();
        }

    },

    _incrementalRenderNormal: function (params, seriesModel) {
        var data = seriesModel.getData();
        var isSimpleBox = data.getLayout('isSimpleBox');

        var dataIndex;
        while ((dataIndex = params.next()) != null) {
            var el;

            var itemLayout = data.getItemLayout(dataIndex);
            el = createNormalBox$1(itemLayout, dataIndex);
            setBoxCommon(el, data, dataIndex, isSimpleBox);

            el.incremental = true;
            this.group.add(el);
        }
    },

    _incrementalRenderLarge: function (params, seriesModel) {
        createLarge$1(seriesModel, this.group, true);
    },

    remove: function (ecModel) {
        this._clear();
    },

    _clear: function () {
        this.group.removeAll();
        this._data = null;
    },

    dispose: noop

});


var NormalBoxPath = Path.extend({

    type: 'normalCandlestickBox',

    shape: {},

    buildPath: function (ctx, shape) {
        var ends = shape.points;

        if (this.__simpleBox) {
            ctx.moveTo(ends[4][0], ends[4][1]);
            ctx.lineTo(ends[6][0], ends[6][1]);
        }
        else {
            ctx.moveTo(ends[0][0], ends[0][1]);
            ctx.lineTo(ends[1][0], ends[1][1]);
            ctx.lineTo(ends[2][0], ends[2][1]);
            ctx.lineTo(ends[3][0], ends[3][1]);
            ctx.closePath();

            ctx.moveTo(ends[4][0], ends[4][1]);
            ctx.lineTo(ends[5][0], ends[5][1]);
            ctx.moveTo(ends[6][0], ends[6][1]);
            ctx.lineTo(ends[7][0], ends[7][1]);
        }
    }
});


function createNormalBox$1(itemLayout, dataIndex, isInit) {
    var ends = itemLayout.ends;
    return new NormalBoxPath({
        shape: {
            points: isInit
                ? transInit$1(ends, itemLayout)
                : ends
        },
        z2: 100
    });
}

function isNormalBoxClipped(clipArea, itemLayout) {
    var clipped = true;
    for (var i = 0; i < itemLayout.ends.length; i++) {
        // If any point are in the region.
        if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) {
            clipped = false;
            break;
        }
    }
    return clipped;
}

function setBoxCommon(el, data, dataIndex, isSimpleBox) {
    var itemModel = data.getItemModel(dataIndex);
    var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH$1);
    var color = data.getItemVisual(dataIndex, 'color');
    var borderColor = data.getItemVisual(dataIndex, 'borderColor') || color;

    // Color must be excluded.
    // Because symbol provide setColor individually to set fill and stroke
    var itemStyle = normalItemStyleModel.getItemStyle(SKIP_PROPS);

    el.useStyle(itemStyle);
    el.style.strokeNoScale = true;
    el.style.fill = color;
    el.style.stroke = borderColor;

    el.__simpleBox = isSimpleBox;

    var hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH$1).getItemStyle();
    setHoverStyle(el, hoverStyle);
}

function transInit$1(points, itemLayout) {
    return map(points, function (point) {
        point = point.slice();
        point[1] = itemLayout.initBaseline;
        return point;
    });
}



var LargeBoxPath = Path.extend({

    type: 'largeCandlestickBox',

    shape: {},

    buildPath: function (ctx, shape) {
        // Drawing lines is more efficient than drawing
        // a whole line or drawing rects.
        var points = shape.points;
        for (var i = 0; i < points.length;) {
            if (this.__sign === points[i++]) {
                var x = points[i++];
                ctx.moveTo(x, points[i++]);
                ctx.lineTo(x, points[i++]);
            }
            else {
                i += 3;
            }
        }
    }
});

function createLarge$1(seriesModel, group, incremental) {
    var data = seriesModel.getData();
    var largePoints = data.getLayout('largePoints');

    var elP = new LargeBoxPath({
        shape: {points: largePoints},
        __sign: 1
    });
    group.add(elP);
    var elN = new LargeBoxPath({
        shape: {points: largePoints},
        __sign: -1
    });
    group.add(elN);

    setLargeStyle$1(1, elP, seriesModel, data);
    setLargeStyle$1(-1, elN, seriesModel, data);

    if (incremental) {
        elP.incremental = true;
        elN.incremental = true;
    }
}

function setLargeStyle$1(sign, el, seriesModel, data) {
    var suffix = sign > 0 ? 'P' : 'N';
    var borderColor = data.getVisual('borderColor' + suffix)
        || data.getVisual('color' + suffix);

    // Color must be excluded.
    // Because symbol provide setColor individually to set fill and stroke
    var itemStyle = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH$1).getItemStyle(SKIP_PROPS);

    el.useStyle(itemStyle);
    el.style.fill = null;
    el.style.stroke = borderColor;
    // No different
    // el.style.lineWidth = .5;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var preprocessor = function (option) {
    if (!option || !isArray(option.series)) {
        return;
    }

    // Translate 'k' to 'candlestick'.
    each$1(option.series, function (seriesItem) {
        if (isObject$1(seriesItem) && seriesItem.type === 'k') {
            seriesItem.type = 'candlestick';
        }
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var positiveBorderColorQuery = ['itemStyle', 'borderColor'];
var negativeBorderColorQuery = ['itemStyle', 'borderColor0'];
var positiveColorQuery = ['itemStyle', 'color'];
var negativeColorQuery = ['itemStyle', 'color0'];

var candlestickVisual = {

    seriesType: 'candlestick',

    plan: createRenderPlanner(),

    // For legend.
    performRawSeries: true,

    reset: function (seriesModel, ecModel) {

        var data = seriesModel.getData();
        var isLargeRender = seriesModel.pipelineContext.large;

        data.setVisual({
            legendSymbol: 'roundRect',
            colorP: getColor(1, seriesModel),
            colorN: getColor(-1, seriesModel),
            borderColorP: getBorderColor(1, seriesModel),
            borderColorN: getBorderColor(-1, seriesModel)
        });

        // Only visible series has each data be visual encoded
        if (ecModel.isSeriesFiltered(seriesModel)) {
            return;
        }

        return !isLargeRender && {progress: progress};


        function progress(params, data) {
            var dataIndex;
            while ((dataIndex = params.next()) != null) {
                var itemModel = data.getItemModel(dataIndex);
                var sign = data.getItemLayout(dataIndex).sign;

                data.setItemVisual(
                    dataIndex,
                    {
                        color: getColor(sign, itemModel),
                        borderColor: getBorderColor(sign, itemModel)
                    }
                );
            }
        }

        function getColor(sign, model) {
            return model.get(
                sign > 0 ? positiveColorQuery : negativeColorQuery
            );
        }

        function getBorderColor(sign, model) {
            return model.get(
                sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery
            );
        }

    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float32Array */

var LargeArr$1 = typeof Float32Array !== 'undefined' ? Float32Array : Array;

var candlestickLayout = {

    seriesType: 'candlestick',

    plan: createRenderPlanner(),

    reset: function (seriesModel) {

        var coordSys = seriesModel.coordinateSystem;
        var data = seriesModel.getData();
        var candleWidth = calculateCandleWidth(seriesModel, data);
        var cDimIdx = 0;
        var vDimIdx = 1;
        var coordDims = ['x', 'y'];
        var cDim = data.mapDimension(coordDims[cDimIdx]);
        var vDims = data.mapDimension(coordDims[vDimIdx], true);
        var openDim = vDims[0];
        var closeDim = vDims[1];
        var lowestDim = vDims[2];
        var highestDim = vDims[3];

        data.setLayout({
            candleWidth: candleWidth,
            // The value is experimented visually.
            isSimpleBox: candleWidth <= 1.3
        });

        if (cDim == null || vDims.length < 4) {
            return;
        }

        return {
            progress: seriesModel.pipelineContext.large
                ? largeProgress : normalProgress
        };

        function normalProgress(params, data) {
            var dataIndex;
            while ((dataIndex = params.next()) != null) {

                var axisDimVal = data.get(cDim, dataIndex);
                var openVal = data.get(openDim, dataIndex);
                var closeVal = data.get(closeDim, dataIndex);
                var lowestVal = data.get(lowestDim, dataIndex);
                var highestVal = data.get(highestDim, dataIndex);

                var ocLow = Math.min(openVal, closeVal);
                var ocHigh = Math.max(openVal, closeVal);

                var ocLowPoint = getPoint(ocLow, axisDimVal);
                var ocHighPoint = getPoint(ocHigh, axisDimVal);
                var lowestPoint = getPoint(lowestVal, axisDimVal);
                var highestPoint = getPoint(highestVal, axisDimVal);

                var ends = [];
                addBodyEnd(ends, ocHighPoint, 0);
                addBodyEnd(ends, ocLowPoint, 1);

                ends.push(
                    subPixelOptimizePoint(highestPoint),
                    subPixelOptimizePoint(ocHighPoint),
                    subPixelOptimizePoint(lowestPoint),
                    subPixelOptimizePoint(ocLowPoint)
                );

                data.setItemLayout(dataIndex, {
                    sign: getSign(data, dataIndex, openVal, closeVal, closeDim),
                    initBaseline: openVal > closeVal
                        ? ocHighPoint[vDimIdx] : ocLowPoint[vDimIdx], // open point.
                    ends: ends,
                    brushRect: makeBrushRect(lowestVal, highestVal, axisDimVal)
                });
            }

            function getPoint(val, axisDimVal) {
                var p = [];
                p[cDimIdx] = axisDimVal;
                p[vDimIdx] = val;
                return (isNaN(axisDimVal) || isNaN(val))
                    ? [NaN, NaN]
                    : coordSys.dataToPoint(p);
            }

            function addBodyEnd(ends, point, start) {
                var point1 = point.slice();
                var point2 = point.slice();

                point1[cDimIdx] = subPixelOptimize(
                    point1[cDimIdx] + candleWidth / 2, 1, false
                );
                point2[cDimIdx] = subPixelOptimize(
                    point2[cDimIdx] - candleWidth / 2, 1, true
                );

                start
                    ? ends.push(point1, point2)
                    : ends.push(point2, point1);
            }

            function makeBrushRect(lowestVal, highestVal, axisDimVal) {
                var pmin = getPoint(lowestVal, axisDimVal);
                var pmax = getPoint(highestVal, axisDimVal);

                pmin[cDimIdx] -= candleWidth / 2;
                pmax[cDimIdx] -= candleWidth / 2;

                return {
                    x: pmin[0],
                    y: pmin[1],
                    width: vDimIdx ? candleWidth : pmax[0] - pmin[0],
                    height: vDimIdx ? pmax[1] - pmin[1] : candleWidth
                };
            }

            function subPixelOptimizePoint(point) {
                point[cDimIdx] = subPixelOptimize(point[cDimIdx], 1);
                return point;
            }
        }

        function largeProgress(params, data) {
            // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...]
            var points = new LargeArr$1(params.count * 4);
            var offset = 0;
            var point;
            var tmpIn = [];
            var tmpOut = [];
            var dataIndex;

            while ((dataIndex = params.next()) != null) {
                var axisDimVal = data.get(cDim, dataIndex);
                var openVal = data.get(openDim, dataIndex);
                var closeVal = data.get(closeDim, dataIndex);
                var lowestVal = data.get(lowestDim, dataIndex);
                var highestVal = data.get(highestDim, dataIndex);

                if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) {
                    points[offset++] = NaN;
                    offset += 3;
                    continue;
                }

                points[offset++] = getSign(data, dataIndex, openVal, closeVal, closeDim);

                tmpIn[cDimIdx] = axisDimVal;

                tmpIn[vDimIdx] = lowestVal;
                point = coordSys.dataToPoint(tmpIn, null, tmpOut);
                points[offset++] = point ? point[0] : NaN;
                points[offset++] = point ? point[1] : NaN;
                tmpIn[vDimIdx] = highestVal;
                point = coordSys.dataToPoint(tmpIn, null, tmpOut);
                points[offset++] = point ? point[1] : NaN;
            }

            data.setLayout('largePoints', points);
        }
    }
};

function getSign(data, dataIndex, openVal, closeVal, closeDim) {
    var sign;
    if (openVal > closeVal) {
        sign = -1;
    }
    else if (openVal < closeVal) {
        sign = 1;
    }
    else {
        sign = dataIndex > 0
            // If close === open, compare with close of last record
            ? (data.get(closeDim, dataIndex - 1) <= closeVal ? 1 : -1)
            // No record of previous, set to be positive
            : 1;
    }

    return sign;
}

function calculateCandleWidth(seriesModel, data) {
    var baseAxis = seriesModel.getBaseAxis();
    var extent;

    var bandWidth = baseAxis.type === 'category'
        ? baseAxis.getBandWidth()
        : (
            extent = baseAxis.getExtent(),
            Math.abs(extent[1] - extent[0]) / data.count()
        );

    var barMaxWidth = parsePercent$1(
        retrieve2(seriesModel.get('barMaxWidth'), bandWidth),
        bandWidth
    );
    var barMinWidth = parsePercent$1(
        retrieve2(seriesModel.get('barMinWidth'), 1),
        bandWidth
    );
    var barWidth = seriesModel.get('barWidth');

    return barWidth != null
        ? parsePercent$1(barWidth, bandWidth)
        // Put max outer to ensure bar visible in spite of overlap.
        : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerPreprocessor(preprocessor);
registerVisual(candlestickVisual);
registerLayout(candlestickLayout);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.effectScatter',

    dependencies: ['grid', 'polar'],

    getInitialData: function (option, ecModel) {
        return createListFromArray(this.getSource(), this);
    },

    brushSelector: 'point',

    defaultOption: {
        coordinateSystem: 'cartesian2d',
        zlevel: 0,
        z: 2,
        legendHoverLink: true,

        effectType: 'ripple',

        progressive: 0,

        // When to show the effect, option: 'render'|'emphasis'
        showEffectOn: 'render',

        // Ripple effect config
        rippleEffect: {
            period: 4,
            // Scale of ripple
            scale: 2.5,
            // Brush type can be fill or stroke
            brushType: 'fill'
        },

        // Cartesian coordinate system
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // Polar coordinate system
        // polarIndex: 0,

        // Geo coordinate system
        // geoIndex: 0,

        // symbol: null,        // 图形类型
        symbolSize: 10          // 图形大小，半宽（半径）参数，当图形为方向或菱形则总宽度为symbolSize * 2
        // symbolRotate: null,  // 图形旋转控制

        // large: false,
        // Available when large is true
        // largeThreshold: 2000,

        // itemStyle: {
        //     opacity: 1
        // }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Symbol with ripple effect
 * @module echarts/chart/helper/EffectSymbol
 */

var EFFECT_RIPPLE_NUMBER = 3;

function normalizeSymbolSize$1(symbolSize) {
    if (!isArray(symbolSize)) {
        symbolSize = [+symbolSize, +symbolSize];
    }
    return symbolSize;
}

function updateRipplePath(rippleGroup, effectCfg) {
    var color = effectCfg.rippleEffectColor || effectCfg.color;
    rippleGroup.eachChild(function (ripplePath) {
        ripplePath.attr({
            z: effectCfg.z,
            zlevel: effectCfg.zlevel,
            style: {
                stroke: effectCfg.brushType === 'stroke' ? color : null,
                fill: effectCfg.brushType === 'fill' ? color : null
            }
        });
    });
}
/**
 * @constructor
 * @param {module:echarts/data/List} data
 * @param {number} idx
 * @extends {module:zrender/graphic/Group}
 */
function EffectSymbol(data, idx) {
    Group.call(this);

    var symbol = new SymbolClz$1(data, idx);
    var rippleGroup = new Group();
    this.add(symbol);
    this.add(rippleGroup);

    rippleGroup.beforeUpdate = function () {
        this.attr(symbol.getScale());
    };
    this.updateData(data, idx);
}

var effectSymbolProto = EffectSymbol.prototype;

effectSymbolProto.stopEffectAnimation = function () {
    this.childAt(1).removeAll();
};

effectSymbolProto.startEffectAnimation = function (effectCfg) {
    var symbolType = effectCfg.symbolType;
    var color = effectCfg.color;
    var rippleGroup = this.childAt(1);

    for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) {
        // If width/height are set too small (e.g., set to 1) on ios10
        // and macOS Sierra, a circle stroke become a rect, no matter what
        // the scale is set. So we set width/height as 2. See #4136.
        var ripplePath = createSymbol(
            symbolType, -1, -1, 2, 2, color
        );
        ripplePath.attr({
            style: {
                strokeNoScale: true
            },
            z2: 99,
            silent: true,
            scale: [0.5, 0.5]
        });

        var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset;
        // TODO Configurable effectCfg.period
        ripplePath.animate('', true)
            .when(effectCfg.period, {
                scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2]
            })
            .delay(delay)
            .start();
        ripplePath.animateStyle(true)
            .when(effectCfg.period, {
                opacity: 0
            })
            .delay(delay)
            .start();

        rippleGroup.add(ripplePath);
    }

    updateRipplePath(rippleGroup, effectCfg);
};

/**
 * Update effect symbol
 */
effectSymbolProto.updateEffectAnimation = function (effectCfg) {
    var oldEffectCfg = this._effectCfg;
    var rippleGroup = this.childAt(1);

    // Must reinitialize effect if following configuration changed
    var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale'];
    for (var i = 0; i < DIFFICULT_PROPS.length; i++) {
        var propName = DIFFICULT_PROPS[i];
        if (oldEffectCfg[propName] !== effectCfg[propName]) {
            this.stopEffectAnimation();
            this.startEffectAnimation(effectCfg);
            return;
        }
    }

    updateRipplePath(rippleGroup, effectCfg);
};

/**
 * Highlight symbol
 */
effectSymbolProto.highlight = function () {
    this.trigger('emphasis');
};

/**
 * Downplay symbol
 */
effectSymbolProto.downplay = function () {
    this.trigger('normal');
};

/**
 * Update symbol properties
 * @param  {module:echarts/data/List} data
 * @param  {number} idx
 */
effectSymbolProto.updateData = function (data, idx) {
    var seriesModel = data.hostModel;

    this.childAt(0).updateData(data, idx);

    var rippleGroup = this.childAt(1);
    var itemModel = data.getItemModel(idx);
    var symbolType = data.getItemVisual(idx, 'symbol');
    var symbolSize = normalizeSymbolSize$1(data.getItemVisual(idx, 'symbolSize'));
    var color = data.getItemVisual(idx, 'color');

    rippleGroup.attr('scale', symbolSize);

    rippleGroup.traverse(function (ripplePath) {
        ripplePath.attr({
            fill: color
        });
    });

    var symbolOffset = itemModel.getShallow('symbolOffset');
    if (symbolOffset) {
        var pos = rippleGroup.position;
        pos[0] = parsePercent$1(symbolOffset[0], symbolSize[0]);
        pos[1] = parsePercent$1(symbolOffset[1], symbolSize[1]);
    }
    rippleGroup.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0;

    var effectCfg = {};

    effectCfg.showEffectOn = seriesModel.get('showEffectOn');
    effectCfg.rippleScale = itemModel.get('rippleEffect.scale');
    effectCfg.brushType = itemModel.get('rippleEffect.brushType');
    effectCfg.period = itemModel.get('rippleEffect.period') * 1000;
    effectCfg.effectOffset = idx / data.count();
    effectCfg.z = itemModel.getShallow('z') || 0;
    effectCfg.zlevel = itemModel.getShallow('zlevel') || 0;
    effectCfg.symbolType = symbolType;
    effectCfg.color = color;
    effectCfg.rippleEffectColor = itemModel.get('rippleEffect.color');

    this.off('mouseover').off('mouseout').off('emphasis').off('normal');

    if (effectCfg.showEffectOn === 'render') {
        this._effectCfg
            ? this.updateEffectAnimation(effectCfg)
            : this.startEffectAnimation(effectCfg);

        this._effectCfg = effectCfg;
    }
    else {
        // Not keep old effect config
        this._effectCfg = null;

        this.stopEffectAnimation();
        var symbol = this.childAt(0);
        var onEmphasis = function () {
            symbol.highlight();
            if (effectCfg.showEffectOn !== 'render') {
                this.startEffectAnimation(effectCfg);
            }
        };
        var onNormal = function () {
            symbol.downplay();
            if (effectCfg.showEffectOn !== 'render') {
                this.stopEffectAnimation();
            }
        };
        this.on('mouseover', onEmphasis, this)
            .on('mouseout', onNormal, this)
            .on('emphasis', onEmphasis, this)
            .on('normal', onNormal, this);
    }

    this._effectCfg = effectCfg;
};

effectSymbolProto.fadeOut = function (cb) {
    this.off('mouseover').off('mouseout').off('emphasis').off('normal');
    cb && cb();
};

inherits(EffectSymbol, Group);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendChartView({

    type: 'effectScatter',

    init: function () {
        this._symbolDraw = new SymbolDraw(EffectSymbol);
    },

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var effectSymbolDraw = this._symbolDraw;
        effectSymbolDraw.updateData(data);
        this.group.add(effectSymbolDraw.group);
    },

    updateTransform: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();

        this.group.dirty();

        var res = pointsLayout().reset(seriesModel);
        if (res.progress) {
            res.progress({ start: 0, end: data.count() }, data);
        }

        this._symbolDraw.updateLayout(data);
    },

    _updateGroupTransform: function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;
        if (coordSys && coordSys.getRoamTransform) {
            this.group.transform = clone$2(coordSys.getRoamTransform());
            this.group.decomposeTransform();
        }
    },

    remove: function (ecModel, api) {
        this._symbolDraw && this._symbolDraw.remove(api);
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(visualSymbol('effectScatter', 'circle'));
registerLayout(pointsLayout('effectScatter'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Uint32Array, Float64Array, Float32Array */

var Uint32Arr = typeof Uint32Array === 'undefined' ? Array : Uint32Array;
var Float64Arr = typeof Float64Array === 'undefined' ? Array : Float64Array;

function compatEc2(seriesOpt) {
    var data = seriesOpt.data;
    if (data && data[0] && data[0][0] && data[0][0].coord) {
        if (__DEV__) {
            console.warn('Lines data configuration has been changed to'
                + ' { coords:[[1,2],[2,3]] }');
        }
        seriesOpt.data = map(data, function (itemOpt) {
            var coords = [
                itemOpt[0].coord, itemOpt[1].coord
            ];
            var target = {
                coords: coords
            };
            if (itemOpt[0].name) {
                target.fromName = itemOpt[0].name;
            }
            if (itemOpt[1].name) {
                target.toName = itemOpt[1].name;
            }
            return mergeAll([target, itemOpt[0], itemOpt[1]]);
        });
    }
}

var LinesSeries = SeriesModel.extend({

    type: 'series.lines',

    dependencies: ['grid', 'polar'],

    visualColorAccessPath: 'lineStyle.color',

    init: function (option) {
        // The input data may be null/undefined.
        option.data = option.data || [];

        // Not using preprocessor because mergeOption may not have series.type
        compatEc2(option);

        var result = this._processFlatCoordsArray(option.data);
        this._flatCoords = result.flatCoords;
        this._flatCoordsOffset = result.flatCoordsOffset;
        if (result.flatCoords) {
            option.data = new Float32Array(result.count);
        }

        LinesSeries.superApply(this, 'init', arguments);
    },

    mergeOption: function (option) {
        // The input data may be null/undefined.
        option.data = option.data || [];

        compatEc2(option);

        if (option.data) {
            // Only update when have option data to merge.
            var result = this._processFlatCoordsArray(option.data);
            this._flatCoords = result.flatCoords;
            this._flatCoordsOffset = result.flatCoordsOffset;
            if (result.flatCoords) {
                option.data = new Float32Array(result.count);
            }
        }

        LinesSeries.superApply(this, 'mergeOption', arguments);
    },

    appendData: function (params) {
        var result = this._processFlatCoordsArray(params.data);
        if (result.flatCoords) {
            if (!this._flatCoords) {
                this._flatCoords = result.flatCoords;
                this._flatCoordsOffset = result.flatCoordsOffset;
            }
            else {
                this._flatCoords = concatArray(this._flatCoords, result.flatCoords);
                this._flatCoordsOffset = concatArray(this._flatCoordsOffset, result.flatCoordsOffset);
            }
            params.data = new Float32Array(result.count);
        }

        this.getRawData().appendData(params.data);
    },

    _getCoordsFromItemModel: function (idx) {
        var itemModel = this.getData().getItemModel(idx);
        var coords = (itemModel.option instanceof Array)
            ? itemModel.option : itemModel.getShallow('coords');

        if (__DEV__) {
            if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) {
                throw new Error(
                    'Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'
                );
            }
        }
        return coords;
    },

    getLineCoordsCount: function (idx) {
        if (this._flatCoordsOffset) {
            return this._flatCoordsOffset[idx * 2 + 1];
        }
        else {
            return this._getCoordsFromItemModel(idx).length;
        }
    },

    getLineCoords: function (idx, out) {
        if (this._flatCoordsOffset) {
            var offset = this._flatCoordsOffset[idx * 2];
            var len = this._flatCoordsOffset[idx * 2 + 1];
            for (var i = 0; i < len; i++) {
                out[i] = out[i] || [];
                out[i][0] = this._flatCoords[offset + i * 2];
                out[i][1] = this._flatCoords[offset + i * 2 + 1];
            }
            return len;
        }
        else {
            var coords = this._getCoordsFromItemModel(idx);
            for (var i = 0; i < coords.length; i++) {
                out[i] = out[i] || [];
                out[i][0] = coords[i][0];
                out[i][1] = coords[i][1];
            }
            return coords.length;
        }
    },

    _processFlatCoordsArray: function (data) {
        var startOffset = 0;
        if (this._flatCoords) {
            startOffset = this._flatCoords.length;
        }
        // Stored as a typed array. In format
        // Points Count(2) | x | y | x | y | Points Count(3) | x |  y | x | y | x | y |
        if (typeof data[0] === 'number') {
            var len = data.length;
            // Store offset and len of each segment
            var coordsOffsetAndLenStorage = new Uint32Arr(len);
            var coordsStorage = new Float64Arr(len);
            var coordsCursor = 0;
            var offsetCursor = 0;
            var dataCount = 0;
            for (var i = 0; i < len;) {
                dataCount++;
                var count = data[i++];
                // Offset
                coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset;
                // Len
                coordsOffsetAndLenStorage[offsetCursor++] = count;
                for (var k = 0; k < count; k++) {
                    var x = data[i++];
                    var y = data[i++];
                    coordsStorage[coordsCursor++] = x;
                    coordsStorage[coordsCursor++] = y;

                    if (i > len) {
                        if (__DEV__) {
                            throw new Error('Invalid data format.');
                        }
                    }
                }
            }

            return {
                flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor),
                flatCoords: coordsStorage,
                count: dataCount
            };
        }

        return {
            flatCoordsOffset: null,
            flatCoords: null,
            count: data.length
        };
    },

    getInitialData: function (option, ecModel) {
        if (__DEV__) {
            var CoordSys = CoordinateSystemManager.get(option.coordinateSystem);
            if (!CoordSys) {
                throw new Error('Unkown coordinate system ' + option.coordinateSystem);
            }
        }

        var lineData = new List(['value'], this);
        lineData.hasItemOption = false;

        lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) {
            // dataItem is simply coords
            if (dataItem instanceof Array) {
                return NaN;
            }
            else {
                lineData.hasItemOption = true;
                var value = dataItem.value;
                if (value != null) {
                    return value instanceof Array ? value[dimIndex] : value;
                }
            }
        });

        return lineData;
    },

    formatTooltip: function (dataIndex) {
        var data = this.getData();
        var itemModel = data.getItemModel(dataIndex);
        var name = itemModel.get('name');
        if (name) {
            return name;
        }
        var fromName = itemModel.get('fromName');
        var toName = itemModel.get('toName');
        var html = [];
        fromName != null && html.push(fromName);
        toName != null && html.push(toName);

        return encodeHTML(html.join(' > '));
    },

    preventIncremental: function () {
        return !!this.get('effect.show');
    },

    getProgressive: function () {
        var progressive = this.option.progressive;
        if (progressive == null) {
            return this.option.large ? 1e4 : this.get('progressive');
        }
        return progressive;
    },

    getProgressiveThreshold: function () {
        var progressiveThreshold = this.option.progressiveThreshold;
        if (progressiveThreshold == null) {
            return this.option.large ? 2e4 : this.get('progressiveThreshold');
        }
        return progressiveThreshold;
    },

    defaultOption: {
        coordinateSystem: 'geo',
        zlevel: 0,
        z: 2,
        legendHoverLink: true,

        hoverAnimation: true,
        // Cartesian coordinate system
        xAxisIndex: 0,
        yAxisIndex: 0,

        symbol: ['none', 'none'],
        symbolSize: [10, 10],
        // Geo coordinate system
        geoIndex: 0,

        effect: {
            show: false,
            period: 4,
            // Animation delay. support callback
            // delay: 0,
            // If move with constant speed px/sec
            // period will be ignored if this property is > 0,
            constantSpeed: 0,
            symbol: 'circle',
            symbolSize: 3,
            loop: true,
            // Length of trail, 0 - 1
            trailLength: 0.2
            // Same with lineStyle.color
            // color
        },

        large: false,
        // Available when large is true
        largeThreshold: 2000,

        // If lines are polyline
        // polyline not support curveness, label, animation
        polyline: false,

        // If clip the overflow.
        // Available when coordinateSystem is cartesian or polar.
        clip: true,

        label: {
            show: false,
            position: 'end'
            // distance: 5,
            // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
        },

        lineStyle: {
            opacity: 0.5
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Provide effect for line
 * @module echarts/chart/helper/EffectLine
 */

/**
 * @constructor
 * @extends {module:zrender/graphic/Group}
 * @alias {module:echarts/chart/helper/Line}
 */
function EffectLine(lineData, idx, seriesScope) {
    Group.call(this);

    this.add(this.createLine(lineData, idx, seriesScope));

    this._updateEffectSymbol(lineData, idx);
}

var effectLineProto = EffectLine.prototype;

effectLineProto.createLine = function (lineData, idx, seriesScope) {
    return new Line$1(lineData, idx, seriesScope);
};

effectLineProto._updateEffectSymbol = function (lineData, idx) {
    var itemModel = lineData.getItemModel(idx);
    var effectModel = itemModel.getModel('effect');
    var size = effectModel.get('symbolSize');
    var symbolType = effectModel.get('symbol');
    if (!isArray(size)) {
        size = [size, size];
    }
    var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color');
    var symbol = this.childAt(1);

    if (this._symbolType !== symbolType) {
        // Remove previous
        this.remove(symbol);

        symbol = createSymbol(
            symbolType, -0.5, -0.5, 1, 1, color
        );
        symbol.z2 = 100;
        symbol.culling = true;

        this.add(symbol);
    }

    // Symbol may be removed if loop is false
    if (!symbol) {
        return;
    }

    // Shadow color is same with color in default
    symbol.setStyle('shadowColor', color);
    symbol.setStyle(effectModel.getItemStyle(['color']));

    symbol.attr('scale', size);

    symbol.setColor(color);
    symbol.attr('scale', size);

    this._symbolType = symbolType;

    this._updateEffectAnimation(lineData, effectModel, idx);
};

effectLineProto._updateEffectAnimation = function (lineData, effectModel, idx) {

    var symbol = this.childAt(1);
    if (!symbol) {
        return;
    }

    var self = this;

    var points = lineData.getItemLayout(idx);

    var period = effectModel.get('period') * 1000;
    var loop = effectModel.get('loop');
    var constantSpeed = effectModel.get('constantSpeed');
    var delayExpr = retrieve(effectModel.get('delay'), function (idx) {
        return idx / lineData.count() * period / 3;
    });
    var isDelayFunc = typeof delayExpr === 'function';

    // Ignore when updating
    symbol.ignore = true;

    this.updateAnimationPoints(symbol, points);

    if (constantSpeed > 0) {
        period = this.getLineLength(symbol) / constantSpeed * 1000;
    }

    if (period !== this._period || loop !== this._loop) {

        symbol.stopAnimation();

        var delay = delayExpr;
        if (isDelayFunc) {
            delay = delayExpr(idx);
        }
        if (symbol.__t > 0) {
            delay = -period * symbol.__t;
        }
        symbol.__t = 0;
        var animator = symbol.animate('', loop)
            .when(period, {
                __t: 1
            })
            .delay(delay)
            .during(function () {
                self.updateSymbolPosition(symbol);
            });
        if (!loop) {
            animator.done(function () {
                self.remove(symbol);
            });
        }
        animator.start();
    }

    this._period = period;
    this._loop = loop;
};

effectLineProto.getLineLength = function (symbol) {
    // Not so accurate
    return (dist(symbol.__p1, symbol.__cp1)
        + dist(symbol.__cp1, symbol.__p2));
};

effectLineProto.updateAnimationPoints = function (symbol, points) {
    symbol.__p1 = points[0];
    symbol.__p2 = points[1];
    symbol.__cp1 = points[2] || [
        (points[0][0] + points[1][0]) / 2,
        (points[0][1] + points[1][1]) / 2
    ];
};

effectLineProto.updateData = function (lineData, idx, seriesScope) {
    this.childAt(0).updateData(lineData, idx, seriesScope);
    this._updateEffectSymbol(lineData, idx);
};

effectLineProto.updateSymbolPosition = function (symbol) {
    var p1 = symbol.__p1;
    var p2 = symbol.__p2;
    var cp1 = symbol.__cp1;
    var t = symbol.__t;
    var pos = symbol.position;
    var quadraticAt$$1 = quadraticAt;
    var quadraticDerivativeAt$$1 = quadraticDerivativeAt;
    pos[0] = quadraticAt$$1(p1[0], cp1[0], p2[0], t);
    pos[1] = quadraticAt$$1(p1[1], cp1[1], p2[1], t);

    // Tangent
    var tx = quadraticDerivativeAt$$1(p1[0], cp1[0], p2[0], t);
    var ty = quadraticDerivativeAt$$1(p1[1], cp1[1], p2[1], t);

    symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;

    symbol.ignore = false;
};


effectLineProto.updateLayout = function (lineData, idx) {
    this.childAt(0).updateLayout(lineData, idx);

    var effectModel = lineData.getItemModel(idx).getModel('effect');
    this._updateEffectAnimation(lineData, effectModel, idx);
};

inherits(EffectLine, Group);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/chart/helper/Line
 */

/**
 * @constructor
 * @extends {module:zrender/graphic/Group}
 * @alias {module:echarts/chart/helper/Polyline}
 */
function Polyline$2(lineData, idx, seriesScope) {
    Group.call(this);

    this._createPolyline(lineData, idx, seriesScope);
}

var polylineProto = Polyline$2.prototype;

polylineProto._createPolyline = function (lineData, idx, seriesScope) {
    // var seriesModel = lineData.hostModel;
    var points = lineData.getItemLayout(idx);

    var line = new Polyline({
        shape: {
            points: points
        }
    });

    this.add(line);

    this._updateCommonStl(lineData, idx, seriesScope);
};

polylineProto.updateData = function (lineData, idx, seriesScope) {
    var seriesModel = lineData.hostModel;

    var line = this.childAt(0);
    var target = {
        shape: {
            points: lineData.getItemLayout(idx)
        }
    };
    updateProps(line, target, seriesModel, idx);

    this._updateCommonStl(lineData, idx, seriesScope);
};

polylineProto._updateCommonStl = function (lineData, idx, seriesScope) {
    var line = this.childAt(0);
    var itemModel = lineData.getItemModel(idx);

    var visualColor = lineData.getItemVisual(idx, 'color');

    var lineStyle = seriesScope && seriesScope.lineStyle;
    var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle;

    if (!seriesScope || lineData.hasItemOption) {
        lineStyle = itemModel.getModel('lineStyle').getLineStyle();
        hoverLineStyle = itemModel.getModel('emphasis.lineStyle').getLineStyle();
    }
    line.useStyle(defaults(
        {
            strokeNoScale: true,
            fill: 'none',
            stroke: visualColor
        },
        lineStyle
    ));
    line.hoverStyle = hoverLineStyle;

    setHoverStyle(this);
};

polylineProto.updateLayout = function (lineData, idx) {
    var polyline = this.childAt(0);
    polyline.setShape('points', lineData.getItemLayout(idx));
};

inherits(Polyline$2, Group);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Provide effect for line
 * @module echarts/chart/helper/EffectLine
 */

/**
 * @constructor
 * @extends {module:echarts/chart/helper/EffectLine}
 * @alias {module:echarts/chart/helper/Polyline}
 */
function EffectPolyline(lineData, idx, seriesScope) {
    EffectLine.call(this, lineData, idx, seriesScope);
    this._lastFrame = 0;
    this._lastFramePercent = 0;
}

var effectPolylineProto = EffectPolyline.prototype;

// Overwrite
effectPolylineProto.createLine = function (lineData, idx, seriesScope) {
    return new Polyline$2(lineData, idx, seriesScope);
};

// Overwrite
effectPolylineProto.updateAnimationPoints = function (symbol, points) {
    this._points = points;
    var accLenArr = [0];
    var len$$1 = 0;
    for (var i = 1; i < points.length; i++) {
        var p1 = points[i - 1];
        var p2 = points[i];
        len$$1 += dist(p1, p2);
        accLenArr.push(len$$1);
    }
    if (len$$1 === 0) {
        return;
    }

    for (var i = 0; i < accLenArr.length; i++) {
        accLenArr[i] /= len$$1;
    }
    this._offsets = accLenArr;
    this._length = len$$1;
};

// Overwrite
effectPolylineProto.getLineLength = function (symbol) {
    return this._length;
};

// Overwrite
effectPolylineProto.updateSymbolPosition = function (symbol) {
    var t = symbol.__t;
    var points = this._points;
    var offsets = this._offsets;
    var len$$1 = points.length;

    if (!offsets) {
        // Has length 0
        return;
    }

    var lastFrame = this._lastFrame;
    var frame;

    if (t < this._lastFramePercent) {
        // Start from the next frame
        // PENDING start from lastFrame ?
        var start = Math.min(lastFrame + 1, len$$1 - 1);
        for (frame = start; frame >= 0; frame--) {
            if (offsets[frame] <= t) {
                break;
            }
        }
        // PENDING really need to do this ?
        frame = Math.min(frame, len$$1 - 2);
    }
    else {
        for (var frame = lastFrame; frame < len$$1; frame++) {
            if (offsets[frame] > t) {
                break;
            }
        }
        frame = Math.min(frame - 1, len$$1 - 2);
    }

    lerp(
        symbol.position, points[frame], points[frame + 1],
        (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame])
    );

    var tx = points[frame + 1][0] - points[frame][0];
    var ty = points[frame + 1][1] - points[frame][1];
    symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;

    this._lastFrame = frame;
    this._lastFramePercent = t;

    symbol.ignore = false;
};

inherits(EffectPolyline, EffectLine);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO Batch by color

var LargeLineShape = extendShape({

    shape: {
        polyline: false,
        curveness: 0,
        segs: []
    },

    buildPath: function (path, shape) {
        var segs = shape.segs;
        var curveness = shape.curveness;

        if (shape.polyline) {
            for (var i = 0; i < segs.length;) {
                var count = segs[i++];
                if (count > 0) {
                    path.moveTo(segs[i++], segs[i++]);
                    for (var k = 1; k < count; k++) {
                        path.lineTo(segs[i++], segs[i++]);
                    }
                }
            }
        }
        else {
            for (var i = 0; i < segs.length;) {
                var x0 = segs[i++];
                var y0 = segs[i++];
                var x1 = segs[i++];
                var y1 = segs[i++];
                path.moveTo(x0, y0);
                if (curveness > 0) {
                    var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
                    var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;
                    path.quadraticCurveTo(x2, y2, x1, y1);
                }
                else {
                    path.lineTo(x1, y1);
                }
            }
        }
    },

    findDataIndex: function (x, y) {

        var shape = this.shape;
        var segs = shape.segs;
        var curveness = shape.curveness;

        if (shape.polyline) {
            var dataIndex = 0;
            for (var i = 0; i < segs.length;) {
                var count = segs[i++];
                if (count > 0) {
                    var x0 = segs[i++];
                    var y0 = segs[i++];
                    for (var k = 1; k < count; k++) {
                        var x1 = segs[i++];
                        var y1 = segs[i++];
                        if (containStroke$1(x0, y0, x1, y1)) {
                            return dataIndex;
                        }
                    }
                }

                dataIndex++;
            }
        }
        else {
            var dataIndex = 0;
            for (var i = 0; i < segs.length;) {
                var x0 = segs[i++];
                var y0 = segs[i++];
                var x1 = segs[i++];
                var y1 = segs[i++];
                if (curveness > 0) {
                    var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
                    var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;

                    if (containStroke$3(x0, y0, x2, y2, x1, y1)) {
                        return dataIndex;
                    }
                }
                else {
                    if (containStroke$1(x0, y0, x1, y1)) {
                        return dataIndex;
                    }
                }

                dataIndex++;
            }
        }

        return -1;
    }
});

function LargeLineDraw() {
    this.group = new Group();
}

var largeLineProto = LargeLineDraw.prototype;

largeLineProto.isPersistent = function () {
    return !this._incremental;
};

/**
 * Update symbols draw by new data
 * @param {module:echarts/data/List} data
 */
largeLineProto.updateData = function (data) {
    this.group.removeAll();

    var lineEl = new LargeLineShape({
        rectHover: true,
        cursor: 'default'
    });
    lineEl.setShape({
        segs: data.getLayout('linesPoints')
    });

    this._setCommon(lineEl, data);

    // Add back
    this.group.add(lineEl);

    this._incremental = null;
};

/**
 * @override
 */
largeLineProto.incrementalPrepareUpdate = function (data) {
    this.group.removeAll();

    this._clearIncremental();

    if (data.count() > 5e5) {
        if (!this._incremental) {
            this._incremental = new IncrementalDisplayble({
                silent: true
            });
        }
        this.group.add(this._incremental);
    }
    else {
        this._incremental = null;
    }
};

/**
 * @override
 */
largeLineProto.incrementalUpdate = function (taskParams, data) {
    var lineEl = new LargeLineShape();
    lineEl.setShape({
        segs: data.getLayout('linesPoints')
    });

    this._setCommon(lineEl, data, !!this._incremental);

    if (!this._incremental) {
        lineEl.rectHover = true;
        lineEl.cursor = 'default';
        lineEl.__startIndex = taskParams.start;
        this.group.add(lineEl);
    }
    else {
        this._incremental.addDisplayable(lineEl, true);
    }
};

/**
 * @override
 */
largeLineProto.remove = function () {
    this._clearIncremental();
    this._incremental = null;
    this.group.removeAll();
};

largeLineProto._setCommon = function (lineEl, data, isIncremental) {
    var hostModel = data.hostModel;

    lineEl.setShape({
        polyline: hostModel.get('polyline'),
        curveness: hostModel.get('lineStyle.curveness')
    });

    lineEl.useStyle(
        hostModel.getModel('lineStyle').getLineStyle()
    );
    lineEl.style.strokeNoScale = true;

    var visualColor = data.getVisual('color');
    if (visualColor) {
        lineEl.setStyle('stroke', visualColor);
    }
    lineEl.setStyle('fill');

    if (!isIncremental) {
        // Enable tooltip
        // PENDING May have performance issue when path is extremely large
        lineEl.seriesIndex = hostModel.seriesIndex;
        lineEl.on('mousemove', function (e) {
            lineEl.dataIndex = null;
            var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY);
            if (dataIndex > 0) {
                // Provide dataIndex for tooltip
                lineEl.dataIndex = dataIndex + lineEl.__startIndex;
            }
        });
    }
};

largeLineProto._clearIncremental = function () {
    var incremental = this._incremental;
    if (incremental) {
        incremental.clearDisplaybles();
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Float32Array */

var linesLayout = {
    seriesType: 'lines',

    plan: createRenderPlanner(),

    reset: function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;
        var isPolyline = seriesModel.get('polyline');
        var isLarge = seriesModel.pipelineContext.large;

        function progress(params, lineData) {
            var lineCoords = [];
            if (isLarge) {
                var points;
                var segCount = params.end - params.start;
                if (isPolyline) {
                    var totalCoordsCount = 0;
                    for (var i = params.start; i < params.end; i++) {
                        totalCoordsCount += seriesModel.getLineCoordsCount(i);
                    }
                    points = new Float32Array(segCount + totalCoordsCount * 2);
                }
                else {
                    points = new Float32Array(segCount * 4);
                }

                var offset = 0;
                var pt = [];
                for (var i = params.start; i < params.end; i++) {
                    var len = seriesModel.getLineCoords(i, lineCoords);
                    if (isPolyline) {
                        points[offset++] = len;
                    }
                    for (var k = 0; k < len; k++) {
                        pt = coordSys.dataToPoint(lineCoords[k], false, pt);
                        points[offset++] = pt[0];
                        points[offset++] = pt[1];
                    }
                }

                lineData.setLayout('linesPoints', points);
            }
            else {
                for (var i = params.start; i < params.end; i++) {
                    var itemModel = lineData.getItemModel(i);
                    var len = seriesModel.getLineCoords(i, lineCoords);

                    var pts = [];
                    if (isPolyline) {
                        for (var j = 0; j < len; j++) {
                            pts.push(coordSys.dataToPoint(lineCoords[j]));
                        }
                    }
                    else {
                        pts[0] = coordSys.dataToPoint(lineCoords[0]);
                        pts[1] = coordSys.dataToPoint(lineCoords[1]);

                        var curveness = itemModel.get('lineStyle.curveness');
                        if (+curveness) {
                            pts[2] = [
                                (pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness,
                                (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness
                            ];
                        }
                    }
                    lineData.setItemLayout(i, pts);
                }
            }
        }

        return { progress: progress };
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendChartView({

    type: 'lines',

    init: function () {},

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();

        var lineDraw = this._updateLineDraw(data, seriesModel);

        var zlevel = seriesModel.get('zlevel');
        var trailLength = seriesModel.get('effect.trailLength');

        var zr = api.getZr();
        // Avoid the drag cause ghost shadow
        // FIXME Better way ?
        // SVG doesn't support
        var isSvg = zr.painter.getType() === 'svg';
        if (!isSvg) {
            zr.painter.getLayer(zlevel).clear(true);
        }
        // Config layer with motion blur
        if (this._lastZlevel != null && !isSvg) {
            zr.configLayer(this._lastZlevel, {
                motionBlur: false
            });
        }
        if (this._showEffect(seriesModel) && trailLength) {
            if (__DEV__) {
                var notInIndividual = false;
                ecModel.eachSeries(function (otherSeriesModel) {
                    if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) {
                        notInIndividual = true;
                    }
                });
                notInIndividual && console.warn('Lines with trail effect should have an individual zlevel');
            }

            if (!isSvg) {
                zr.configLayer(zlevel, {
                    motionBlur: true,
                    lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0)
                });
            }
        }

        lineDraw.updateData(data);

        var clipPath = seriesModel.get('clip', true) && createClipPath(
            seriesModel.coordinateSystem, false, seriesModel
        );
        if (clipPath) {
            this.group.setClipPath(clipPath);
        }
        else {
            this.group.removeClipPath();
        }

        this._lastZlevel = zlevel;

        this._finished = true;
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();

        var lineDraw = this._updateLineDraw(data, seriesModel);

        lineDraw.incrementalPrepareUpdate(data);

        this._clearLayer(api);

        this._finished = false;
    },

    incrementalRender: function (taskParams, seriesModel, ecModel) {
        this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData());

        this._finished = taskParams.end === seriesModel.getData().count();
    },

    updateTransform: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();
        var pipelineContext = seriesModel.pipelineContext;

        if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) {
            // TODO Don't have to do update in large mode. Only do it when there are millions of data.
            return {
                update: true
            };
        }
        else {
            // TODO Use same logic with ScatterView.
            // Manually update layout
            var res = linesLayout.reset(seriesModel);
            if (res.progress) {
                res.progress({ start: 0, end: data.count() }, data);
            }
            this._lineDraw.updateLayout();
            this._clearLayer(api);
        }
    },

    _updateLineDraw: function (data, seriesModel) {
        var lineDraw = this._lineDraw;
        var hasEffect = this._showEffect(seriesModel);
        var isPolyline = !!seriesModel.get('polyline');
        var pipelineContext = seriesModel.pipelineContext;
        var isLargeDraw = pipelineContext.large;

        if (__DEV__) {
            if (hasEffect && isLargeDraw) {
                console.warn('Large lines not support effect');
            }
        }
        if (!lineDraw
            || hasEffect !== this._hasEffet
            || isPolyline !== this._isPolyline
            || isLargeDraw !== this._isLargeDraw
        ) {
            if (lineDraw) {
                lineDraw.remove();
            }
            lineDraw = this._lineDraw = isLargeDraw
                ? new LargeLineDraw()
                : new LineDraw(
                    isPolyline
                        ? (hasEffect ? EffectPolyline : Polyline$2)
                        : (hasEffect ? EffectLine : Line$1)
                );
            this._hasEffet = hasEffect;
            this._isPolyline = isPolyline;
            this._isLargeDraw = isLargeDraw;
            this.group.removeAll();
        }

        this.group.add(lineDraw.group);

        return lineDraw;
    },

    _showEffect: function (seriesModel) {
        return !!seriesModel.get('effect.show');
    },

    _clearLayer: function (api) {
        // Not use motion when dragging or zooming
        var zr = api.getZr();
        var isSvg = zr.painter.getType() === 'svg';
        if (!isSvg && this._lastZlevel != null) {
            zr.painter.getLayer(this._lastZlevel).clear(true);
        }
    },

    remove: function (ecModel, api) {
        this._lineDraw && this._lineDraw.remove();
        this._lineDraw = null;
        // Clear motion when lineDraw is removed
        this._clearLayer(api);
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


function normalize$2(a) {
    if (!(a instanceof Array)) {
        a = [a, a];
    }
    return a;
}

var opacityQuery = 'lineStyle.opacity'.split('.');

var linesVisual = {
    seriesType: 'lines',
    reset: function (seriesModel, ecModel, api) {
        var symbolType = normalize$2(seriesModel.get('symbol'));
        var symbolSize = normalize$2(seriesModel.get('symbolSize'));
        var data = seriesModel.getData();

        data.setVisual('fromSymbol', symbolType && symbolType[0]);
        data.setVisual('toSymbol', symbolType && symbolType[1]);
        data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
        data.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
        data.setVisual('opacity', seriesModel.get(opacityQuery));

        function dataEach(data, idx) {
            var itemModel = data.getItemModel(idx);
            var symbolType = normalize$2(itemModel.getShallow('symbol', true));
            var symbolSize = normalize$2(itemModel.getShallow('symbolSize', true));
            var opacity = itemModel.get(opacityQuery);

            symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]);
            symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]);
            symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]);
            symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]);

            data.setItemVisual(idx, 'opacity', opacity);
        }

        return {dataEach: data.hasItemOption ? dataEach : null};
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerLayout(linesLayout);
registerVisual(linesVisual);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({
    type: 'series.heatmap',

    getInitialData: function (option, ecModel) {
        return createListFromArray(this.getSource(), this, {
            generateCoord: 'value'
        });
    },

    preventIncremental: function () {
        var coordSysCreator = CoordinateSystemManager.get(this.get('coordinateSystem'));
        if (coordSysCreator && coordSysCreator.dimensions) {
            return coordSysCreator.dimensions[0] === 'lng' && coordSysCreator.dimensions[1] === 'lat';
        }
    },

    defaultOption: {

        // Cartesian2D or geo
        coordinateSystem: 'cartesian2d',

        zlevel: 0,

        z: 2,

        // Cartesian coordinate system
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // Geo coordinate system
        geoIndex: 0,

        blurSize: 30,

        pointSize: 20,

        maxOpacity: 1,

        minOpacity: 0
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Uint8ClampedArray */

var GRADIENT_LEVELS = 256;

/**
 * Heatmap Chart
 *
 * @class
 */
function Heatmap() {
    var canvas = createCanvas();
    this.canvas = canvas;

    this.blurSize = 30;
    this.pointSize = 20;

    this.maxOpacity = 1;
    this.minOpacity = 0;

    this._gradientPixels = {};
}

Heatmap.prototype = {
    /**
     * Renders Heatmap and returns the rendered canvas
     * @param {Array} data array of data, each has x, y, value
     * @param {number} width canvas width
     * @param {number} height canvas height
     */
    update: function (data, width, height, normalize, colorFunc, isInRange) {
        var brush = this._getBrush();
        var gradientInRange = this._getGradient(data, colorFunc, 'inRange');
        var gradientOutOfRange = this._getGradient(data, colorFunc, 'outOfRange');
        var r = this.pointSize + this.blurSize;

        var canvas = this.canvas;
        var ctx = canvas.getContext('2d');
        var len = data.length;
        canvas.width = width;
        canvas.height = height;
        for (var i = 0; i < len; ++i) {
            var p = data[i];
            var x = p[0];
            var y = p[1];
            var value = p[2];

            // calculate alpha using value
            var alpha = normalize(value);

            // draw with the circle brush with alpha
            ctx.globalAlpha = alpha;
            ctx.drawImage(brush, x - r, y - r);
        }

        if (!canvas.width || !canvas.height) {
            // Avoid "Uncaught DOMException: Failed to execute 'getImageData' on
            // 'CanvasRenderingContext2D': The source height is 0."
            return canvas;
        }

        // colorize the canvas using alpha value and set with gradient
        var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

        var pixels = imageData.data;
        var offset = 0;
        var pixelLen = pixels.length;
        var minOpacity = this.minOpacity;
        var maxOpacity = this.maxOpacity;
        var diffOpacity = maxOpacity - minOpacity;

        while (offset < pixelLen) {
            var alpha = pixels[offset + 3] / 256;
            var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4;
            // Simple optimize to ignore the empty data
            if (alpha > 0) {
                var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange;
                // Any alpha > 0 will be mapped to [minOpacity, maxOpacity]
                alpha > 0 && (alpha = alpha * diffOpacity + minOpacity);
                pixels[offset++] = gradient[gradientOffset];
                pixels[offset++] = gradient[gradientOffset + 1];
                pixels[offset++] = gradient[gradientOffset + 2];
                pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256;
            }
            else {
                offset += 4;
            }
        }
        ctx.putImageData(imageData, 0, 0);

        return canvas;
    },

    /**
     * get canvas of a black circle brush used for canvas to draw later
     * @private
     * @returns {Object} circle brush canvas
     */
    _getBrush: function () {
        var brushCanvas = this._brushCanvas || (this._brushCanvas = createCanvas());
        // set brush size
        var r = this.pointSize + this.blurSize;
        var d = r * 2;
        brushCanvas.width = d;
        brushCanvas.height = d;

        var ctx = brushCanvas.getContext('2d');
        ctx.clearRect(0, 0, d, d);

        // in order to render shadow without the distinct circle,
        // draw the distinct circle in an invisible place,
        // and use shadowOffset to draw shadow in the center of the canvas
        ctx.shadowOffsetX = d;
        ctx.shadowBlur = this.blurSize;
        // draw the shadow in black, and use alpha and shadow blur to generate
        // color in color map
        ctx.shadowColor = '#000';

        // draw circle in the left to the canvas
        ctx.beginPath();
        ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true);
        ctx.closePath();
        ctx.fill();
        return brushCanvas;
    },

    /**
     * get gradient color map
     * @private
     */
    _getGradient: function (data, colorFunc, state) {
        var gradientPixels = this._gradientPixels;
        var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4));
        var color = [0, 0, 0, 0];
        var off = 0;
        for (var i = 0; i < 256; i++) {
            colorFunc[state](i / 255, true, color);
            pixelsSingleState[off++] = color[0];
            pixelsSingleState[off++] = color[1];
            pixelsSingleState[off++] = color[2];
            pixelsSingleState[off++] = color[3];
        }
        return pixelsSingleState;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function getIsInPiecewiseRange(dataExtent, pieceList, selected) {
    var dataSpan = dataExtent[1] - dataExtent[0];
    pieceList = map(pieceList, function (piece) {
        return {
            interval: [
                (piece.interval[0] - dataExtent[0]) / dataSpan,
                (piece.interval[1] - dataExtent[0]) / dataSpan
            ]
        };
    });
    var len = pieceList.length;
    var lastIndex = 0;

    return function (val) {
        // Try to find in the location of the last found
        for (var i = lastIndex; i < len; i++) {
            var interval = pieceList[i].interval;
            if (interval[0] <= val && val <= interval[1]) {
                lastIndex = i;
                break;
            }
        }
        if (i === len) { // Not found, back interation
            for (var i = lastIndex - 1; i >= 0; i--) {
                var interval = pieceList[i].interval;
                if (interval[0] <= val && val <= interval[1]) {
                    lastIndex = i;
                    break;
                }
            }
        }
        return i >= 0 && i < len && selected[i];
    };
}

function getIsInContinuousRange(dataExtent, range) {
    var dataSpan = dataExtent[1] - dataExtent[0];
    range = [
        (range[0] - dataExtent[0]) / dataSpan,
        (range[1] - dataExtent[0]) / dataSpan
    ];
    return function (val) {
        return val >= range[0] && val <= range[1];
    };
}

function isGeoCoordSys(coordSys) {
    var dimensions = coordSys.dimensions;
    // Not use coorSys.type === 'geo' because coordSys maybe extended
    return dimensions[0] === 'lng' && dimensions[1] === 'lat';
}

extendChartView({

    type: 'heatmap',

    render: function (seriesModel, ecModel, api) {
        var visualMapOfThisSeries;
        ecModel.eachComponent('visualMap', function (visualMap) {
            visualMap.eachTargetSeries(function (targetSeries) {
                if (targetSeries === seriesModel) {
                    visualMapOfThisSeries = visualMap;
                }
            });
        });

        if (__DEV__) {
            if (!visualMapOfThisSeries) {
                throw new Error('Heatmap must use with visualMap');
            }
        }

        this.group.removeAll();

        this._incrementalDisplayable = null;

        var coordSys = seriesModel.coordinateSystem;
        if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') {
            this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count());
        }
        else if (isGeoCoordSys(coordSys)) {
            this._renderOnGeo(
                coordSys, seriesModel, visualMapOfThisSeries, api
            );
        }
    },

    incrementalPrepareRender: function (seriesModel, ecModel, api) {
        this.group.removeAll();
    },

    incrementalRender: function (params, seriesModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;
        if (coordSys) {
            this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true);
        }
    },

    _renderOnCartesianAndCalendar: function (seriesModel, api, start, end, incremental) {

        var coordSys = seriesModel.coordinateSystem;
        var width;
        var height;

        if (coordSys.type === 'cartesian2d') {
            var xAxis = coordSys.getAxis('x');
            var yAxis = coordSys.getAxis('y');

            if (__DEV__) {
                if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
                    throw new Error('Heatmap on cartesian must have two category axes');
                }
                if (!(xAxis.onBand && yAxis.onBand)) {
                    throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
                }
            }

            width = xAxis.getBandWidth();
            height = yAxis.getBandWidth();
        }

        var group = this.group;
        var data = seriesModel.getData();

        var itemStyleQuery = 'itemStyle';
        var hoverItemStyleQuery = 'emphasis.itemStyle';
        var labelQuery = 'label';
        var hoverLabelQuery = 'emphasis.label';
        var style = seriesModel.getModel(itemStyleQuery).getItemStyle(['color']);
        var hoverStl = seriesModel.getModel(hoverItemStyleQuery).getItemStyle();
        var labelModel = seriesModel.getModel(labelQuery);
        var hoverLabelModel = seriesModel.getModel(hoverLabelQuery);
        var coordSysType = coordSys.type;


        var dataDims = coordSysType === 'cartesian2d'
            ? [
                data.mapDimension('x'),
                data.mapDimension('y'),
                data.mapDimension('value')
            ]
            : [
                data.mapDimension('time'),
                data.mapDimension('value')
            ];

        for (var idx = start; idx < end; idx++) {
            var rect;

            if (coordSysType === 'cartesian2d') {
                // Ignore empty data
                if (isNaN(data.get(dataDims[2], idx))) {
                    continue;
                }

                var point = coordSys.dataToPoint([
                    data.get(dataDims[0], idx),
                    data.get(dataDims[1], idx)
                ]);

                rect = new Rect({
                    shape: {
                        x: point[0] - width / 2,
                        y: point[1] - height / 2,
                        width: width,
                        height: height
                    },
                    style: {
                        fill: data.getItemVisual(idx, 'color'),
                        opacity: data.getItemVisual(idx, 'opacity')
                    }
                });
            }
            else {
                // Ignore empty data
                if (isNaN(data.get(dataDims[1], idx))) {
                    continue;
                }

                rect = new Rect({
                    z2: 1,
                    shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape,
                    style: {
                        fill: data.getItemVisual(idx, 'color'),
                        opacity: data.getItemVisual(idx, 'opacity')
                    }
                });
            }

            var itemModel = data.getItemModel(idx);

            // Optimization for large datset
            if (data.hasItemOption) {
                style = itemModel.getModel(itemStyleQuery).getItemStyle(['color']);
                hoverStl = itemModel.getModel(hoverItemStyleQuery).getItemStyle();
                labelModel = itemModel.getModel(labelQuery);
                hoverLabelModel = itemModel.getModel(hoverLabelQuery);
            }

            var rawValue = seriesModel.getRawValue(idx);
            var defaultText = '-';
            if (rawValue && rawValue[2] != null) {
                defaultText = rawValue[2];
            }

            setLabelStyle(
                style, hoverStl, labelModel, hoverLabelModel,
                {
                    labelFetcher: seriesModel,
                    labelDataIndex: idx,
                    defaultText: defaultText,
                    isRectText: true
                }
            );

            rect.setStyle(style);
            setHoverStyle(rect, data.hasItemOption ? hoverStl : extend({}, hoverStl));

            rect.incremental = incremental;
            // PENDING
            if (incremental) {
                // Rect must use hover layer if it's incremental.
                rect.useHoverLayer = true;
            }

            group.add(rect);
            data.setItemGraphicEl(idx, rect);
        }
    },

    _renderOnGeo: function (geo, seriesModel, visualMapModel, api) {
        var inRangeVisuals = visualMapModel.targetVisuals.inRange;
        var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange;
        // if (!visualMapping) {
        //     throw new Error('Data range must have color visuals');
        // }

        var data = seriesModel.getData();
        var hmLayer = this._hmLayer || (this._hmLayer || new Heatmap());
        hmLayer.blurSize = seriesModel.get('blurSize');
        hmLayer.pointSize = seriesModel.get('pointSize');
        hmLayer.minOpacity = seriesModel.get('minOpacity');
        hmLayer.maxOpacity = seriesModel.get('maxOpacity');

        var rect = geo.getViewRect().clone();
        var roamTransform = geo.getRoamTransform();
        rect.applyTransform(roamTransform);

        // Clamp on viewport
        var x = Math.max(rect.x, 0);
        var y = Math.max(rect.y, 0);
        var x2 = Math.min(rect.width + rect.x, api.getWidth());
        var y2 = Math.min(rect.height + rect.y, api.getHeight());
        var width = x2 - x;
        var height = y2 - y;

        var dims = [
            data.mapDimension('lng'),
            data.mapDimension('lat'),
            data.mapDimension('value')
        ];

        var points = data.mapArray(dims, function (lng, lat, value) {
            var pt = geo.dataToPoint([lng, lat]);
            pt[0] -= x;
            pt[1] -= y;
            pt.push(value);
            return pt;
        });

        var dataExtent = visualMapModel.getExtent();
        var isInRange = visualMapModel.type === 'visualMap.continuous'
            ? getIsInContinuousRange(dataExtent, visualMapModel.option.range)
            : getIsInPiecewiseRange(
                dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected
            );

        hmLayer.update(
            points, width, height,
            inRangeVisuals.color.getNormalizer(),
            {
                inRange: inRangeVisuals.color.getColorMapper(),
                outOfRange: outOfRangeVisuals.color.getColorMapper()
            },
            isInRange
        );
        var img = new ZImage({
            style: {
                width: width,
                height: height,
                x: x,
                y: y,
                image: hmLayer.canvas
            },
            silent: true
        });
        this.group.add(img);
    },

    dispose: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PictorialBarSeries = BaseBarSeries.extend({

    type: 'series.pictorialBar',

    dependencies: ['grid'],

    defaultOption: {
        symbol: 'circle',     // Customized bar shape
        symbolSize: null,     // Can be ['100%', '100%'], null means auto.
        symbolRotate: null,

        symbolPosition: null, // 'start' or 'end' or 'center', null means auto.
        symbolOffset: null,
        symbolMargin: null,   // start margin and end margin. Can be a number or a percent string.
                                // Auto margin by defualt.
        symbolRepeat: false,  // false/null/undefined, means no repeat.
                                // Can be true, means auto calculate repeat times and cut by data.
                                // Can be a number, specifies repeat times, and do not cut by data.
                                // Can be 'fixed', means auto calculate repeat times but do not cut by data.
        symbolRepeatDirection: 'end', // 'end' means from 'start' to 'end'.

        symbolClip: false,
        symbolBoundingData: null, // Can be 60 or -40 or [-40, 60]
        symbolPatternSize: 400, // 400 * 400 px

        barGap: '-100%',      // In most case, overlap is needed.

        // z can be set in data item, which is z2 actually.

        // Disable progressive
        progressive: 0,
        hoverAnimation: false // Open only when needed.
    },

    getInitialData: function (option) {
        // Disable stack.
        option.stack = null;
        return PictorialBarSeries.superApply(this, 'getInitialData', arguments);
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var BAR_BORDER_WIDTH_QUERY$1 = ['itemStyle', 'borderWidth'];

// index: +isHorizontal
var LAYOUT_ATTRS = [
    {xy: 'x', wh: 'width', index: 0, posDesc: ['left', 'right']},
    {xy: 'y', wh: 'height', index: 1, posDesc: ['top', 'bottom']}
];

var pathForLineWidth = new Circle();

var BarView$1 = extendChartView({

    type: 'pictorialBar',

    render: function (seriesModel, ecModel, api) {
        var group = this.group;
        var data = seriesModel.getData();
        var oldData = this._data;

        var cartesian = seriesModel.coordinateSystem;
        var baseAxis = cartesian.getBaseAxis();
        var isHorizontal = !!baseAxis.isHorizontal();
        var coordSysRect = cartesian.grid.getRect();

        var opt = {
            ecSize: {width: api.getWidth(), height: api.getHeight()},
            seriesModel: seriesModel,
            coordSys: cartesian,
            coordSysExtent: [
                [coordSysRect.x, coordSysRect.x + coordSysRect.width],
                [coordSysRect.y, coordSysRect.y + coordSysRect.height]
            ],
            isHorizontal: isHorizontal,
            valueDim: LAYOUT_ATTRS[+isHorizontal],
            categoryDim: LAYOUT_ATTRS[1 - isHorizontal]
        };

        data.diff(oldData)
            .add(function (dataIndex) {
                if (!data.hasValue(dataIndex)) {
                    return;
                }

                var itemModel = getItemModel(data, dataIndex);
                var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt);

                var bar = createBar(data, opt, symbolMeta);

                data.setItemGraphicEl(dataIndex, bar);
                group.add(bar);

                updateCommon$1(bar, opt, symbolMeta);
            })
            .update(function (newIndex, oldIndex) {
                var bar = oldData.getItemGraphicEl(oldIndex);

                if (!data.hasValue(newIndex)) {
                    group.remove(bar);
                    return;
                }

                var itemModel = getItemModel(data, newIndex);
                var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt);

                var pictorialShapeStr = getShapeStr(data, symbolMeta);
                if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) {
                    group.remove(bar);
                    data.setItemGraphicEl(newIndex, null);
                    bar = null;
                }

                if (bar) {
                    updateBar(bar, opt, symbolMeta);
                }
                else {
                    bar = createBar(data, opt, symbolMeta, true);
                }

                data.setItemGraphicEl(newIndex, bar);
                bar.__pictorialSymbolMeta = symbolMeta;
                // Add back
                group.add(bar);

                updateCommon$1(bar, opt, symbolMeta);
            })
            .remove(function (dataIndex) {
                var bar = oldData.getItemGraphicEl(dataIndex);
                bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar);
            })
            .execute();

        this._data = data;

        return this.group;
    },

    dispose: noop,

    remove: function (ecModel, api) {
        var group = this.group;
        var data = this._data;
        if (ecModel.get('animation')) {
            if (data) {
                data.eachItemGraphicEl(function (bar) {
                    removeBar(data, bar.dataIndex, ecModel, bar);
                });
            }
        }
        else {
            group.removeAll();
        }
    }
});


// Set or calculate default value about symbol, and calculate layout info.
function getSymbolMeta(data, dataIndex, itemModel, opt) {
    var layout = data.getItemLayout(dataIndex);
    var symbolRepeat = itemModel.get('symbolRepeat');
    var symbolClip = itemModel.get('symbolClip');
    var symbolPosition = itemModel.get('symbolPosition') || 'start';
    var symbolRotate = itemModel.get('symbolRotate');
    var rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
    var symbolPatternSize = itemModel.get('symbolPatternSize') || 2;
    var isAnimationEnabled = itemModel.isAnimationEnabled();

    var symbolMeta = {
        dataIndex: dataIndex,
        layout: layout,
        itemModel: itemModel,
        symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle',
        color: data.getItemVisual(dataIndex, 'color'),
        symbolClip: symbolClip,
        symbolRepeat: symbolRepeat,
        symbolRepeatDirection: itemModel.get('symbolRepeatDirection'),
        symbolPatternSize: symbolPatternSize,
        rotation: rotation,
        animationModel: isAnimationEnabled ? itemModel : null,
        hoverAnimation: isAnimationEnabled && itemModel.get('hoverAnimation'),
        z2: itemModel.getShallow('z', true) || 0
    };

    prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta);

    prepareSymbolSize(
        data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength,
        symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta
    );

    prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta);

    var symbolSize = symbolMeta.symbolSize;
    var symbolOffset = itemModel.get('symbolOffset');
    if (isArray(symbolOffset)) {
        symbolOffset = [
            parsePercent$1(symbolOffset[0], symbolSize[0]),
            parsePercent$1(symbolOffset[1], symbolSize[1])
        ];
    }

    prepareLayoutInfo(
        itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset,
        symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength,
        opt, symbolMeta
    );

    return symbolMeta;
}

// bar length can be negative.
function prepareBarLength(itemModel, symbolRepeat, layout, opt, output) {
    var valueDim = opt.valueDim;
    var symbolBoundingData = itemModel.get('symbolBoundingData');
    var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis());
    var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0));
    var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0);
    var boundingLength;

    if (isArray(symbolBoundingData)) {
        var symbolBoundingExtent = [
            convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx,
            convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx
        ];
        symbolBoundingExtent[1] < symbolBoundingExtent[0] && (symbolBoundingExtent.reverse());
        boundingLength = symbolBoundingExtent[pxSignIdx];
    }
    else if (symbolBoundingData != null) {
        boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx;
    }
    else if (symbolRepeat) {
        boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx;
    }
    else {
        boundingLength = layout[valueDim.wh];
    }

    output.boundingLength = boundingLength;

    if (symbolRepeat) {
        output.repeatCutLength = layout[valueDim.wh];
    }

    output.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0;
}

function convertToCoordOnAxis(axis, value) {
    return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value)));
}

// Support ['100%', '100%']
function prepareSymbolSize(
    data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength,
    pxSign, symbolPatternSize, opt, output
) {
    var valueDim = opt.valueDim;
    var categoryDim = opt.categoryDim;
    var categorySize = Math.abs(layout[categoryDim.wh]);

    var symbolSize = data.getItemVisual(dataIndex, 'symbolSize');
    if (isArray(symbolSize)) {
        symbolSize = symbolSize.slice();
    }
    else {
        if (symbolSize == null) {
            symbolSize = '100%';
        }
        symbolSize = [symbolSize, symbolSize];
    }

    // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is
    // to complicated to calculate real percent value if considering scaled lineWidth.
    // So the actual size will bigger than layout size if lineWidth is bigger than zero,
    // which can be tolerated in pictorial chart.

    symbolSize[categoryDim.index] = parsePercent$1(
        symbolSize[categoryDim.index],
        categorySize
    );
    symbolSize[valueDim.index] = parsePercent$1(
        symbolSize[valueDim.index],
        symbolRepeat ? categorySize : Math.abs(boundingLength)
    );

    output.symbolSize = symbolSize;

    // If x or y is less than zero, show reversed shape.
    var symbolScale = output.symbolScale = [
        symbolSize[0] / symbolPatternSize,
        symbolSize[1] / symbolPatternSize
    ];
    // Follow convention, 'right' and 'top' is the normal scale.
    symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign;
}

function prepareLineWidth(itemModel, symbolScale, rotation, opt, output) {
    // In symbols are drawn with scale, so do not need to care about the case that width
    // or height are too small. But symbol use strokeNoScale, where acture lineWidth should
    // be calculated.
    var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY$1) || 0;

    if (valueLineWidth) {
        pathForLineWidth.attr({
            scale: symbolScale.slice(),
            rotation: rotation
        });
        pathForLineWidth.updateTransform();
        valueLineWidth /= pathForLineWidth.getLineScale();
        valueLineWidth *= symbolScale[opt.valueDim.index];
    }

    output.valueLineWidth = valueLineWidth;
}

function prepareLayoutInfo(
    itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset,
    symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, output
) {
    var categoryDim = opt.categoryDim;
    var valueDim = opt.valueDim;
    var pxSign = output.pxSign;

    var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0);
    var pathLen = unitLength;

    // Note: rotation will not effect the layout of symbols, because user may
    // want symbols to rotate on its center, which should not be translated
    // when rotating.

    if (symbolRepeat) {
        var absBoundingLength = Math.abs(boundingLength);

        var symbolMargin = retrieve(itemModel.get('symbolMargin'), '15%') + '';
        var hasEndGap = false;
        if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) {
            hasEndGap = true;
            symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1);
        }
        symbolMargin = parsePercent$1(symbolMargin, symbolSize[valueDim.index]);

        var uLenWithMargin = Math.max(unitLength + symbolMargin * 2, 0);

        // When symbol margin is less than 0, margin at both ends will be subtracted
        // to ensure that all of the symbols will not be overflow the given area.
        var endFix = hasEndGap ? 0 : symbolMargin * 2;

        // Both final repeatTimes and final symbolMargin area calculated based on
        // boundingLength.
        var repeatSpecified = isNumeric(symbolRepeat);
        var repeatTimes = repeatSpecified
            ? symbolRepeat
            : toIntTimes((absBoundingLength + endFix) / uLenWithMargin);

        // Adjust calculate margin, to ensure each symbol is displayed
        // entirely in the given layout area.
        var mDiff = absBoundingLength - repeatTimes * unitLength;
        symbolMargin = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1);
        uLenWithMargin = unitLength + symbolMargin * 2;
        endFix = hasEndGap ? 0 : symbolMargin * 2;

        // Update repeatTimes when not all symbol will be shown.
        if (!repeatSpecified && symbolRepeat !== 'fixed') {
            repeatTimes = repeatCutLength
                ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin)
                : 0;
        }

        pathLen = repeatTimes * uLenWithMargin - endFix;
        output.repeatTimes = repeatTimes;
        output.symbolMargin = symbolMargin;
    }

    var sizeFix = pxSign * (pathLen / 2);
    var pathPosition = output.pathPosition = [];
    pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2;
    pathPosition[valueDim.index] = symbolPosition === 'start'
        ? sizeFix
        : symbolPosition === 'end'
        ? boundingLength - sizeFix
        : boundingLength / 2; // 'center'
    if (symbolOffset) {
        pathPosition[0] += symbolOffset[0];
        pathPosition[1] += symbolOffset[1];
    }

    var bundlePosition = output.bundlePosition = [];
    bundlePosition[categoryDim.index] = layout[categoryDim.xy];
    bundlePosition[valueDim.index] = layout[valueDim.xy];

    var barRectShape = output.barRectShape = extend({}, layout);
    barRectShape[valueDim.wh] = pxSign * Math.max(
        Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)
    );
    barRectShape[categoryDim.wh] = layout[categoryDim.wh];

    var clipShape = output.clipShape = {};
    // Consider that symbol may be overflow layout rect.
    clipShape[categoryDim.xy] = -layout[categoryDim.xy];
    clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh];
    clipShape[valueDim.xy] = 0;
    clipShape[valueDim.wh] = layout[valueDim.wh];
}

function createPath(symbolMeta) {
    var symbolPatternSize = symbolMeta.symbolPatternSize;
    var path = createSymbol(
        // Consider texture img, make a big size.
        symbolMeta.symbolType,
        -symbolPatternSize / 2,
        -symbolPatternSize / 2,
        symbolPatternSize,
        symbolPatternSize,
        symbolMeta.color
    );
    path.attr({
        culling: true
    });
    path.type !== 'image' && path.setStyle({
        strokeNoScale: true
    });

    return path;
}

function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) {
    var bundle = bar.__pictorialBundle;
    var symbolSize = symbolMeta.symbolSize;
    var valueLineWidth = symbolMeta.valueLineWidth;
    var pathPosition = symbolMeta.pathPosition;
    var valueDim = opt.valueDim;
    var repeatTimes = symbolMeta.repeatTimes || 0;

    var index = 0;
    var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2;

    eachPath(bar, function (path) {
        path.__pictorialAnimationIndex = index;
        path.__pictorialRepeatTimes = repeatTimes;
        if (index < repeatTimes) {
            updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate);
        }
        else {
            updateAttr(path, null, {scale: [0, 0]}, symbolMeta, isUpdate, function () {
                bundle.remove(path);
            });
        }

        updateHoverAnimation(path, symbolMeta);

        index++;
    });

    for (; index < repeatTimes; index++) {
        var path = createPath(symbolMeta);
        path.__pictorialAnimationIndex = index;
        path.__pictorialRepeatTimes = repeatTimes;
        bundle.add(path);

        var target = makeTarget(index);

        updateAttr(
            path,
            {
                position: target.position,
                scale: [0, 0]
            },
            {
                scale: target.scale,
                rotation: target.rotation
            },
            symbolMeta,
            isUpdate
        );

        // FIXME
        // If all emphasis/normal through action.
        path
            .on('mouseover', onMouseOver)
            .on('mouseout', onMouseOut);

        updateHoverAnimation(path, symbolMeta);
    }

    function makeTarget(index) {
        var position = pathPosition.slice();
        // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index
        // Otherwise: i = index;
        var pxSign = symbolMeta.pxSign;
        var i = index;
        if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) {
            i = repeatTimes - 1 - index;
        }
        position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index];

        return {
            position: position,
            scale: symbolMeta.symbolScale.slice(),
            rotation: symbolMeta.rotation
        };
    }

    function onMouseOver() {
        eachPath(bar, function (path) {
            path.trigger('emphasis');
        });
    }

    function onMouseOut() {
        eachPath(bar, function (path) {
            path.trigger('normal');
        });
    }
}

function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) {
    var bundle = bar.__pictorialBundle;
    var mainPath = bar.__pictorialMainPath;

    if (!mainPath) {
        mainPath = bar.__pictorialMainPath = createPath(symbolMeta);
        bundle.add(mainPath);

        updateAttr(
            mainPath,
            {
                position: symbolMeta.pathPosition.slice(),
                scale: [0, 0],
                rotation: symbolMeta.rotation
            },
            {
                scale: symbolMeta.symbolScale.slice()
            },
            symbolMeta,
            isUpdate
        );

        mainPath
            .on('mouseover', onMouseOver)
            .on('mouseout', onMouseOut);
    }
    else {
        updateAttr(
            mainPath,
            null,
            {
                position: symbolMeta.pathPosition.slice(),
                scale: symbolMeta.symbolScale.slice(),
                rotation: symbolMeta.rotation
            },
            symbolMeta,
            isUpdate
        );
    }

    updateHoverAnimation(mainPath, symbolMeta);

    function onMouseOver() {
        this.trigger('emphasis');
    }

    function onMouseOut() {
        this.trigger('normal');
    }
}

// bar rect is used for label.
function createOrUpdateBarRect(bar, symbolMeta, isUpdate) {
    var rectShape = extend({}, symbolMeta.barRectShape);

    var barRect = bar.__pictorialBarRect;
    if (!barRect) {
        barRect = bar.__pictorialBarRect = new Rect({
            z2: 2,
            shape: rectShape,
            silent: true,
            style: {
                stroke: 'transparent',
                fill: 'transparent',
                lineWidth: 0
            }
        });

        bar.add(barRect);
    }
    else {
        updateAttr(barRect, null, {shape: rectShape}, symbolMeta, isUpdate);
    }
}

function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) {
    // If not clip, symbol will be remove and rebuilt.
    if (symbolMeta.symbolClip) {
        var clipPath = bar.__pictorialClipPath;
        var clipShape = extend({}, symbolMeta.clipShape);
        var valueDim = opt.valueDim;
        var animationModel = symbolMeta.animationModel;
        var dataIndex = symbolMeta.dataIndex;

        if (clipPath) {
            updateProps(
                clipPath, {shape: clipShape}, animationModel, dataIndex
            );
        }
        else {
            clipShape[valueDim.wh] = 0;
            clipPath = new Rect({shape: clipShape});
            bar.__pictorialBundle.setClipPath(clipPath);
            bar.__pictorialClipPath = clipPath;

            var target = {};
            target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh];

            graphic[isUpdate ? 'updateProps' : 'initProps'](
                clipPath, {shape: target}, animationModel, dataIndex
            );
        }
    }
}

function getItemModel(data, dataIndex) {
    var itemModel = data.getItemModel(dataIndex);
    itemModel.getAnimationDelayParams = getAnimationDelayParams;
    itemModel.isAnimationEnabled = isAnimationEnabled;
    return itemModel;
}

function getAnimationDelayParams(path) {
    // The order is the same as the z-order, see `symbolRepeatDiretion`.
    return {
        index: path.__pictorialAnimationIndex,
        count: path.__pictorialRepeatTimes
    };
}

function isAnimationEnabled() {
    // `animation` prop can be set on itemModel in pictorial bar chart.
    return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation');
}

function updateHoverAnimation(path, symbolMeta) {
    path.off('emphasis').off('normal');

    var scale = symbolMeta.symbolScale.slice();

    symbolMeta.hoverAnimation && path
        .on('emphasis', function () {
            this.animateTo({
                scale: [scale[0] * 1.1, scale[1] * 1.1]
            }, 400, 'elasticOut');
        })
        .on('normal', function () {
            this.animateTo({
                scale: scale.slice()
            }, 400, 'elasticOut');
        });
}

function createBar(data, opt, symbolMeta, isUpdate) {
    // bar is the main element for each data.
    var bar = new Group();
    // bundle is used for location and clip.
    var bundle = new Group();
    bar.add(bundle);
    bar.__pictorialBundle = bundle;
    bundle.attr('position', symbolMeta.bundlePosition.slice());

    if (symbolMeta.symbolRepeat) {
        createOrUpdateRepeatSymbols(bar, opt, symbolMeta);
    }
    else {
        createOrUpdateSingleSymbol(bar, opt, symbolMeta);
    }

    createOrUpdateBarRect(bar, symbolMeta, isUpdate);

    createOrUpdateClip(bar, opt, symbolMeta, isUpdate);

    bar.__pictorialShapeStr = getShapeStr(data, symbolMeta);
    bar.__pictorialSymbolMeta = symbolMeta;

    return bar;
}

function updateBar(bar, opt, symbolMeta) {
    var animationModel = symbolMeta.animationModel;
    var dataIndex = symbolMeta.dataIndex;
    var bundle = bar.__pictorialBundle;

    updateProps(
        bundle, {position: symbolMeta.bundlePosition.slice()}, animationModel, dataIndex
    );

    if (symbolMeta.symbolRepeat) {
        createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true);
    }
    else {
        createOrUpdateSingleSymbol(bar, opt, symbolMeta, true);
    }

    createOrUpdateBarRect(bar, symbolMeta, true);

    createOrUpdateClip(bar, opt, symbolMeta, true);
}

function removeBar(data, dataIndex, animationModel, bar) {
    // Not show text when animating
    var labelRect = bar.__pictorialBarRect;
    labelRect && (labelRect.style.text = null);

    var pathes = [];
    eachPath(bar, function (path) {
        pathes.push(path);
    });
    bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath);

    // I do not find proper remove animation for clip yet.
    bar.__pictorialClipPath && (animationModel = null);

    each$1(pathes, function (path) {
        updateProps(
            path, {scale: [0, 0]}, animationModel, dataIndex,
            function () {
                bar.parent && bar.parent.remove(bar);
            }
        );
    });

    data.setItemGraphicEl(dataIndex, null);
}

function getShapeStr(data, symbolMeta) {
    return [
        data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none',
        !!symbolMeta.symbolRepeat,
        !!symbolMeta.symbolClip
    ].join(':');
}

function eachPath(bar, cb, context) {
    // Do not use Group#eachChild, because it do not support remove.
    each$1(bar.__pictorialBundle.children(), function (el) {
        el !== bar.__pictorialBarRect && cb.call(context, el);
    });
}

function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) {
    immediateAttrs && el.attr(immediateAttrs);
    // when symbolCip used, only clip path has init animation, otherwise it would be weird effect.
    if (symbolMeta.symbolClip && !isUpdate) {
        animationAttrs && el.attr(animationAttrs);
    }
    else {
        animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](
            el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb
        );
    }
}

function updateCommon$1(bar, opt, symbolMeta) {
    var color = symbolMeta.color;
    var dataIndex = symbolMeta.dataIndex;
    var itemModel = symbolMeta.itemModel;
    // Color must be excluded.
    // Because symbol provide setColor individually to set fill and stroke
    var normalStyle = itemModel.getModel('itemStyle').getItemStyle(['color']);
    var hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();
    var cursorStyle = itemModel.getShallow('cursor');

    eachPath(bar, function (path) {
        // PENDING setColor should be before setStyle!!!
        path.setColor(color);
        path.setStyle(defaults(
            {
                fill: color,
                opacity: symbolMeta.opacity
            },
            normalStyle
        ));
        setHoverStyle(path, hoverStyle);

        cursorStyle && (path.cursor = cursorStyle);
        path.z2 = symbolMeta.z2;
    });

    var barRectHoverStyle = {};
    var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)];
    var barRect = bar.__pictorialBarRect;

    setLabel(
        barRect.style, barRectHoverStyle, itemModel,
        color, opt.seriesModel, dataIndex, barPositionOutside
    );

    setHoverStyle(barRect, barRectHoverStyle);
}

function toIntTimes(times) {
    var roundedTimes = Math.round(times);
    // Escapse accurate error
    return Math.abs(times - roundedTimes) < 1e-4
        ? roundedTimes
        : Math.ceil(times);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// In case developer forget to include grid component
registerLayout(curry(
    layout, 'pictorialBar'
));
registerVisual(visualSymbol('pictorialBar', 'roundRect'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @constructor  module:echarts/coord/single/SingleAxis
 * @extends {module:echarts/coord/Axis}
 * @param {string} dim
 * @param {*} scale
 * @param {Array.<number>} coordExtent
 * @param {string} axisType
 * @param {string} position
 */
var SingleAxis = function (dim, scale, coordExtent, axisType, position) {

    Axis.call(this, dim, scale, coordExtent);

    /**
     * Axis type
     * - 'category'
     * - 'value'
     * - 'time'
     * - 'log'
     * @type {string}
     */
    this.type = axisType || 'value';

    /**
     * Axis position
     *  - 'top'
     *  - 'bottom'
     *  - 'left'
     *  - 'right'
     *  @type {string}
     */
    this.position = position || 'bottom';

    /**
     * Axis orient
     *  - 'horizontal'
     *  - 'vertical'
     * @type {[type]}
     */
    this.orient = null;

};

SingleAxis.prototype = {

    constructor: SingleAxis,

    /**
     * Axis model
     * @type {module:echarts/coord/single/AxisModel}
     */
    model: null,

    /**
     * Judge the orient of the axis.
     * @return {boolean}
     */
    isHorizontal: function () {
        var position = this.position;
        return position === 'top' || position === 'bottom';

    },

    /**
     * @override
     */
    pointToData: function (point, clamp) {
        return this.coordinateSystem.pointToData(point, clamp)[0];
    },

    /**
     * Convert the local coord(processed by dataToCoord())
     * to global coord(concrete pixel coord).
     * designated by module:echarts/coord/single/Single.
     * @type {Function}
     */
    toGlobalCoord: null,

    /**
     * Convert the global coord to local coord.
     * designated by module:echarts/coord/single/Single.
     * @type {Function}
     */
    toLocalCoord: null

};

inherits(SingleAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Single coordinates system.
 */

/**
 * Create a single coordinates system.
 *
 * @param {module:echarts/coord/single/AxisModel} axisModel
 * @param {module:echarts/model/Global} ecModel
 * @param {module:echarts/ExtensionAPI} api
 */
function Single(axisModel, ecModel, api) {

    /**
     * @type {string}
     * @readOnly
     */
    this.dimension = 'single';

    /**
     * Add it just for draw tooltip.
     *
     * @type {Array.<string>}
     * @readOnly
     */
    this.dimensions = ['single'];

    /**
     * @private
     * @type {module:echarts/coord/single/SingleAxis}.
     */
    this._axis = null;

    /**
     * @private
     * @type {module:zrender/core/BoundingRect}
     */
    this._rect;

    this._init(axisModel, ecModel, api);

    /**
     * @type {module:echarts/coord/single/AxisModel}
     */
    this.model = axisModel;
}

Single.prototype = {

    type: 'singleAxis',

    axisPointerEnabled: true,

    constructor: Single,

    /**
     * Initialize single coordinate system.
     *
     * @param  {module:echarts/coord/single/AxisModel} axisModel
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     * @private
     */
    _init: function (axisModel, ecModel, api) {

        var dim = this.dimension;

        var axis = new SingleAxis(
            dim,
            createScaleByModel(axisModel),
            [0, 0],
            axisModel.get('type'),
            axisModel.get('position')
        );

        var isCategory = axis.type === 'category';
        axis.onBand = isCategory && axisModel.get('boundaryGap');
        axis.inverse = axisModel.get('inverse');
        axis.orient = axisModel.get('orient');

        axisModel.axis = axis;
        axis.model = axisModel;
        axis.coordinateSystem = this;
        this._axis = axis;
    },

    /**
     * Update axis scale after data processed
     * @param  {module:echarts/model/Global} ecModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    update: function (ecModel, api) {
        ecModel.eachSeries(function (seriesModel) {
            if (seriesModel.coordinateSystem === this) {
                var data = seriesModel.getData();
                each$1(data.mapDimension(this.dimension, true), function (dim) {
                    this._axis.scale.unionExtentFromData(data, dim);
                }, this);
                niceScaleExtent(this._axis.scale, this._axis.model);
            }
        }, this);
    },

    /**
     * Resize the single coordinate system.
     *
     * @param  {module:echarts/coord/single/AxisModel} axisModel
     * @param  {module:echarts/ExtensionAPI} api
     */
    resize: function (axisModel, api) {
        this._rect = getLayoutRect(
            {
                left: axisModel.get('left'),
                top: axisModel.get('top'),
                right: axisModel.get('right'),
                bottom: axisModel.get('bottom'),
                width: axisModel.get('width'),
                height: axisModel.get('height')
            },
            {
                width: api.getWidth(),
                height: api.getHeight()
            }
        );

        this._adjustAxis();
    },

    /**
     * @return {module:zrender/core/BoundingRect}
     */
    getRect: function () {
        return this._rect;
    },

    /**
     * @private
     */
    _adjustAxis: function () {

        var rect = this._rect;
        var axis = this._axis;

        var isHorizontal = axis.isHorizontal();
        var extent = isHorizontal ? [0, rect.width] : [0, rect.height];
        var idx = axis.reverse ? 1 : 0;

        axis.setExtent(extent[idx], extent[1 - idx]);

        this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y);

    },

    /**
     * @param  {module:echarts/coord/single/SingleAxis} axis
     * @param  {number} coordBase
     */
    _updateAxisTransform: function (axis, coordBase) {

        var axisExtent = axis.getExtent();
        var extentSum = axisExtent[0] + axisExtent[1];
        var isHorizontal = axis.isHorizontal();

        axis.toGlobalCoord = isHorizontal
            ? function (coord) {
                return coord + coordBase;
            }
            : function (coord) {
                return extentSum - coord + coordBase;
            };

        axis.toLocalCoord = isHorizontal
            ? function (coord) {
                return coord - coordBase;
            }
            : function (coord) {
                return extentSum - coord + coordBase;
            };
    },

    /**
     * Get axis.
     *
     * @return {module:echarts/coord/single/SingleAxis}
     */
    getAxis: function () {
        return this._axis;
    },

    /**
     * Get axis, add it just for draw tooltip.
     *
     * @return {[type]} [description]
     */
    getBaseAxis: function () {
        return this._axis;
    },

    /**
     * @return {Array.<module:echarts/coord/Axis>}
     */
    getAxes: function () {
        return [this._axis];
    },

    /**
     * @return {Object} {baseAxes: [], otherAxes: []}
     */
    getTooltipAxes: function () {
        return {baseAxes: [this.getAxis()]};
    },

    /**
     * If contain point.
     *
     * @param  {Array.<number>} point
     * @return {boolean}
     */
    containPoint: function (point) {
        var rect = this.getRect();
        var axis = this.getAxis();
        var orient = axis.orient;
        if (orient === 'horizontal') {
            return axis.contain(axis.toLocalCoord(point[0]))
            && (point[1] >= rect.y && point[1] <= (rect.y + rect.height));
        }
        else {
            return axis.contain(axis.toLocalCoord(point[1]))
            && (point[0] >= rect.y && point[0] <= (rect.y + rect.height));
        }
    },

    /**
     * @param {Array.<number>} point
     * @return {Array.<number>}
     */
    pointToData: function (point) {
        var axis = this.getAxis();
        return [axis.coordToData(axis.toLocalCoord(
            point[axis.orient === 'horizontal' ? 0 : 1]
        ))];
    },

    /**
     * Convert the series data to concrete point.
     *
     * @param  {number|Array.<number>} val
     * @return {Array.<number>}
     */
    dataToPoint: function (val) {
        var axis = this.getAxis();
        var rect = this.getRect();
        var pt = [];
        var idx = axis.orient === 'horizontal' ? 0 : 1;

        if (val instanceof Array) {
            val = val[0];
        }

        pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val));
        pt[1 - idx] = idx === 0 ? (rect.y + rect.height / 2) : (rect.x + rect.width / 2);
        return pt;
    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Single coordinate system creator.
 */

/**
 * Create single coordinate system and inject it into seriesModel.
 *
 * @param {module:echarts/model/Global} ecModel
 * @param {module:echarts/ExtensionAPI} api
 * @return {Array.<module:echarts/coord/single/Single>}
 */
function create$3(ecModel, api) {
    var singles = [];

    ecModel.eachComponent('singleAxis', function (axisModel, idx) {

        var single = new Single(axisModel, ecModel, api);
        single.name = 'single_' + idx;
        single.resize(axisModel, api);
        axisModel.coordinateSystem = single;
        singles.push(single);

    });

    ecModel.eachSeries(function (seriesModel) {
        if (seriesModel.get('coordinateSystem') === 'singleAxis') {
            var singleAxisModel = ecModel.queryComponents({
                mainType: 'singleAxis',
                index: seriesModel.get('singleAxisIndex'),
                id: seriesModel.get('singleAxisId')
            })[0];
            seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem;
        }
    });

    return singles;
}

CoordinateSystemManager.register('single', {
    create: create$3,
    dimensions: Single.prototype.dimensions
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {Object} opt {labelInside}
 * @return {Object} {
 *  position, rotation, labelDirection, labelOffset,
 *  tickDirection, labelRotate, z2
 * }
 */
function layout$2(axisModel, opt) {
    opt = opt || {};
    var single = axisModel.coordinateSystem;
    var axis = axisModel.axis;
    var layout = {};

    var axisPosition = axis.position;
    var orient = axis.orient;

    var rect = single.getRect();
    var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];

    var positionMap = {
        horizontal: {top: rectBound[2], bottom: rectBound[3]},
        vertical: {left: rectBound[0], right: rectBound[1]}
    };

    layout.position = [
        orient === 'vertical'
            ? positionMap.vertical[axisPosition]
            : rectBound[0],
        orient === 'horizontal'
            ? positionMap.horizontal[axisPosition]
            : rectBound[3]
    ];

    var r = {horizontal: 0, vertical: 1};
    layout.rotation = Math.PI / 2 * r[orient];

    var directionMap = {top: -1, bottom: 1, right: 1, left: -1};

    layout.labelDirection = layout.tickDirection =
        layout.nameDirection = directionMap[axisPosition];

    if (axisModel.get('axisTick.inside')) {
        layout.tickDirection = -layout.tickDirection;
    }

    if (retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) {
        layout.labelDirection = -layout.labelDirection;
    }

    var labelRotation = opt.rotate;
    labelRotation == null && (labelRotation = axisModel.get('axisLabel.rotate'));
    layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation;

    layout.z2 = 1;

    return layout;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var axisBuilderAttrs$2 = [
    'axisLine', 'axisTickLabel', 'axisName'
];

var selfBuilderAttr = 'splitLine';

var SingleAxisView = AxisView.extend({

    type: 'singleAxis',

    axisPointerClass: 'SingleAxisPointer',

    render: function (axisModel, ecModel, api, payload) {

        var group = this.group;

        group.removeAll();

        var layout = layout$2(axisModel);

        var axisBuilder = new AxisBuilder(axisModel, layout);

        each$1(axisBuilderAttrs$2, axisBuilder.add, axisBuilder);

        group.add(axisBuilder.getGroup());

        if (axisModel.get(selfBuilderAttr + '.show')) {
            this['_' + selfBuilderAttr](axisModel);
        }

        SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
    },

    _splitLine: function (axisModel) {
        var axis = axisModel.axis;

        if (axis.scale.isBlank()) {
            return;
        }

        var splitLineModel = axisModel.getModel('splitLine');
        var lineStyleModel = splitLineModel.getModel('lineStyle');
        var lineWidth = lineStyleModel.get('width');
        var lineColors = lineStyleModel.get('color');

        lineColors = lineColors instanceof Array ? lineColors : [lineColors];

        var gridRect = axisModel.coordinateSystem.getRect();
        var isHorizontal = axis.isHorizontal();

        var splitLines = [];
        var lineCount = 0;

        var ticksCoords = axis.getTicksCoords({
            tickModel: splitLineModel
        });

        var p1 = [];
        var p2 = [];

        for (var i = 0; i < ticksCoords.length; ++i) {
            var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
            if (isHorizontal) {
                p1[0] = tickCoord;
                p1[1] = gridRect.y;
                p2[0] = tickCoord;
                p2[1] = gridRect.y + gridRect.height;
            }
            else {
                p1[0] = gridRect.x;
                p1[1] = tickCoord;
                p2[0] = gridRect.x + gridRect.width;
                p2[1] = tickCoord;
            }
            var colorIndex = (lineCount++) % lineColors.length;
            splitLines[colorIndex] = splitLines[colorIndex] || [];
            splitLines[colorIndex].push(new Line({
                subPixelOptimize: true,
                shape: {
                    x1: p1[0],
                    y1: p1[1],
                    x2: p2[0],
                    y2: p2[1]
                },
                style: {
                    lineWidth: lineWidth
                },
                silent: true
            }));
        }

        for (var i = 0; i < splitLines.length; ++i) {
            this.group.add(mergePath(splitLines[i], {
                style: {
                    stroke: lineColors[i % lineColors.length],
                    lineDash: lineStyleModel.getLineDash(lineWidth),
                    lineWidth: lineWidth
                },
                silent: true
            }));
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AxisModel$4 = ComponentModel.extend({

    type: 'singleAxis',

    layoutMode: 'box',

    /**
     * @type {module:echarts/coord/single/SingleAxis}
     */
    axis: null,

    /**
     * @type {module:echarts/coord/single/Single}
     */
    coordinateSystem: null,

    /**
     * @override
     */
    getCoordSysModel: function () {
        return this;
    }

});

var defaultOption$2 = {

    left: '5%',
    top: '5%',
    right: '5%',
    bottom: '5%',

    type: 'value',

    position: 'bottom',

    orient: 'horizontal',

    axisLine: {
        show: true,
        lineStyle: {
            width: 1,
            type: 'solid'
        }
    },

    // Single coordinate system and single axis is the,
    // which is used as the parent tooltip model.
    // same model, so we set default tooltip show as true.
    tooltip: {
        show: true
    },

    axisTick: {
        show: true,
        length: 6,
        lineStyle: {
            width: 1
        }
    },

    axisLabel: {
        show: true,
        interval: 'auto'
    },

    splitLine: {
        show: true,
        lineStyle: {
            type: 'dashed',
            opacity: 0.2
        }
    }
};

function getAxisType$2(axisName, option) {
    return option.type || (option.data ? 'category' : 'value');
}

merge(AxisModel$4.prototype, axisModelCommonMixin);

axisModelCreator('single', AxisModel$4, getAxisType$2, defaultOption$2);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {Object} finder contains {seriesIndex, dataIndex, dataIndexInside}
 * @param {module:echarts/model/Global} ecModel
 * @return {Object} {point: [x, y], el: ...} point Will not be null.
 */
var findPointFromSeries = function (finder, ecModel) {
    var point = [];
    var seriesIndex = finder.seriesIndex;
    var seriesModel;
    if (seriesIndex == null || !(
        seriesModel = ecModel.getSeriesByIndex(seriesIndex)
    )) {
        return {point: []};
    }

    var data = seriesModel.getData();
    var dataIndex = queryDataIndex(data, finder);
    if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) {
        return {point: []};
    }

    var el = data.getItemGraphicEl(dataIndex);
    var coordSys = seriesModel.coordinateSystem;

    if (seriesModel.getTooltipPosition) {
        point = seriesModel.getTooltipPosition(dataIndex) || [];
    }
    else if (coordSys && coordSys.dataToPoint) {
        point = coordSys.dataToPoint(
            data.getValues(
                map(coordSys.dimensions, function (dim) {
                    return data.mapDimension(dim);
                }), dataIndex, true
            )
        ) || [];
    }
    else if (el) {
        // Use graphic bounding rect
        var rect = el.getBoundingRect().clone();
        rect.applyTransform(el.transform);
        point = [
            rect.x + rect.width / 2,
            rect.y + rect.height / 2
        ];
    }

    return {point: point, el: el};
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$14 = each$1;
var curry$3 = curry;
var inner$9 = makeInner();

/**
 * Basic logic: check all axis, if they do not demand show/highlight,
 * then hide/downplay them.
 *
 * @param {Object} coordSysAxesInfo
 * @param {Object} payload
 * @param {string} [payload.currTrigger] 'click' | 'mousemove' | 'leave'
 * @param {Array.<number>} [payload.x] x and y, which are mandatory, specify a point to
 *              trigger axisPointer and tooltip.
 * @param {Array.<number>} [payload.y] x and y, which are mandatory, specify a point to
 *              trigger axisPointer and tooltip.
 * @param {Object} [payload.seriesIndex] finder, optional, restrict target axes.
 * @param {Object} [payload.dataIndex] finder, restrict target axes.
 * @param {Object} [payload.axesInfo] finder, restrict target axes.
 *        [{
 *          axisDim: 'x'|'y'|'angle'|...,
 *          axisIndex: ...,
 *          value: ...
 *        }, ...]
 * @param {Function} [payload.dispatchAction]
 * @param {Object} [payload.tooltipOption]
 * @param {Object|Array.<number>|Function} [payload.position] Tooltip position,
 *        which can be specified in dispatchAction
 * @param {module:echarts/model/Global} ecModel
 * @param {module:echarts/ExtensionAPI} api
 * @return {Object} content of event obj for echarts.connect.
 */
var axisTrigger = function (payload, ecModel, api) {
    var currTrigger = payload.currTrigger;
    var point = [payload.x, payload.y];
    var finder = payload;
    var dispatchAction = payload.dispatchAction || bind(api.dispatchAction, api);
    var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

    // Pending
    // See #6121. But we are not able to reproduce it yet.
    if (!coordSysAxesInfo) {
        return;
    }

    if (illegalPoint(point)) {
        // Used in the default behavior of `connection`: use the sample seriesIndex
        // and dataIndex. And also used in the tooltipView trigger.
        point = findPointFromSeries({
            seriesIndex: finder.seriesIndex,
            // Do not use dataIndexInside from other ec instance.
            // FIXME: auto detect it?
            dataIndex: finder.dataIndex
        }, ecModel).point;
    }
    var isIllegalPoint = illegalPoint(point);

    // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}).
    // Notice: In this case, it is difficult to get the `point` (which is necessary to show
    // tooltip, so if point is not given, we just use the point found by sample seriesIndex
    // and dataIndex.
    var inputAxesInfo = finder.axesInfo;

    var axesInfo = coordSysAxesInfo.axesInfo;
    var shouldHide = currTrigger === 'leave' || illegalPoint(point);
    var outputFinder = {};

    var showValueMap = {};
    var dataByCoordSys = {list: [], map: {}};
    var updaters = {
        showPointer: curry$3(showPointer, showValueMap),
        showTooltip: curry$3(showTooltip, dataByCoordSys)
    };

    // Process for triggered axes.
    each$14(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) {
        // If a point given, it must be contained by the coordinate system.
        var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point);

        each$14(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) {
            var axis = axisInfo.axis;
            var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo);
            // If no inputAxesInfo, no axis is restricted.
            if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) {
                var val = inputAxisInfo && inputAxisInfo.value;
                if (val == null && !isIllegalPoint) {
                    val = axis.pointToData(point);
                }
                val != null && processOnAxis(axisInfo, val, updaters, false, outputFinder);
            }
        });
    });

    // Process for linked axes.
    var linkTriggers = {};
    each$14(axesInfo, function (tarAxisInfo, tarKey) {
        var linkGroup = tarAxisInfo.linkGroup;

        // If axis has been triggered in the previous stage, it should not be triggered by link.
        if (linkGroup && !showValueMap[tarKey]) {
            each$14(linkGroup.axesInfo, function (srcAxisInfo, srcKey) {
                var srcValItem = showValueMap[srcKey];
                // If srcValItem exist, source axis is triggered, so link to target axis.
                if (srcAxisInfo !== tarAxisInfo && srcValItem) {
                    var val = srcValItem.value;
                    linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(
                        val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo)
                    )));
                    linkTriggers[tarAxisInfo.key] = val;
                }
            });
        }
    });
    each$14(linkTriggers, function (val, tarKey) {
        processOnAxis(axesInfo[tarKey], val, updaters, true, outputFinder);
    });

    updateModelActually(showValueMap, axesInfo, outputFinder);
    dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction);
    dispatchHighDownActually(axesInfo, dispatchAction, api);

    return outputFinder;
};

function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
    var axis = axisInfo.axis;

    if (axis.scale.isBlank() || !axis.containData(newValue)) {
        return;
    }

    if (!axisInfo.involveSeries) {
        updaters.showPointer(axisInfo, newValue);
        return;
    }

    // Heavy calculation. So put it after axis.containData checking.
    var payloadInfo = buildPayloadsBySeries(newValue, axisInfo);
    var payloadBatch = payloadInfo.payloadBatch;
    var snapToValue = payloadInfo.snapToValue;

    // Fill content of event obj for echarts.connect.
    // By defualt use the first involved series data as a sample to connect.
    if (payloadBatch[0] && outputFinder.seriesIndex == null) {
        extend(outputFinder, payloadBatch[0]);
    }

    // If no linkSource input, this process is for collecting link
    // target, where snap should not be accepted.
    if (!dontSnap && axisInfo.snap) {
        if (axis.containData(snapToValue) && snapToValue != null) {
            newValue = snapToValue;
        }
    }

    updaters.showPointer(axisInfo, newValue, payloadBatch, outputFinder);
    // Tooltip should always be snapToValue, otherwise there will be
    // incorrect "axis value ~ series value" mapping displayed in tooltip.
    updaters.showTooltip(axisInfo, payloadInfo, snapToValue);
}

function buildPayloadsBySeries(value, axisInfo) {
    var axis = axisInfo.axis;
    var dim = axis.dim;
    var snapToValue = value;
    var payloadBatch = [];
    var minDist = Number.MAX_VALUE;
    var minDiff = -1;

    each$14(axisInfo.seriesModels, function (series, idx) {
        var dataDim = series.getData().mapDimension(dim, true);
        var seriesNestestValue;
        var dataIndices;

        if (series.getAxisTooltipData) {
            var result = series.getAxisTooltipData(dataDim, value, axis);
            dataIndices = result.dataIndices;
            seriesNestestValue = result.nestestValue;
        }
        else {
            dataIndices = series.getData().indicesOfNearest(
                dataDim[0],
                value,
                // Add a threshold to avoid find the wrong dataIndex
                // when data length is not same.
                // false,
                axis.type === 'category' ? 0.5 : null
            );
            if (!dataIndices.length) {
                return;
            }
            seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]);
        }

        if (seriesNestestValue == null || !isFinite(seriesNestestValue)) {
            return;
        }

        var diff = value - seriesNestestValue;
        var dist = Math.abs(diff);
        // Consider category case
        if (dist <= minDist) {
            if (dist < minDist || (diff >= 0 && minDiff < 0)) {
                minDist = dist;
                minDiff = diff;
                snapToValue = seriesNestestValue;
                payloadBatch.length = 0;
            }
            each$14(dataIndices, function (dataIndex) {
                payloadBatch.push({
                    seriesIndex: series.seriesIndex,
                    dataIndexInside: dataIndex,
                    dataIndex: series.getData().getRawIndex(dataIndex)
                });
            });
        }
    });

    return {
        payloadBatch: payloadBatch,
        snapToValue: snapToValue
    };
}

function showPointer(showValueMap, axisInfo, value, payloadBatch) {
    showValueMap[axisInfo.key] = {value: value, payloadBatch: payloadBatch};
}

function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) {
    var payloadBatch = payloadInfo.payloadBatch;
    var axis = axisInfo.axis;
    var axisModel = axis.model;
    var axisPointerModel = axisInfo.axisPointerModel;

    // If no data, do not create anything in dataByCoordSys,
    // whose length will be used to judge whether dispatch action.
    if (!axisInfo.triggerTooltip || !payloadBatch.length) {
        return;
    }

    var coordSysModel = axisInfo.coordSys.model;
    var coordSysKey = makeKey(coordSysModel);
    var coordSysItem = dataByCoordSys.map[coordSysKey];
    if (!coordSysItem) {
        coordSysItem = dataByCoordSys.map[coordSysKey] = {
            coordSysId: coordSysModel.id,
            coordSysIndex: coordSysModel.componentIndex,
            coordSysType: coordSysModel.type,
            coordSysMainType: coordSysModel.mainType,
            dataByAxis: []
        };
        dataByCoordSys.list.push(coordSysItem);
    }

    coordSysItem.dataByAxis.push({
        axisDim: axis.dim,
        axisIndex: axisModel.componentIndex,
        axisType: axisModel.type,
        axisId: axisModel.id,
        value: value,
        // Caustion: viewHelper.getValueLabel is actually on "view stage", which
        // depends that all models have been updated. So it should not be performed
        // here. Considering axisPointerModel used here is volatile, which is hard
        // to be retrieve in TooltipView, we prepare parameters here.
        valueLabelOpt: {
            precision: axisPointerModel.get('label.precision'),
            formatter: axisPointerModel.get('label.formatter')
        },
        seriesDataIndices: payloadBatch.slice()
    });
}

function updateModelActually(showValueMap, axesInfo, outputFinder) {
    var outputAxesInfo = outputFinder.axesInfo = [];
    // Basic logic: If no 'show' required, 'hide' this axisPointer.
    each$14(axesInfo, function (axisInfo, key) {
        var option = axisInfo.axisPointerModel.option;
        var valItem = showValueMap[key];

        if (valItem) {
            !axisInfo.useHandle && (option.status = 'show');
            option.value = valItem.value;
            // For label formatter param and highlight.
            option.seriesDataIndices = (valItem.payloadBatch || []).slice();
        }
        // When always show (e.g., handle used), remain
        // original value and status.
        else {
            // If hide, value still need to be set, consider
            // click legend to toggle axis blank.
            !axisInfo.useHandle && (option.status = 'hide');
        }

        // If status is 'hide', should be no info in payload.
        option.status === 'show' && outputAxesInfo.push({
            axisDim: axisInfo.axis.dim,
            axisIndex: axisInfo.axis.model.componentIndex,
            value: option.value
        });
    });
}

function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) {
    // Basic logic: If no showTip required, hideTip will be dispatched.
    if (illegalPoint(point) || !dataByCoordSys.list.length) {
        dispatchAction({type: 'hideTip'});
        return;
    }

    // In most case only one axis (or event one series is used). It is
    // convinient to fetch payload.seriesIndex and payload.dataIndex
    // dirtectly. So put the first seriesIndex and dataIndex of the first
    // axis on the payload.
    var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {};

    dispatchAction({
        type: 'showTip',
        escapeConnect: true,
        x: point[0],
        y: point[1],
        tooltipOption: payload.tooltipOption,
        position: payload.position,
        dataIndexInside: sampleItem.dataIndexInside,
        dataIndex: sampleItem.dataIndex,
        seriesIndex: sampleItem.seriesIndex,
        dataByCoordSys: dataByCoordSys.list
    });
}

function dispatchHighDownActually(axesInfo, dispatchAction, api) {
    // FIXME
    // highlight status modification shoule be a stage of main process?
    // (Consider confilct (e.g., legend and axisPointer) and setOption)

    var zr = api.getZr();
    var highDownKey = 'axisPointerLastHighlights';
    var lastHighlights = inner$9(zr)[highDownKey] || {};
    var newHighlights = inner$9(zr)[highDownKey] = {};

    // Update highlight/downplay status according to axisPointer model.
    // Build hash map and remove duplicate incidentally.
    each$14(axesInfo, function (axisInfo, key) {
        var option = axisInfo.axisPointerModel.option;
        option.status === 'show' && each$14(option.seriesDataIndices, function (batchItem) {
            var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex;
            newHighlights[key] = batchItem;
        });
    });

    // Diff.
    var toHighlight = [];
    var toDownplay = [];
    each$1(lastHighlights, function (batchItem, key) {
        !newHighlights[key] && toDownplay.push(batchItem);
    });
    each$1(newHighlights, function (batchItem, key) {
        !lastHighlights[key] && toHighlight.push(batchItem);
    });

    toDownplay.length && api.dispatchAction({
        type: 'downplay', escapeConnect: true, batch: toDownplay
    });
    toHighlight.length && api.dispatchAction({
        type: 'highlight', escapeConnect: true, batch: toHighlight
    });
}

function findInputAxisInfo(inputAxesInfo, axisInfo) {
    for (var i = 0; i < (inputAxesInfo || []).length; i++) {
        var inputAxisInfo = inputAxesInfo[i];
        if (axisInfo.axis.dim === inputAxisInfo.axisDim
            && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex
        ) {
            return inputAxisInfo;
        }
    }
}

function makeMapperParam(axisInfo) {
    var axisModel = axisInfo.axis.model;
    var item = {};
    var dim = item.axisDim = axisInfo.axis.dim;
    item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex;
    item.axisName = item[dim + 'AxisName'] = axisModel.name;
    item.axisId = item[dim + 'AxisId'] = axisModel.id;
    return item;
}

function illegalPoint(point) {
    return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AxisPointerModel = extendComponentModel({

    type: 'axisPointer',

    coordSysAxesInfo: null,

    defaultOption: {
        // 'auto' means that show when triggered by tooltip or handle.
        show: 'auto',
        // 'click' | 'mousemove' | 'none'
        triggerOn: null, // set default in AxisPonterView.js

        zlevel: 0,
        z: 50,

        type: 'line', // 'line' 'shadow' 'cross' 'none'.
        // axispointer triggered by tootip determine snap automatically,
        // see `modelHelper`.
        snap: false,
        triggerTooltip: true,

        value: null,
        status: null, // Init value depends on whether handle is used.

        // [group0, group1, ...]
        // Each group can be: {
        //      mapper: function () {},
        //      singleTooltip: 'multiple',  // 'multiple' or 'single'
        //      xAxisId: ...,
        //      yAxisName: ...,
        //      angleAxisIndex: ...
        // }
        // mapper: can be ignored.
        //      input: {axisInfo, value}
        //      output: {axisInfo, value}
        link: [],

        // Do not set 'auto' here, otherwise global animation: false
        // will not effect at this axispointer.
        animation: null,
        animationDurationUpdate: 200,

        lineStyle: {
            color: '#aaa',
            width: 1,
            type: 'solid'
        },

        shadowStyle: {
            color: 'rgba(150,150,150,0.3)'
        },

        label: {
            show: true,
            formatter: null, // string | Function
            precision: 'auto', // Or a number like 0, 1, 2 ...
            margin: 3,
            color: '#fff',
            padding: [5, 7, 5, 7],
            backgroundColor: 'auto', // default: axis line color
            borderColor: null,
            borderWidth: 0,
            shadowBlur: 3,
            shadowColor: '#aaa'
            // Considering applicability, common style should
            // better not have shadowOffset.
            // shadowOffsetX: 0,
            // shadowOffsetY: 2
        },

        handle: {
            show: false,
            /* eslint-disable */
            icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line
            /* eslint-enable */
            size: 45,
            // handle margin is from symbol center to axis, which is stable when circular move.
            margin: 50,
            // color: '#1b8bbd'
            // color: '#2f4554'
            color: '#333',
            shadowBlur: 3,
            shadowColor: '#aaa',
            shadowOffsetX: 0,
            shadowOffsetY: 2,

            // For mobile performance
            throttle: 40
        }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$10 = makeInner();
var each$15 = each$1;

/**
 * @param {string} key
 * @param {module:echarts/ExtensionAPI} api
 * @param {Function} handler
 *      param: {string} currTrigger
 *      param: {Array.<number>} point
 */
function register(key, api, handler) {
    if (env$1.node) {
        return;
    }

    var zr = api.getZr();
    inner$10(zr).records || (inner$10(zr).records = {});

    initGlobalListeners(zr, api);

    var record = inner$10(zr).records[key] || (inner$10(zr).records[key] = {});
    record.handler = handler;
}

function initGlobalListeners(zr, api) {
    if (inner$10(zr).initialized) {
        return;
    }

    inner$10(zr).initialized = true;

    useHandler('click', curry(doEnter, 'click'));
    useHandler('mousemove', curry(doEnter, 'mousemove'));
    // useHandler('mouseout', onLeave);
    useHandler('globalout', onLeave);

    function useHandler(eventType, cb) {
        zr.on(eventType, function (e) {
            var dis = makeDispatchAction(api);

            each$15(inner$10(zr).records, function (record) {
                record && cb(record, e, dis.dispatchAction);
            });

            dispatchTooltipFinally(dis.pendings, api);
        });
    }
}

function dispatchTooltipFinally(pendings, api) {
    var showLen = pendings.showTip.length;
    var hideLen = pendings.hideTip.length;

    var actuallyPayload;
    if (showLen) {
        actuallyPayload = pendings.showTip[showLen - 1];
    }
    else if (hideLen) {
        actuallyPayload = pendings.hideTip[hideLen - 1];
    }
    if (actuallyPayload) {
        actuallyPayload.dispatchAction = null;
        api.dispatchAction(actuallyPayload);
    }
}

function onLeave(record, e, dispatchAction) {
    record.handler('leave', null, dispatchAction);
}

function doEnter(currTrigger, record, e, dispatchAction) {
    record.handler(currTrigger, e, dispatchAction);
}

function makeDispatchAction(api) {
    var pendings = {
        showTip: [],
        hideTip: []
    };
    // FIXME
    // better approach?
    // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip,
    // which may be conflict, (axisPointer call showTip but tooltip call hideTip);
    // So we have to add "final stage" to merge those dispatched actions.
    var dispatchAction = function (payload) {
        var pendingList = pendings[payload.type];
        if (pendingList) {
            pendingList.push(payload);
        }
        else {
            payload.dispatchAction = dispatchAction;
            api.dispatchAction(payload);
        }
    };

    return {
        dispatchAction: dispatchAction,
        pendings: pendings
    };
}

/**
 * @param {string} key
 * @param {module:echarts/ExtensionAPI} api
 */
function unregister(key, api) {
    if (env$1.node) {
        return;
    }
    var zr = api.getZr();
    var record = (inner$10(zr).records || {})[key];
    if (record) {
        inner$10(zr).records[key] = null;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AxisPointerView = extendComponentView({

    type: 'axisPointer',

    render: function (globalAxisPointerModel, ecModel, api) {
        var globalTooltipModel = ecModel.getComponent('tooltip');
        var triggerOn = globalAxisPointerModel.get('triggerOn')
            || (globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click');

        // Register global listener in AxisPointerView to enable
        // AxisPointerView to be independent to Tooltip.
        register(
            'axisPointer',
            api,
            function (currTrigger, e, dispatchAction) {
                // If 'none', it is not controlled by mouse totally.
                if (triggerOn !== 'none'
                    && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)
                ) {
                    dispatchAction({
                        type: 'updateAxisPointer',
                        currTrigger: currTrigger,
                        x: e && e.offsetX,
                        y: e && e.offsetY
                    });
                }
            }
        );
    },

    /**
     * @override
     */
    remove: function (ecModel, api) {
        unregister(api.getZr(), 'axisPointer');
        AxisPointerView.superApply(this._model, 'remove', arguments);
    },

    /**
     * @override
     */
    dispose: function (ecModel, api) {
        unregister('axisPointer', api);
        AxisPointerView.superApply(this._model, 'dispose', arguments);
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$11 = makeInner();
var clone$4 = clone;
var bind$2 = bind;

/**
 * Base axis pointer class in 2D.
 * Implemenents {module:echarts/component/axis/IAxisPointer}.
 */
function BaseAxisPointer() {
}

BaseAxisPointer.prototype = {

    /**
     * @private
     */
    _group: null,

    /**
     * @private
     */
    _lastGraphicKey: null,

    /**
     * @private
     */
    _handle: null,

    /**
     * @private
     */
    _dragging: false,

    /**
     * @private
     */
    _lastValue: null,

    /**
     * @private
     */
    _lastStatus: null,

    /**
     * @private
     */
    _payloadInfo: null,

    /**
     * In px, arbitrary value. Do not set too small,
     * no animation is ok for most cases.
     * @protected
     */
    animationThreshold: 15,

    /**
     * @implement
     */
    render: function (axisModel, axisPointerModel, api, forceRender) {
        var value = axisPointerModel.get('value');
        var status = axisPointerModel.get('status');

        // Bind them to `this`, not in closure, otherwise they will not
        // be replaced when user calling setOption in not merge mode.
        this._axisModel = axisModel;
        this._axisPointerModel = axisPointerModel;
        this._api = api;

        // Optimize: `render` will be called repeatly during mouse move.
        // So it is power consuming if performing `render` each time,
        // especially on mobile device.
        if (!forceRender
            && this._lastValue === value
            && this._lastStatus === status
        ) {
            return;
        }
        this._lastValue = value;
        this._lastStatus = status;

        var group = this._group;
        var handle = this._handle;

        if (!status || status === 'hide') {
            // Do not clear here, for animation better.
            group && group.hide();
            handle && handle.hide();
            return;
        }
        group && group.show();
        handle && handle.show();

        // Otherwise status is 'show'
        var elOption = {};
        this.makeElOption(elOption, value, axisModel, axisPointerModel, api);

        // Enable change axis pointer type.
        var graphicKey = elOption.graphicKey;
        if (graphicKey !== this._lastGraphicKey) {
            this.clear(api);
        }
        this._lastGraphicKey = graphicKey;

        var moveAnimation = this._moveAnimation =
            this.determineAnimation(axisModel, axisPointerModel);

        if (!group) {
            group = this._group = new Group();
            this.createPointerEl(group, elOption, axisModel, axisPointerModel);
            this.createLabelEl(group, elOption, axisModel, axisPointerModel);
            api.getZr().add(group);
        }
        else {
            var doUpdateProps = curry(updateProps$1, axisPointerModel, moveAnimation);
            this.updatePointerEl(group, elOption, doUpdateProps, axisPointerModel);
            this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel);
        }

        updateMandatoryProps(group, axisPointerModel, true);

        this._renderHandle(value);
    },

    /**
     * @implement
     */
    remove: function (api) {
        this.clear(api);
    },

    /**
     * @implement
     */
    dispose: function (api) {
        this.clear(api);
    },

    /**
     * @protected
     */
    determineAnimation: function (axisModel, axisPointerModel) {
        var animation = axisPointerModel.get('animation');
        var axis = axisModel.axis;
        var isCategoryAxis = axis.type === 'category';
        var useSnap = axisPointerModel.get('snap');

        // Value axis without snap always do not snap.
        if (!useSnap && !isCategoryAxis) {
            return false;
        }

        if (animation === 'auto' || animation == null) {
            var animationThreshold = this.animationThreshold;
            if (isCategoryAxis && axis.getBandWidth() > animationThreshold) {
                return true;
            }

            // It is important to auto animation when snap used. Consider if there is
            // a dataZoom, animation will be disabled when too many points exist, while
            // it will be enabled for better visual effect when little points exist.
            if (useSnap) {
                var seriesDataCount = getAxisInfo(axisModel).seriesDataCount;
                var axisExtent = axis.getExtent();
                // Approximate band width
                return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold;
            }

            return false;
        }

        return animation === true;
    },

    /**
     * add {pointer, label, graphicKey} to elOption
     * @protected
     */
    makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
        // Shoule be implemenented by sub-class.
    },

    /**
     * @protected
     */
    createPointerEl: function (group, elOption, axisModel, axisPointerModel) {
        var pointerOption = elOption.pointer;
        if (pointerOption) {
            var pointerEl = inner$11(group).pointerEl = new graphic[pointerOption.type](
                clone$4(elOption.pointer)
            );
            group.add(pointerEl);
        }
    },

    /**
     * @protected
     */
    createLabelEl: function (group, elOption, axisModel, axisPointerModel) {
        if (elOption.label) {
            var labelEl = inner$11(group).labelEl = new Rect(
                clone$4(elOption.label)
            );

            group.add(labelEl);
            updateLabelShowHide(labelEl, axisPointerModel);
        }
    },

    /**
     * @protected
     */
    updatePointerEl: function (group, elOption, updateProps$$1) {
        var pointerEl = inner$11(group).pointerEl;
        if (pointerEl && elOption.pointer) {
            pointerEl.setStyle(elOption.pointer.style);
            updateProps$$1(pointerEl, {shape: elOption.pointer.shape});
        }
    },

    /**
     * @protected
     */
    updateLabelEl: function (group, elOption, updateProps$$1, axisPointerModel) {
        var labelEl = inner$11(group).labelEl;
        if (labelEl) {
            labelEl.setStyle(elOption.label.style);
            updateProps$$1(labelEl, {
                // Consider text length change in vertical axis, animation should
                // be used on shape, otherwise the effect will be weird.
                shape: elOption.label.shape,
                position: elOption.label.position
            });

            updateLabelShowHide(labelEl, axisPointerModel);
        }
    },

    /**
     * @private
     */
    _renderHandle: function (value) {
        if (this._dragging || !this.updateHandleTransform) {
            return;
        }

        var axisPointerModel = this._axisPointerModel;
        var zr = this._api.getZr();
        var handle = this._handle;
        var handleModel = axisPointerModel.getModel('handle');

        var status = axisPointerModel.get('status');
        if (!handleModel.get('show') || !status || status === 'hide') {
            handle && zr.remove(handle);
            this._handle = null;
            return;
        }

        var isInit;
        if (!this._handle) {
            isInit = true;
            handle = this._handle = createIcon(
                handleModel.get('icon'),
                {
                    cursor: 'move',
                    draggable: true,
                    onmousemove: function (e) {
                        // Fot mobile devicem, prevent screen slider on the button.
                        stop(e.event);
                    },
                    onmousedown: bind$2(this._onHandleDragMove, this, 0, 0),
                    drift: bind$2(this._onHandleDragMove, this),
                    ondragend: bind$2(this._onHandleDragEnd, this)
                }
            );
            zr.add(handle);
        }

        updateMandatoryProps(handle, axisPointerModel, false);

        // update style
        var includeStyles = [
            'color', 'borderColor', 'borderWidth', 'opacity',
            'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'
        ];
        handle.setStyle(handleModel.getItemStyle(null, includeStyles));

        // update position
        var handleSize = handleModel.get('size');
        if (!isArray(handleSize)) {
            handleSize = [handleSize, handleSize];
        }
        handle.attr('scale', [handleSize[0] / 2, handleSize[1] / 2]);

        createOrUpdate(
            this,
            '_doDispatchAxisPointer',
            handleModel.get('throttle') || 0,
            'fixRate'
        );

        this._moveHandleToValue(value, isInit);
    },

    /**
     * @private
     */
    _moveHandleToValue: function (value, isInit) {
        updateProps$1(
            this._axisPointerModel,
            !isInit && this._moveAnimation,
            this._handle,
            getHandleTransProps(this.getHandleTransform(
                value, this._axisModel, this._axisPointerModel
            ))
        );
    },

    /**
     * @private
     */
    _onHandleDragMove: function (dx, dy) {
        var handle = this._handle;
        if (!handle) {
            return;
        }

        this._dragging = true;

        // Persistent for throttle.
        var trans = this.updateHandleTransform(
            getHandleTransProps(handle),
            [dx, dy],
            this._axisModel,
            this._axisPointerModel
        );
        this._payloadInfo = trans;

        handle.stopAnimation();
        handle.attr(getHandleTransProps(trans));
        inner$11(handle).lastProp = null;

        this._doDispatchAxisPointer();
    },

    /**
     * Throttled method.
     * @private
     */
    _doDispatchAxisPointer: function () {
        var handle = this._handle;
        if (!handle) {
            return;
        }

        var payloadInfo = this._payloadInfo;
        var axisModel = this._axisModel;
        this._api.dispatchAction({
            type: 'updateAxisPointer',
            x: payloadInfo.cursorPoint[0],
            y: payloadInfo.cursorPoint[1],
            tooltipOption: payloadInfo.tooltipOption,
            axesInfo: [{
                axisDim: axisModel.axis.dim,
                axisIndex: axisModel.componentIndex
            }]
        });
    },

    /**
     * @private
     */
    _onHandleDragEnd: function (moveAnimation) {
        this._dragging = false;
        var handle = this._handle;
        if (!handle) {
            return;
        }

        var value = this._axisPointerModel.get('value');
        // Consider snap or categroy axis, handle may be not consistent with
        // axisPointer. So move handle to align the exact value position when
        // drag ended.
        this._moveHandleToValue(value);

        // For the effect: tooltip will be shown when finger holding on handle
        // button, and will be hidden after finger left handle button.
        this._api.dispatchAction({
            type: 'hideTip'
        });
    },

    /**
     * Should be implemenented by sub-class if support `handle`.
     * @protected
     * @param {number} value
     * @param {module:echarts/model/Model} axisModel
     * @param {module:echarts/model/Model} axisPointerModel
     * @return {Object} {position: [x, y], rotation: 0}
     */
    getHandleTransform: null,

    /**
     * * Should be implemenented by sub-class if support `handle`.
     * @protected
     * @param {Object} transform {position, rotation}
     * @param {Array.<number>} delta [dx, dy]
     * @param {module:echarts/model/Model} axisModel
     * @param {module:echarts/model/Model} axisPointerModel
     * @return {Object} {position: [x, y], rotation: 0, cursorPoint: [x, y]}
     */
    updateHandleTransform: null,

    /**
     * @private
     */
    clear: function (api) {
        this._lastValue = null;
        this._lastStatus = null;

        var zr = api.getZr();
        var group = this._group;
        var handle = this._handle;
        if (zr && group) {
            this._lastGraphicKey = null;
            group && zr.remove(group);
            handle && zr.remove(handle);
            this._group = null;
            this._handle = null;
            this._payloadInfo = null;
        }
    },

    /**
     * @protected
     */
    doClear: function () {
        // Implemented by sub-class if necessary.
    },

    /**
     * @protected
     * @param {Array.<number>} xy
     * @param {Array.<number>} wh
     * @param {number} [xDimIndex=0] or 1
     */
    buildLabel: function (xy, wh, xDimIndex) {
        xDimIndex = xDimIndex || 0;
        return {
            x: xy[xDimIndex],
            y: xy[1 - xDimIndex],
            width: wh[xDimIndex],
            height: wh[1 - xDimIndex]
        };
    }
};

BaseAxisPointer.prototype.constructor = BaseAxisPointer;


function updateProps$1(animationModel, moveAnimation, el, props) {
    // Animation optimize.
    if (!propsEqual(inner$11(el).lastProp, props)) {
        inner$11(el).lastProp = props;
        moveAnimation
            ? updateProps(el, props, animationModel)
            : (el.stopAnimation(), el.attr(props));
    }
}

function propsEqual(lastProps, newProps) {
    if (isObject$1(lastProps) && isObject$1(newProps)) {
        var equals = true;
        each$1(newProps, function (item, key) {
            equals = equals && propsEqual(lastProps[key], item);
        });
        return !!equals;
    }
    else {
        return lastProps === newProps;
    }
}

function updateLabelShowHide(labelEl, axisPointerModel) {
    labelEl[axisPointerModel.get('label.show') ? 'show' : 'hide']();
}

function getHandleTransProps(trans) {
    return {
        position: trans.position.slice(),
        rotation: trans.rotation || 0
    };
}

function updateMandatoryProps(group, axisPointerModel, silent) {
    var z = axisPointerModel.get('z');
    var zlevel = axisPointerModel.get('zlevel');

    group && group.traverse(function (el) {
        if (el.type !== 'group') {
            z != null && (el.z = z);
            zlevel != null && (el.zlevel = zlevel);
            el.silent = silent;
        }
    });
}

enableClassExtend(BaseAxisPointer);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/model/Model} axisPointerModel
 */
function buildElStyle(axisPointerModel) {
    var axisPointerType = axisPointerModel.get('type');
    var styleModel = axisPointerModel.getModel(axisPointerType + 'Style');
    var style;
    if (axisPointerType === 'line') {
        style = styleModel.getLineStyle();
        style.fill = null;
    }
    else if (axisPointerType === 'shadow') {
        style = styleModel.getAreaStyle();
        style.stroke = null;
    }
    return style;
}

/**
 * @param {Function} labelPos {align, verticalAlign, position}
 */
function buildLabelElOption(
    elOption, axisModel, axisPointerModel, api, labelPos
) {
    var value = axisPointerModel.get('value');
    var text = getValueLabel(
        value, axisModel.axis, axisModel.ecModel,
        axisPointerModel.get('seriesDataIndices'),
        {
            precision: axisPointerModel.get('label.precision'),
            formatter: axisPointerModel.get('label.formatter')
        }
    );
    var labelModel = axisPointerModel.getModel('label');
    var paddings = normalizeCssArray$1(labelModel.get('padding') || 0);

    var font = labelModel.getFont();
    var textRect = getBoundingRect(text, font);

    var position = labelPos.position;
    var width = textRect.width + paddings[1] + paddings[3];
    var height = textRect.height + paddings[0] + paddings[2];

    // Adjust by align.
    var align = labelPos.align;
    align === 'right' && (position[0] -= width);
    align === 'center' && (position[0] -= width / 2);
    var verticalAlign = labelPos.verticalAlign;
    verticalAlign === 'bottom' && (position[1] -= height);
    verticalAlign === 'middle' && (position[1] -= height / 2);

    // Not overflow ec container
    confineInContainer(position, width, height, api);

    var bgColor = labelModel.get('backgroundColor');
    if (!bgColor || bgColor === 'auto') {
        bgColor = axisModel.get('axisLine.lineStyle.color');
    }

    elOption.label = {
        shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')},
        position: position.slice(),
        // TODO: rich
        style: {
            text: text,
            textFont: font,
            textFill: labelModel.getTextColor(),
            textPosition: 'inside',
            textPadding: paddings,
            fill: bgColor,
            stroke: labelModel.get('borderColor') || 'transparent',
            lineWidth: labelModel.get('borderWidth') || 0,
            shadowBlur: labelModel.get('shadowBlur'),
            shadowColor: labelModel.get('shadowColor'),
            shadowOffsetX: labelModel.get('shadowOffsetX'),
            shadowOffsetY: labelModel.get('shadowOffsetY')
        },
        // Lable should be over axisPointer.
        z2: 10
    };
}

// Do not overflow ec container
function confineInContainer(position, width, height, api) {
    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();
    position[0] = Math.min(position[0] + width, viewWidth) - width;
    position[1] = Math.min(position[1] + height, viewHeight) - height;
    position[0] = Math.max(position[0], 0);
    position[1] = Math.max(position[1], 0);
}

/**
 * @param {number} value
 * @param {module:echarts/coord/Axis} axis
 * @param {module:echarts/model/Global} ecModel
 * @param {Object} opt
 * @param {Array.<Object>} seriesDataIndices
 * @param {number|string} opt.precision 'auto' or a number
 * @param {string|Function} opt.formatter label formatter
 */
function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) {
    value = axis.scale.parse(value);
    var text = axis.scale.getLabel(
        // If `precision` is set, width can be fixed (like '12.00500'), which
        // helps to debounce when when moving label.
        value, {precision: opt.precision}
    );
    var formatter = opt.formatter;

    if (formatter) {
        var params = {
            value: getAxisRawValue(axis, value),
            axisDimension: axis.dim,
            axisIndex: axis.index,
            seriesData: []
        };
        each$1(seriesDataIndices, function (idxItem) {
            var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
            var dataIndex = idxItem.dataIndexInside;
            var dataParams = series && series.getDataParams(dataIndex);
            dataParams && params.seriesData.push(dataParams);
        });

        if (isString(formatter)) {
            text = formatter.replace('{value}', text);
        }
        else if (isFunction$1(formatter)) {
            text = formatter(params);
        }
    }

    return text;
}

/**
 * @param {module:echarts/coord/Axis} axis
 * @param {number} value
 * @param {Object} layoutInfo {
 *  rotation, position, labelOffset, labelDirection, labelMargin
 * }
 */
function getTransformedPosition(axis, value, layoutInfo) {
    var transform = create$1();
    rotate(transform, transform, layoutInfo.rotation);
    translate(transform, transform, layoutInfo.position);

    return applyTransform$1([
        axis.dataToCoord(value),
        (layoutInfo.labelOffset || 0)
            + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)
    ], transform);
}

function buildCartesianSingleLabelElOption(
    value, elOption, layoutInfo, axisModel, axisPointerModel, api
) {
    var textLayout = AxisBuilder.innerTextLayout(
        layoutInfo.rotation, 0, layoutInfo.labelDirection
    );
    layoutInfo.labelMargin = axisPointerModel.get('label.margin');
    buildLabelElOption(elOption, axisModel, axisPointerModel, api, {
        position: getTransformedPosition(axisModel.axis, value, layoutInfo),
        align: textLayout.textAlign,
        verticalAlign: textLayout.textVerticalAlign
    });
}

/**
 * @param {Array.<number>} p1
 * @param {Array.<number>} p2
 * @param {number} [xDimIndex=0] or 1
 */
function makeLineShape(p1, p2, xDimIndex) {
    xDimIndex = xDimIndex || 0;
    return {
        x1: p1[xDimIndex],
        y1: p1[1 - xDimIndex],
        x2: p2[xDimIndex],
        y2: p2[1 - xDimIndex]
    };
}

/**
 * @param {Array.<number>} xy
 * @param {Array.<number>} wh
 * @param {number} [xDimIndex=0] or 1
 */
function makeRectShape(xy, wh, xDimIndex) {
    xDimIndex = xDimIndex || 0;
    return {
        x: xy[xDimIndex],
        y: xy[1 - xDimIndex],
        width: wh[xDimIndex],
        height: wh[1 - xDimIndex]
    };
}

function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) {
    return {
        cx: cx,
        cy: cy,
        r0: r0,
        r: r,
        startAngle: startAngle,
        endAngle: endAngle,
        clockwise: true
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var CartesianAxisPointer = BaseAxisPointer.extend({

    /**
     * @override
     */
    makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
        var axis = axisModel.axis;
        var grid = axis.grid;
        var axisPointerType = axisPointerModel.get('type');
        var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
        var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true));

        if (axisPointerType && axisPointerType !== 'none') {
            var elStyle = buildElStyle(axisPointerModel);
            var pointerOption = pointerShapeBuilder[axisPointerType](
                axis, pixelValue, otherExtent
            );
            pointerOption.style = elStyle;
            elOption.graphicKey = pointerOption.type;
            elOption.pointer = pointerOption;
        }

        var layoutInfo = layout$1(grid.model, axisModel);
        buildCartesianSingleLabelElOption(
            value, elOption, layoutInfo, axisModel, axisPointerModel, api
        );
    },

    /**
     * @override
     */
    getHandleTransform: function (value, axisModel, axisPointerModel) {
        var layoutInfo = layout$1(axisModel.axis.grid.model, axisModel, {
            labelInside: false
        });
        layoutInfo.labelMargin = axisPointerModel.get('handle.margin');
        return {
            position: getTransformedPosition(axisModel.axis, value, layoutInfo),
            rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
        };
    },

    /**
     * @override
     */
    updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) {
        var axis = axisModel.axis;
        var grid = axis.grid;
        var axisExtent = axis.getGlobalExtent(true);
        var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
        var dimIndex = axis.dim === 'x' ? 0 : 1;

        var currPosition = transform.position;
        currPosition[dimIndex] += delta[dimIndex];
        currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
        currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);

        var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
        var cursorPoint = [cursorOtherValue, cursorOtherValue];
        cursorPoint[dimIndex] = currPosition[dimIndex];

        // Make tooltip do not overlap axisPointer and in the middle of the grid.
        var tooltipOptions = [{verticalAlign: 'middle'}, {align: 'center'}];

        return {
            position: currPosition,
            rotation: transform.rotation,
            cursorPoint: cursorPoint,
            tooltipOption: tooltipOptions[dimIndex]
        };
    }

});

function getCartesian(grid, axis) {
    var opt = {};
    opt[axis.dim + 'AxisIndex'] = axis.index;
    return grid.getCartesian(opt);
}

var pointerShapeBuilder = {

    line: function (axis, pixelValue, otherExtent) {
        var targetShape = makeLineShape(
            [pixelValue, otherExtent[0]],
            [pixelValue, otherExtent[1]],
            getAxisDimIndex(axis)
        );
        return {
            type: 'Line',
            subPixelOptimize: true,
            shape: targetShape
        };
    },

    shadow: function (axis, pixelValue, otherExtent) {
        var bandWidth = Math.max(1, axis.getBandWidth());
        var span = otherExtent[1] - otherExtent[0];
        return {
            type: 'Rect',
            shape: makeRectShape(
                [pixelValue - bandWidth / 2, otherExtent[0]],
                [bandWidth, span],
                getAxisDimIndex(axis)
            )
        };
    }
};

function getAxisDimIndex(axis) {
    return axis.dim === 'x' ? 0 : 1;
}

AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// CartesianAxisPointer is not supposed to be required here. But consider
// echarts.simple.js and online build tooltip, which only require gridSimple,
// CartesianAxisPointer should be able to required somewhere.
registerPreprocessor(function (option) {
    // Always has a global axisPointerModel for default setting.
    if (option) {
        (!option.axisPointer || option.axisPointer.length === 0)
            && (option.axisPointer = {});

        var link = option.axisPointer.link;
        // Normalize to array to avoid object mergin. But if link
        // is not set, remain null/undefined, otherwise it will
        // override existent link setting.
        if (link && !isArray(link)) {
            option.axisPointer.link = [link];
        }
    }
});

// This process should proformed after coordinate systems created
// and series data processed. So put it on statistic processing stage.
registerProcessor(PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) {
    // Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
    // allAxesInfo should be updated when setOption performed.
    ecModel.getComponent('axisPointer').coordSysAxesInfo =
        collect(ecModel, api);
});

// Broadcast to all views.
registerAction({
    type: 'updateAxisPointer',
    event: 'updateAxisPointer',
    update: ':updateAxisPointer'
}, axisTrigger);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var XY = ['x', 'y'];
var WH = ['width', 'height'];

var SingleAxisPointer = BaseAxisPointer.extend({

    /**
     * @override
     */
    makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
        var axis = axisModel.axis;
        var coordSys = axis.coordinateSystem;
        var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis));
        var pixelValue = coordSys.dataToPoint(value)[0];

        var axisPointerType = axisPointerModel.get('type');
        if (axisPointerType && axisPointerType !== 'none') {
            var elStyle = buildElStyle(axisPointerModel);
            var pointerOption = pointerShapeBuilder$1[axisPointerType](
                axis, pixelValue, otherExtent
            );
            pointerOption.style = elStyle;

            elOption.graphicKey = pointerOption.type;
            elOption.pointer = pointerOption;
        }

        var layoutInfo = layout$2(axisModel);
        buildCartesianSingleLabelElOption(
            value, elOption, layoutInfo, axisModel, axisPointerModel, api
        );
    },

    /**
     * @override
     */
    getHandleTransform: function (value, axisModel, axisPointerModel) {
        var layoutInfo = layout$2(axisModel, {labelInside: false});
        layoutInfo.labelMargin = axisPointerModel.get('handle.margin');
        return {
            position: getTransformedPosition(axisModel.axis, value, layoutInfo),
            rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
        };
    },

    /**
     * @override
     */
    updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) {
        var axis = axisModel.axis;
        var coordSys = axis.coordinateSystem;
        var dimIndex = getPointDimIndex(axis);
        var axisExtent = getGlobalExtent(coordSys, dimIndex);
        var currPosition = transform.position;
        currPosition[dimIndex] += delta[dimIndex];
        currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
        currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
        var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex);
        var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
        var cursorPoint = [cursorOtherValue, cursorOtherValue];
        cursorPoint[dimIndex] = currPosition[dimIndex];

        return {
            position: currPosition,
            rotation: transform.rotation,
            cursorPoint: cursorPoint,
            tooltipOption: {
                verticalAlign: 'middle'
            }
        };
    }
});

var pointerShapeBuilder$1 = {

    line: function (axis, pixelValue, otherExtent) {
        var targetShape = makeLineShape(
            [pixelValue, otherExtent[0]],
            [pixelValue, otherExtent[1]],
            getPointDimIndex(axis)
        );
        return {
            type: 'Line',
            subPixelOptimize: true,
            shape: targetShape
        };
    },

    shadow: function (axis, pixelValue, otherExtent) {
        var bandWidth = axis.getBandWidth();
        var span = otherExtent[1] - otherExtent[0];
        return {
            type: 'Rect',
            shape: makeRectShape(
                [pixelValue - bandWidth / 2, otherExtent[0]],
                [bandWidth, span],
                getPointDimIndex(axis)
            )
        };
    }
};

function getPointDimIndex(axis) {
    return axis.isHorizontal() ? 0 : 1;
}

function getGlobalExtent(coordSys, dimIndex) {
    var rect = coordSys.getRect();
    return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]];
}

AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentView({
    type: 'single'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DATA_NAME_INDEX = 2;

var ThemeRiverSeries = SeriesModel.extend({

    type: 'series.themeRiver',

    dependencies: ['singleAxis'],

    /**
     * @readOnly
     * @type {module:zrender/core/util#HashMap}
     */
    nameMap: null,

    /**
     * @override
     */
    init: function (option) {
        // eslint-disable-next-line
        ThemeRiverSeries.superApply(this, 'init', arguments);

        // Put this function here is for the sake of consistency of code style.
        // Enable legend selection for each data item
        // Use a function instead of direct access because data reference may changed
        this.legendDataProvider = function () {
            return this.getRawData();
        };
    },

    /**
     * If there is no value of a certain point in the time for some event,set it value to 0.
     *
     * @param {Array} data  initial data in the option
     * @return {Array}
     */
    fixData: function (data) {
        var rawDataLength = data.length;

        // grouped data by name
        var groupResult = groupData(data, function (item) {
            return item[2];
        });
        var layData = [];
        groupResult.buckets.each(function (items, key) {
            layData.push({name: key, dataList: items});
        });

        var layerNum = layData.length;
        var largestLayer = -1;
        var index = -1;
        for (var i = 0; i < layerNum; ++i) {
            var len = layData[i].dataList.length;
            if (len > largestLayer) {
                largestLayer = len;
                index = i;
            }
        }

        for (var k = 0; k < layerNum; ++k) {
            if (k === index) {
                continue;
            }
            var name = layData[k].name;
            for (var j = 0; j < largestLayer; ++j) {
                var timeValue = layData[index].dataList[j][0];
                var length = layData[k].dataList.length;
                var keyIndex = -1;
                for (var l = 0; l < length; ++l) {
                    var value = layData[k].dataList[l][0];
                    if (value === timeValue) {
                        keyIndex = l;
                        break;
                    }
                }
                if (keyIndex === -1) {
                    data[rawDataLength] = [];
                    data[rawDataLength][0] = timeValue;
                    data[rawDataLength][1] = 0;
                    data[rawDataLength][2] = name;
                    rawDataLength++;

                }
            }
        }
        return data;
    },

    /**
     * @override
     * @param  {Object} option  the initial option that user gived
     * @param  {module:echarts/model/Model} ecModel  the model object for themeRiver option
     * @return {module:echarts/data/List}
     */
    getInitialData: function (option, ecModel) {

        var singleAxisModel = ecModel.queryComponents({
            mainType: 'singleAxis',
            index: this.get('singleAxisIndex'),
            id: this.get('singleAxisId')
        })[0];

        var axisType = singleAxisModel.get('type');

        // filter the data item with the value of label is undefined
        var filterData = filter(option.data, function (dataItem) {
            return dataItem[2] !== undefined;
        });

        // ??? TODO design a stage to transfer data for themeRiver and lines?
        var data = this.fixData(filterData || []);
        var nameList = [];
        var nameMap = this.nameMap = createHashMap();
        var count = 0;

        for (var i = 0; i < data.length; ++i) {
            nameList.push(data[i][DATA_NAME_INDEX]);
            if (!nameMap.get(data[i][DATA_NAME_INDEX])) {
                nameMap.set(data[i][DATA_NAME_INDEX], count);
                count++;
            }
        }

        var dimensionsInfo = createDimensions(data, {
            coordDimensions: ['single'],
            dimensionsDefine: [
                {
                    name: 'time',
                    type: getDimensionTypeByAxis(axisType)
                },
                {
                    name: 'value',
                    type: 'float'
                },
                {
                    name: 'name',
                    type: 'ordinal'
                }
            ],
            encodeDefine: {
                single: 0,
                value: 1,
                itemName: 2
            }
        });

        var list = new List(dimensionsInfo, this);
        list.initData(data);

        return list;
    },

    /**
     * The raw data is divided into multiple layers and each layer
     *     has same name.
     *
     * @return {Array.<Array.<number>>}
     */
    getLayerSeries: function () {
        var data = this.getData();
        var lenCount = data.count();
        var indexArr = [];

        for (var i = 0; i < lenCount; ++i) {
            indexArr[i] = i;
        }

        var timeDim = data.mapDimension('single');

        // data group by name
        var groupResult = groupData(indexArr, function (index) {
            return data.get('name', index);
        });
        var layerSeries = [];
        groupResult.buckets.each(function (items, key) {
            items.sort(function (index1, index2) {
                return data.get(timeDim, index1) - data.get(timeDim, index2);
            });
            layerSeries.push({name: key, indices: items});
        });

        return layerSeries;
    },

    /**
     * Get data indices for show tooltip content

     * @param {Array.<string>|string} dim  single coordinate dimension
     * @param {number} value axis value
     * @param {module:echarts/coord/single/SingleAxis} baseAxis  single Axis used
     *     the themeRiver.
     * @return {Object} {dataIndices, nestestValue}
     */
    getAxisTooltipData: function (dim, value, baseAxis) {
        if (!isArray(dim)) {
            dim = dim ? [dim] : [];
        }

        var data = this.getData();
        var layerSeries = this.getLayerSeries();
        var indices = [];
        var layerNum = layerSeries.length;
        var nestestValue;

        for (var i = 0; i < layerNum; ++i) {
            var minDist = Number.MAX_VALUE;
            var nearestIdx = -1;
            var pointNum = layerSeries[i].indices.length;
            for (var j = 0; j < pointNum; ++j) {
                var theValue = data.get(dim[0], layerSeries[i].indices[j]);
                var dist = Math.abs(theValue - value);
                if (dist <= minDist) {
                    nestestValue = theValue;
                    minDist = dist;
                    nearestIdx = layerSeries[i].indices[j];
                }
            }
            indices.push(nearestIdx);
        }

        return {dataIndices: indices, nestestValue: nestestValue};
    },

    /**
     * @override
     * @param {number} dataIndex  index of data
     */
    formatTooltip: function (dataIndex) {
        var data = this.getData();
        var htmlName = data.getName(dataIndex);
        var htmlValue = data.get(data.mapDimension('value'), dataIndex);
        if (isNaN(htmlValue) || htmlValue == null) {
            htmlValue = '-';
        }
        return encodeHTML(htmlName + ' : ' + htmlValue);
    },

    defaultOption: {
        zlevel: 0,
        z: 2,

        coordinateSystem: 'singleAxis',

        // gap in axis's orthogonal orientation
        boundaryGap: ['10%', '10%'],

        // legendHoverLink: true,

        singleAxisIndex: 0,

        animationEasing: 'linear',

        label: {
            margin: 4,
            show: true,
            position: 'left',
            color: '#000',
            fontSize: 11
        },

        emphasis: {
            label: {
                show: true
            }
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendChartView({

    type: 'themeRiver',

    init: function () {
        this._layers = [];
    },

    render: function (seriesModel, ecModel, api) {
        var data = seriesModel.getData();

        var group = this.group;

        var layerSeries = seriesModel.getLayerSeries();

        var layoutInfo = data.getLayout('layoutInfo');
        var rect = layoutInfo.rect;
        var boundaryGap = layoutInfo.boundaryGap;

        group.attr('position', [0, rect.y + boundaryGap[0]]);

        function keyGetter(item) {
            return item.name;
        }
        var dataDiffer = new DataDiffer(
            this._layersSeries || [], layerSeries,
            keyGetter, keyGetter
        );

        var newLayersGroups = {};

        dataDiffer
            .add(bind(process, this, 'add'))
            .update(bind(process, this, 'update'))
            .remove(bind(process, this, 'remove'))
            .execute();

        function process(status, idx, oldIdx) {
            var oldLayersGroups = this._layers;
            if (status === 'remove') {
                group.remove(oldLayersGroups[idx]);
                return;
            }
            var points0 = [];
            var points1 = [];
            var color;
            var indices = layerSeries[idx].indices;
            for (var j = 0; j < indices.length; j++) {
                var layout = data.getItemLayout(indices[j]);
                var x = layout.x;
                var y0 = layout.y0;
                var y = layout.y;

                points0.push([x, y0]);
                points1.push([x, y0 + y]);

                color = data.getItemVisual(indices[j], 'color');
            }

            var polygon;
            var text;
            var textLayout = data.getItemLayout(indices[0]);
            var itemModel = data.getItemModel(indices[j - 1]);
            var labelModel = itemModel.getModel('label');
            var margin = labelModel.get('margin');
            if (status === 'add') {
                var layerGroup = newLayersGroups[idx] = new Group();
                polygon = new Polygon$1({
                    shape: {
                        points: points0,
                        stackedOnPoints: points1,
                        smooth: 0.4,
                        stackedOnSmooth: 0.4,
                        smoothConstraint: false
                    },
                    z2: 0
                });
                text = new Text({
                    style: {
                        x: textLayout.x - margin,
                        y: textLayout.y0 + textLayout.y / 2
                    }
                });
                layerGroup.add(polygon);
                layerGroup.add(text);
                group.add(layerGroup);

                polygon.setClipPath(createGridClipShape$2(polygon.getBoundingRect(), seriesModel, function () {
                    polygon.removeClipPath();
                }));
            }
            else {
                var layerGroup = oldLayersGroups[oldIdx];
                polygon = layerGroup.childAt(0);
                text = layerGroup.childAt(1);
                group.add(layerGroup);

                newLayersGroups[idx] = layerGroup;

                updateProps(polygon, {
                    shape: {
                        points: points0,
                        stackedOnPoints: points1
                    }
                }, seriesModel);

                updateProps(text, {
                    style: {
                        x: textLayout.x - margin,
                        y: textLayout.y0 + textLayout.y / 2
                    }
                }, seriesModel);
            }

            var hoverItemStyleModel = itemModel.getModel('emphasis.itemStyle');
            var itemStyleModel = itemModel.getModel('itemStyle');

            setTextStyle(text.style, labelModel, {
                text: labelModel.get('show')
                    ? seriesModel.getFormattedLabel(indices[j - 1], 'normal')
                        || data.getName(indices[j - 1])
                    : null,
                textVerticalAlign: 'middle'
            });

            polygon.setStyle(extend({
                fill: color
            }, itemStyleModel.getItemStyle(['color'])));

            setHoverStyle(polygon, hoverItemStyleModel.getItemStyle());
        }

        this._layersSeries = layerSeries;
        this._layers = newLayersGroups;
    },

    dispose: function () {}
});

// add animation to the view
function createGridClipShape$2(rect, seriesModel, cb) {
    var rectEl = new Rect({
        shape: {
            x: rect.x - 10,
            y: rect.y - 10,
            width: 0,
            height: rect.height + 20
        }
    });
    initProps(rectEl, {
        shape: {
            width: rect.width + 20,
            height: rect.height + 20
        }
    }, seriesModel, cb);

    return rectEl;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var themeRiverLayout = function (ecModel, api) {

    ecModel.eachSeriesByType('themeRiver', function (seriesModel) {

        var data = seriesModel.getData();

        var single = seriesModel.coordinateSystem;

        var layoutInfo = {};

        // use the axis boundingRect for view
        var rect = single.getRect();

        layoutInfo.rect = rect;

        var boundaryGap = seriesModel.get('boundaryGap');

        var axis = single.getAxis();

        layoutInfo.boundaryGap = boundaryGap;

        if (axis.orient === 'horizontal') {
            boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.height);
            boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.height);
            var height = rect.height - boundaryGap[0] - boundaryGap[1];
            themeRiverLayout$1(data, seriesModel, height);
        }
        else {
            boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.width);
            boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.width);
            var width = rect.width - boundaryGap[0] - boundaryGap[1];
            themeRiverLayout$1(data, seriesModel, width);
        }

        data.setLayout('layoutInfo', layoutInfo);
    });
};

/**
 * The layout information about themeriver
 *
 * @param {module:echarts/data/List} data  data in the series
 * @param {module:echarts/model/Series} seriesModel  the model object of themeRiver series
 * @param {number} height  value used to compute every series height
 */
function themeRiverLayout$1(data, seriesModel, height) {
    if (!data.count()) {
        return;
    }
    var coordSys = seriesModel.coordinateSystem;
    // the data in each layer are organized into a series.
    var layerSeries = seriesModel.getLayerSeries();

    // the points in each layer.
    var timeDim = data.mapDimension('single');
    var valueDim = data.mapDimension('value');
    var layerPoints = map(layerSeries, function (singleLayer) {
        return map(singleLayer.indices, function (idx) {
            var pt = coordSys.dataToPoint(data.get(timeDim, idx));
            pt[1] = data.get(valueDim, idx);
            return pt;
        });
    });

    var base = computeBaseline(layerPoints);
    var baseLine = base.y0;
    var ky = height / base.max;

    // set layout information for each item.
    var n = layerSeries.length;
    var m = layerSeries[0].indices.length;
    var baseY0;
    for (var j = 0; j < m; ++j) {
        baseY0 = baseLine[j] * ky;
        data.setItemLayout(layerSeries[0].indices[j], {
            layerIndex: 0,
            x: layerPoints[0][j][0],
            y0: baseY0,
            y: layerPoints[0][j][1] * ky
        });
        for (var i = 1; i < n; ++i) {
            baseY0 += layerPoints[i - 1][j][1] * ky;
            data.setItemLayout(layerSeries[i].indices[j], {
                layerIndex: i,
                x: layerPoints[i][j][0],
                y0: baseY0,
                y: layerPoints[i][j][1] * ky
            });
        }
    }
}

/**
 * Compute the baseLine of the rawdata
 * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics
 *
 * @param  {Array.<Array>} data  the points in each layer
 * @return {Object}
 */
function computeBaseline(data) {
    var layerNum = data.length;
    var pointNum = data[0].length;
    var sums = [];
    var y0 = [];
    var max = 0;
    var temp;
    var base = {};

    for (var i = 0; i < pointNum; ++i) {
        for (var j = 0, temp = 0; j < layerNum; ++j) {
            temp += data[j][i][1];
        }
        if (temp > max) {
            max = temp;
        }
        sums.push(temp);
    }

    for (var k = 0; k < pointNum; ++k) {
        y0[k] = (max - sums[k]) / 2;
    }
    max = 0;

    for (var l = 0; l < pointNum; ++l) {
        var sum = sums[l] + y0[l];
        if (sum > max) {
            max = sum;
        }
    }
    base.y0 = y0;
    base.max = max;

    return base;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var themeRiverVisual = function (ecModel) {
    ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
        var data = seriesModel.getData();
        var rawData = seriesModel.getRawData();
        var colorList = seriesModel.get('color');
        var idxMap = createHashMap();

        data.each(function (idx) {
            idxMap.set(data.getRawIndex(idx), idx);
        });

        rawData.each(function (rawIndex) {
            var name = rawData.getName(rawIndex);
            var color = colorList[(seriesModel.nameMap.get(name) - 1) % colorList.length];

            rawData.setItemVisual(rawIndex, 'color', color);

            var idx = idxMap.get(rawIndex);

            if (idx != null) {
                data.setItemVisual(idx, 'color', color);
            }
        });
    });
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerLayout(themeRiverLayout);
registerVisual(themeRiverVisual);
registerProcessor(dataFilter('themeRiver'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

SeriesModel.extend({

    type: 'series.sunburst',

    /**
     * @type {module:echarts/data/Tree~Node}
     */
    _viewRoot: null,

    getInitialData: function (option, ecModel) {
        // Create a virtual root.
        var root = { name: option.name, children: option.data };

        completeTreeValue$1(root);

        var levels = option.levels || [];

        // levels = option.levels = setDefault(levels, ecModel);

        var treeOption = {};

        treeOption.levels = levels;

        // Make sure always a new tree is created when setOption,
        // in TreemapView, we check whether oldTree === newTree
        // to choose mappings approach among old shapes and new shapes.
        return Tree.createTree(root, this, treeOption).data;
    },

    optionUpdated: function () {
        this.resetViewRoot();
    },

    /*
     * @override
     */
    getDataParams: function (dataIndex) {
        var params = SeriesModel.prototype.getDataParams.apply(this, arguments);

        var node = this.getData().tree.getNodeByDataIndex(dataIndex);
        params.treePathInfo = wrapTreePathInfo(node, this);

        return params;
    },

    defaultOption: {
        zlevel: 0,
        z: 2,

        // 默认全局居中
        center: ['50%', '50%'],
        radius: [0, '75%'],
        // 默认顺时针
        clockwise: true,
        startAngle: 90,
        // 最小角度改为0
        minAngle: 0,

        percentPrecision: 2,

        // If still show when all data zero.
        stillShowZeroSum: true,

        // Policy of highlighting pieces when hover on one
        // Valid values: 'none' (for not downplay others), 'descendant',
        // 'ancestor', 'self'
        highlightPolicy: 'descendant',

        // 'rootToNode', 'link', or false
        nodeClick: 'rootToNode',

        renderLabelForZeroData: false,

        label: {
            // could be: 'radial', 'tangential', or 'none'
            rotate: 'radial',
            show: true,
            opacity: 1,
            // 'left' is for inner side of inside, and 'right' is for outter
            // side for inside
            align: 'center',
            position: 'inside',
            distance: 5,
            silent: true,
            emphasis: {}
        },
        itemStyle: {
            borderWidth: 1,
            borderColor: 'white',
            borderType: 'solid',
            shadowBlur: 0,
            shadowColor: 'rgba(0, 0, 0, 0.2)',
            shadowOffsetX: 0,
            shadowOffsetY: 0,
            opacity: 1,
            emphasis: {},
            highlight: {
                opacity: 1
            },
            downplay: {
                opacity: 0.9
            }
        },

        // Animation type canbe expansion, scale
        animationType: 'expansion',
        animationDuration: 1000,
        animationDurationUpdate: 500,
        animationEasing: 'cubicOut',

        data: [],

        levels: [],

        /**
         * Sort order.
         *
         * Valid values: 'desc', 'asc', null, or callback function.
         * 'desc' and 'asc' for descend and ascendant order;
         * null for not sorting;
         * example of callback function:
         * function(nodeA, nodeB) {
         *     return nodeA.getValue() - nodeB.getValue();
         * }
         */
        sort: 'desc'
    },

    getViewRoot: function () {
        return this._viewRoot;
    },

    /**
     * @param {module:echarts/data/Tree~Node} [viewRoot]
     */
    resetViewRoot: function (viewRoot) {
        viewRoot
            ? (this._viewRoot = viewRoot)
            : (viewRoot = this._viewRoot);

        var root = this.getRawData().tree.root;

        if (!viewRoot
            || (viewRoot !== root && !root.contains(viewRoot))
        ) {
            this._viewRoot = root;
        }
    }
});



/**
 * @param {Object} dataNode
 */
function completeTreeValue$1(dataNode) {
    // Postorder travel tree.
    // If value of none-leaf node is not set,
    // calculate it by suming up the value of all children.
    var sum = 0;

    each$1(dataNode.children, function (child) {

        completeTreeValue$1(child);

        var childValue = child.value;
        isArray(childValue) && (childValue = childValue[0]);

        sum += childValue;
    });

    var thisValue = dataNode.value;
    if (isArray(thisValue)) {
        thisValue = thisValue[0];
    }

    if (thisValue == null || isNaN(thisValue)) {
        thisValue = sum;
    }
    // Value should not less than 0.
    if (thisValue < 0) {
        thisValue = 0;
    }

    isArray(dataNode.value)
        ? (dataNode.value[0] = thisValue)
        : (dataNode.value = thisValue);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var NodeHighlightPolicy = {
    NONE: 'none', // not downplay others
    DESCENDANT: 'descendant',
    ANCESTOR: 'ancestor',
    SELF: 'self'
};

var DEFAULT_SECTOR_Z = 2;
var DEFAULT_TEXT_Z = 4;

/**
 * Sunburstce of Sunburst including Sector, Label, LabelLine
 * @constructor
 * @extends {module:zrender/graphic/Group}
 */
function SunburstPiece(node, seriesModel, ecModel) {

    Group.call(this);

    var sector = new Sector({
        z2: DEFAULT_SECTOR_Z
    });
    sector.seriesIndex = seriesModel.seriesIndex;

    var text = new Text({
        z2: DEFAULT_TEXT_Z,
        silent: node.getModel('label').get('silent')
    });
    this.add(sector);
    this.add(text);

    this.updateData(true, node, 'normal', seriesModel, ecModel);

    // Hover to change label and labelLine
    function onEmphasis() {
        text.ignore = text.hoverIgnore;
    }
    function onNormal() {
        text.ignore = text.normalIgnore;
    }
    this.on('emphasis', onEmphasis)
        .on('normal', onNormal)
        .on('mouseover', onEmphasis)
        .on('mouseout', onNormal);
}

var SunburstPieceProto = SunburstPiece.prototype;

SunburstPieceProto.updateData = function (
    firstCreate,
    node,
    state,
    seriesModel,
    ecModel
) {
    this.node = node;
    node.piece = this;

    seriesModel = seriesModel || this._seriesModel;
    ecModel = ecModel || this._ecModel;

    var sector = this.childAt(0);
    sector.dataIndex = node.dataIndex;

    var itemModel = node.getModel();
    var layout = node.getLayout();
    // if (!layout) {
    //     console.log(node.getLayout());
    // }
    var sectorShape = extend({}, layout);
    sectorShape.label = null;

    var visualColor = getNodeColor(node, seriesModel, ecModel);

    fillDefaultColor(node, seriesModel, visualColor);

    var normalStyle = itemModel.getModel('itemStyle').getItemStyle();
    var style;
    if (state === 'normal') {
        style = normalStyle;
    }
    else {
        var stateStyle = itemModel.getModel(state + '.itemStyle')
            .getItemStyle();
        style = merge(stateStyle, normalStyle);
    }
    style = defaults(
        {
            lineJoin: 'bevel',
            fill: style.fill || visualColor
        },
        style
    );

    if (firstCreate) {
        sector.setShape(sectorShape);
        sector.shape.r = layout.r0;
        updateProps(
            sector,
            {
                shape: {
                    r: layout.r
                }
            },
            seriesModel,
            node.dataIndex
        );
        sector.useStyle(style);
    }
    else if (typeof style.fill === 'object' && style.fill.type
        || typeof sector.style.fill === 'object' && sector.style.fill.type
    ) {
        // Disable animation for gradient since no interpolation method
        // is supported for gradient
        updateProps(sector, {
            shape: sectorShape
        }, seriesModel);
        sector.useStyle(style);
    }
    else {
        updateProps(sector, {
            shape: sectorShape,
            style: style
        }, seriesModel);
    }

    this._updateLabel(seriesModel, visualColor, state);

    var cursorStyle = itemModel.getShallow('cursor');
    cursorStyle && sector.attr('cursor', cursorStyle);

    if (firstCreate) {
        var highlightPolicy = seriesModel.getShallow('highlightPolicy');
        this._initEvents(sector, node, seriesModel, highlightPolicy);
    }

    this._seriesModel = seriesModel || this._seriesModel;
    this._ecModel = ecModel || this._ecModel;
};

SunburstPieceProto.onEmphasis = function (highlightPolicy) {
    var that = this;
    this.node.hostTree.root.eachNode(function (n) {
        if (n.piece) {
            if (that.node === n) {
                n.piece.updateData(false, n, 'emphasis');
            }
            else if (isNodeHighlighted(n, that.node, highlightPolicy)) {
                n.piece.childAt(0).trigger('highlight');
            }
            else if (highlightPolicy !== NodeHighlightPolicy.NONE) {
                n.piece.childAt(0).trigger('downplay');
            }
        }
    });
};

SunburstPieceProto.onNormal = function () {
    this.node.hostTree.root.eachNode(function (n) {
        if (n.piece) {
            n.piece.updateData(false, n, 'normal');
        }
    });
};

SunburstPieceProto.onHighlight = function () {
    this.updateData(false, this.node, 'highlight');
};

SunburstPieceProto.onDownplay = function () {
    this.updateData(false, this.node, 'downplay');
};

SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) {
    var itemModel = this.node.getModel();
    var normalModel = itemModel.getModel('label');
    var labelModel = state === 'normal' || state === 'emphasis'
        ? normalModel
        : itemModel.getModel(state + '.label');
    var labelHoverModel = itemModel.getModel('emphasis.label');

    var text = retrieve(
        seriesModel.getFormattedLabel(
            this.node.dataIndex, state, null, null, 'label'
        ),
        this.node.name
    );
    if (getLabelAttr('show') === false) {
        text = '';
    }

    var layout = this.node.getLayout();
    var labelMinAngle = labelModel.get('minAngle');
    if (labelMinAngle == null) {
        labelMinAngle = normalModel.get('minAngle');
    }
    labelMinAngle = labelMinAngle / 180 * Math.PI;
    var angle = layout.endAngle - layout.startAngle;
    if (labelMinAngle != null && Math.abs(angle) < labelMinAngle) {
        // Not displaying text when angle is too small
        text = '';
    }

    var label = this.childAt(1);

    setLabelStyle(
        label.style, label.hoverStyle || {}, normalModel, labelHoverModel,
        {
            defaultText: labelModel.getShallow('show') ? text : null,
            autoColor: visualColor,
            useInsideStyle: true
        }
    );

    var midAngle = (layout.startAngle + layout.endAngle) / 2;
    var dx = Math.cos(midAngle);
    var dy = Math.sin(midAngle);

    var r;
    var labelPosition = getLabelAttr('position');
    var labelPadding = getLabelAttr('distance') || 0;
    var textAlign = getLabelAttr('align');
    if (labelPosition === 'outside') {
        r = layout.r + labelPadding;
        textAlign = midAngle > Math.PI / 2 ? 'right' : 'left';
    }
    else {
        if (!textAlign || textAlign === 'center') {
            r = (layout.r + layout.r0) / 2;
            textAlign = 'center';
        }
        else if (textAlign === 'left') {
            r = layout.r0 + labelPadding;
            if (midAngle > Math.PI / 2) {
                textAlign = 'right';
            }
        }
        else if (textAlign === 'right') {
            r = layout.r - labelPadding;
            if (midAngle > Math.PI / 2) {
                textAlign = 'left';
            }
        }
    }

    label.attr('style', {
        text: text,
        textAlign: textAlign,
        textVerticalAlign: getLabelAttr('verticalAlign') || 'middle',
        opacity: getLabelAttr('opacity')
    });

    var textX = r * dx + layout.cx;
    var textY = r * dy + layout.cy;
    label.attr('position', [textX, textY]);

    var rotateType = getLabelAttr('rotate');
    var rotate = 0;
    if (rotateType === 'radial') {
        rotate = -midAngle;
        if (rotate < -Math.PI / 2) {
            rotate += Math.PI;
        }
    }
    else if (rotateType === 'tangential') {
        rotate = Math.PI / 2 - midAngle;
        if (rotate > Math.PI / 2) {
            rotate -= Math.PI;
        }
        else if (rotate < -Math.PI / 2) {
            rotate += Math.PI;
        }
    }
    else if (typeof rotateType === 'number') {
        rotate = rotateType * Math.PI / 180;
    }
    label.attr('rotation', rotate);

    function getLabelAttr(name) {
        var stateAttr = labelModel.get(name);
        if (stateAttr == null) {
            return normalModel.get(name);
        }
        else {
            return stateAttr;
        }
    }
};

SunburstPieceProto._initEvents = function (
    sector,
    node,
    seriesModel,
    highlightPolicy
) {
    sector.off('mouseover').off('mouseout').off('emphasis').off('normal');

    var that = this;
    var onEmphasis = function () {
        that.onEmphasis(highlightPolicy);
    };
    var onNormal = function () {
        that.onNormal();
    };
    var onDownplay = function () {
        that.onDownplay();
    };
    var onHighlight = function () {
        that.onHighlight();
    };

    if (seriesModel.isAnimationEnabled()) {
        sector
            .on('mouseover', onEmphasis)
            .on('mouseout', onNormal)
            .on('emphasis', onEmphasis)
            .on('normal', onNormal)
            .on('downplay', onDownplay)
            .on('highlight', onHighlight);
    }
};

inherits(SunburstPiece, Group);

/**
 * Get node color
 *
 * @param {TreeNode} node the node to get color
 * @param {module:echarts/model/Series} seriesModel series
 * @param {module:echarts/model/Global} ecModel echarts defaults
 */
function getNodeColor(node, seriesModel, ecModel) {
    // Color from visualMap
    var visualColor = node.getVisual('color');
    var visualMetaList = node.getVisual('visualMeta');
    if (!visualMetaList || visualMetaList.length === 0) {
        // Use first-generation color if has no visualMap
        visualColor = null;
    }

    // Self color or level color
    var color = node.getModel('itemStyle').get('color');
    if (color) {
        return color;
    }
    else if (visualColor) {
        // Color mapping
        return visualColor;
    }
    else if (node.depth === 0) {
        // Virtual root node
        return ecModel.option.color[0];
    }
    else {
        // First-generation color
        var length = ecModel.option.color.length;
        color = ecModel.option.color[getRootId(node) % length];
    }
    return color;
}

/**
 * Get index of root in sorted order
 *
 * @param {TreeNode} node current node
 * @return {number} index in root
 */
function getRootId(node) {
    var ancestor = node;
    while (ancestor.depth > 1) {
        ancestor = ancestor.parentNode;
    }

    var virtualRoot = node.getAncestors()[0];
    return indexOf(virtualRoot.children, ancestor);
}

function isNodeHighlighted(node, activeNode, policy) {
    if (policy === NodeHighlightPolicy.NONE) {
        return false;
    }
    else if (policy === NodeHighlightPolicy.SELF) {
        return node === activeNode;
    }
    else if (policy === NodeHighlightPolicy.ANCESTOR) {
        return node === activeNode || node.isAncestorOf(activeNode);
    }
    else {
        return node === activeNode || node.isDescendantOf(activeNode);
    }
}

// Fix tooltip callback function params.color incorrect when pick a default color
function fillDefaultColor(node, seriesModel, color) {
    var data = seriesModel.getData();
    data.setItemVisual(node.dataIndex, 'color', color);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var ROOT_TO_NODE_ACTION = 'sunburstRootToNode';

var SunburstView = Chart.extend({

    type: 'sunburst',

    init: function () {
    },

    render: function (seriesModel, ecModel, api, payload) {
        var that = this;

        this.seriesModel = seriesModel;
        this.api = api;
        this.ecModel = ecModel;

        var data = seriesModel.getData();
        var virtualRoot = data.tree.root;

        var newRoot = seriesModel.getViewRoot();

        var group = this.group;

        var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData');

        var newChildren = [];
        newRoot.eachNode(function (node) {
            newChildren.push(node);
        });
        var oldChildren = this._oldChildren || [];

        dualTravel(newChildren, oldChildren);

        renderRollUp(virtualRoot, newRoot);

        if (payload && payload.highlight && payload.highlight.piece) {
            var highlightPolicy = seriesModel.getShallow('highlightPolicy');
            payload.highlight.piece.onEmphasis(highlightPolicy);
        }
        else if (payload && payload.unhighlight) {
            var piece = this.virtualPiece;
            if (!piece && virtualRoot.children.length) {
                piece = virtualRoot.children[0].piece;
            }
            if (piece) {
                piece.onNormal();
            }
        }

        this._initEvents();

        this._oldChildren = newChildren;

        function dualTravel(newChildren, oldChildren) {
            if (newChildren.length === 0 && oldChildren.length === 0) {
                return;
            }

            new DataDiffer(oldChildren, newChildren, getKey, getKey)
                .add(processNode)
                .update(processNode)
                .remove(curry(processNode, null))
                .execute();

            function getKey(node) {
                return node.getId();
            }

            function processNode(newId, oldId) {
                var newNode = newId == null ? null : newChildren[newId];
                var oldNode = oldId == null ? null : oldChildren[oldId];

                doRenderNode(newNode, oldNode);
            }
        }

        function doRenderNode(newNode, oldNode) {
            if (!renderLabelForZeroData && newNode && !newNode.getValue()) {
                // Not render data with value 0
                newNode = null;
            }

            if (newNode !== virtualRoot && oldNode !== virtualRoot) {
                if (oldNode && oldNode.piece) {
                    if (newNode) {
                        // Update
                        oldNode.piece.updateData(
                            false, newNode, 'normal', seriesModel, ecModel);

                        // For tooltip
                        data.setItemGraphicEl(newNode.dataIndex, oldNode.piece);
                    }
                    else {
                        // Remove
                        removeNode(oldNode);
                    }
                }
                else if (newNode) {
                    // Add
                    var piece = new SunburstPiece(
                        newNode,
                        seriesModel,
                        ecModel
                    );
                    group.add(piece);

                    // For tooltip
                    data.setItemGraphicEl(newNode.dataIndex, piece);
                }
            }
        }

        function removeNode(node) {
            if (!node) {
                return;
            }

            if (node.piece) {
                group.remove(node.piece);
                node.piece = null;
            }
        }

        function renderRollUp(virtualRoot, viewRoot) {
            if (viewRoot.depth > 0) {
                // Render
                if (that.virtualPiece) {
                    // Update
                    that.virtualPiece.updateData(
                        false, virtualRoot, 'normal', seriesModel, ecModel);
                }
                else {
                    // Add
                    that.virtualPiece = new SunburstPiece(
                        virtualRoot,
                        seriesModel,
                        ecModel
                    );
                    group.add(that.virtualPiece);
                }

                if (viewRoot.piece._onclickEvent) {
                    viewRoot.piece.off('click', viewRoot.piece._onclickEvent);
                }
                var event = function (e) {
                    that._rootToNode(viewRoot.parentNode);
                };
                viewRoot.piece._onclickEvent = event;
                that.virtualPiece.on('click', event);
            }
            else if (that.virtualPiece) {
                // Remove
                group.remove(that.virtualPiece);
                that.virtualPiece = null;
            }
        }
    },

    dispose: function () {
    },

    /**
     * @private
     */
    _initEvents: function () {
        var that = this;

        var event = function (e) {
            var targetFound = false;
            var viewRoot = that.seriesModel.getViewRoot();
            viewRoot.eachNode(function (node) {
                if (!targetFound
                    && node.piece && node.piece.childAt(0) === e.target
                ) {
                    var nodeClick = node.getModel().get('nodeClick');
                    if (nodeClick === 'rootToNode') {
                        that._rootToNode(node);
                    }
                    else if (nodeClick === 'link') {
                        var itemModel = node.getModel();
                        var link = itemModel.get('link');
                        if (link) {
                            var linkTarget = itemModel.get('target', true)
                                || '_blank';
                            window.open(link, linkTarget);
                        }
                    }
                    targetFound = true;
                }
            });
        };

        if (this.group._onclickEvent) {
            this.group.off('click', this.group._onclickEvent);
        }
        this.group.on('click', event);
        this.group._onclickEvent = event;
    },

    /**
     * @private
     */
    _rootToNode: function (node) {
        if (node !== this.seriesModel.getViewRoot()) {
            this.api.dispatchAction({
                type: ROOT_TO_NODE_ACTION,
                from: this.uid,
                seriesId: this.seriesModel.id,
                targetNode: node
            });
        }
    },

    /**
     * @implement
     */
    containPoint: function (point, seriesModel) {
        var treeRoot = seriesModel.getData();
        var itemLayout = treeRoot.getItemLayout(0);
        if (itemLayout) {
            var dx = point[0] - itemLayout.cx;
            var dy = point[1] - itemLayout.cy;
            var radius = Math.sqrt(dx * dx + dy * dy);
            return radius <= itemLayout.r && radius >= itemLayout.r0;
        }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @file Sunburst action
 */

var ROOT_TO_NODE_ACTION$1 = 'sunburstRootToNode';

registerAction(
    {type: ROOT_TO_NODE_ACTION$1, update: 'updateView'},
    function (payload, ecModel) {

        ecModel.eachComponent(
            {mainType: 'series', subType: 'sunburst', query: payload},
            handleRootToNode
        );

        function handleRootToNode(model, index) {
            var targetInfo = retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION$1], model);

            if (targetInfo) {
                var originViewRoot = model.getViewRoot();
                if (originViewRoot) {
                    payload.direction = aboveViewRoot(originViewRoot, targetInfo.node)
                        ? 'rollUp' : 'drillDown';
                }
                model.resetViewRoot(targetInfo.node);
            }
        }
    }
);


var HIGHLIGHT_ACTION = 'sunburstHighlight';

registerAction(
    {type: HIGHLIGHT_ACTION, update: 'updateView'},
    function (payload, ecModel) {

        ecModel.eachComponent(
            {mainType: 'series', subType: 'sunburst', query: payload},
            handleHighlight
        );

        function handleHighlight(model, index) {
            var targetInfo = retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model);

            if (targetInfo) {
                payload.highlight = targetInfo.node;
            }
        }
    }
);


var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight';

registerAction(
    {type: UNHIGHLIGHT_ACTION, update: 'updateView'},
    function (payload, ecModel) {

        ecModel.eachComponent(
            {mainType: 'series', subType: 'sunburst', query: payload},
            handleUnhighlight
        );

        function handleUnhighlight(model, index) {
            payload.unhighlight = true;
        }
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


// var PI2 = Math.PI * 2;
var RADIAN$2 = Math.PI / 180;

var sunburstLayout = function (seriesType, ecModel, api, payload) {
    ecModel.eachSeriesByType(seriesType, function (seriesModel) {
        var center = seriesModel.get('center');
        var radius = seriesModel.get('radius');

        if (!isArray(radius)) {
            radius = [0, radius];
        }
        if (!isArray(center)) {
            center = [center, center];
        }

        var width = api.getWidth();
        var height = api.getHeight();
        var size = Math.min(width, height);
        var cx = parsePercent$1(center[0], width);
        var cy = parsePercent$1(center[1], height);
        var r0 = parsePercent$1(radius[0], size / 2);
        var r = parsePercent$1(radius[1], size / 2);

        var startAngle = -seriesModel.get('startAngle') * RADIAN$2;
        var minAngle = seriesModel.get('minAngle') * RADIAN$2;

        var virtualRoot = seriesModel.getData().tree.root;
        var treeRoot = seriesModel.getViewRoot();
        var rootDepth = treeRoot.depth;

        var sort = seriesModel.get('sort');
        if (sort != null) {
            initChildren$1(treeRoot, sort);
        }

        var validDataCount = 0;
        each$1(treeRoot.children, function (child) {
            !isNaN(child.getValue()) && validDataCount++;
        });

        var sum = treeRoot.getValue();
        // Sum may be 0
        var unitRadian = Math.PI / (sum || validDataCount) * 2;

        var renderRollupNode = treeRoot.depth > 0;
        var levels = treeRoot.height - (renderRollupNode ? -1 : 1);
        var rPerLevel = (r - r0) / (levels || 1);

        var clockwise = seriesModel.get('clockwise');

        var stillShowZeroSum = seriesModel.get('stillShowZeroSum');

        // In the case some sector angle is smaller than minAngle
        // var restAngle = PI2;
        // var valueSumLargerThanMinAngle = 0;

        var dir = clockwise ? 1 : -1;

        /**
         * Render a tree
         * @return increased angle
         */
        var renderNode = function (node, startAngle) {
            if (!node) {
                return;
            }

            var endAngle = startAngle;

            // Render self
            if (node !== virtualRoot) {
                // Tree node is virtual, so it doesn't need to be drawn
                var value = node.getValue();

                var angle = (sum === 0 && stillShowZeroSum)
                    ? unitRadian : (value * unitRadian);
                if (angle < minAngle) {
                    angle = minAngle;
                    // restAngle -= minAngle;
                }
                // else {
                //     valueSumLargerThanMinAngle += value;
                // }

                endAngle = startAngle + dir * angle;

                var depth = node.depth - rootDepth
                    - (renderRollupNode ? -1 : 1);
                var rStart = r0 + rPerLevel * depth;
                var rEnd = r0 + rPerLevel * (depth + 1);

                var itemModel = node.getModel();
                if (itemModel.get('r0') != null) {
                    rStart = parsePercent$1(itemModel.get('r0'), size / 2);
                }
                if (itemModel.get('r') != null) {
                    rEnd = parsePercent$1(itemModel.get('r'), size / 2);
                }

                node.setLayout({
                    angle: angle,
                    startAngle: startAngle,
                    endAngle: endAngle,
                    clockwise: clockwise,
                    cx: cx,
                    cy: cy,
                    r0: rStart,
                    r: rEnd
                });
            }

            // Render children
            if (node.children && node.children.length) {
                // currentAngle = startAngle;
                var siblingAngle = 0;
                each$1(node.children, function (node) {
                    siblingAngle += renderNode(node, startAngle + siblingAngle);
                });
            }

            return endAngle - startAngle;
        };

        // Virtual root node for roll up
        if (renderRollupNode) {
            var rStart = r0;
            var rEnd = r0 + rPerLevel;

            var angle = Math.PI * 2;
            virtualRoot.setLayout({
                angle: angle,
                startAngle: startAngle,
                endAngle: startAngle + angle,
                clockwise: clockwise,
                cx: cx,
                cy: cy,
                r0: rStart,
                r: rEnd
            });
        }

        renderNode(treeRoot, startAngle);
    });
};

/**
 * Init node children by order and update visual
 *
 * @param {TreeNode} node  root node
 * @param {boolean}  isAsc if is in ascendant order
 */
function initChildren$1(node, isAsc) {
    var children = node.children || [];

    node.children = sort$2(children, isAsc);

    // Init children recursively
    if (children.length) {
        each$1(node.children, function (child) {
            initChildren$1(child, isAsc);
        });
    }
}

/**
 * Sort children nodes
 *
 * @param {TreeNode[]}               children children of node to be sorted
 * @param {string | function | null} sort sort method
 *                                   See SunburstSeries.js for details.
 */
function sort$2(children, sortOrder) {
    if (typeof sortOrder === 'function') {
        return children.sort(sortOrder);
    }
    else {
        var isAsc = sortOrder === 'asc';
        return children.sort(function (a, b) {
            var diff = (a.getValue() - b.getValue()) * (isAsc ? 1 : -1);
            return diff === 0
                ? (a.dataIndex - b.dataIndex) * (isAsc ? -1 : 1)
                : diff;
        });
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerVisual(curry(dataColor, 'sunburst'));
registerLayout(curry(sunburstLayout, 'sunburst'));
registerProcessor(curry(dataFilter, 'sunburst'));

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function dataToCoordSize(dataSize, dataItem) {
    // dataItem is necessary in log axis.
    dataItem = dataItem || [0, 0];
    return map(['x', 'y'], function (dim, dimIdx) {
        var axis = this.getAxis(dim);
        var val = dataItem[dimIdx];
        var halfSize = dataSize[dimIdx] / 2;
        return axis.type === 'category'
            ? axis.getBandWidth()
            : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
    }, this);
}

var prepareCartesian2d = function (coordSys) {
    var rect = coordSys.grid.getRect();
    return {
        coordSys: {
            // The name exposed to user is always 'cartesian2d' but not 'grid'.
            type: 'cartesian2d',
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
        },
        api: {
            coord: function (data) {
                // do not provide "out" param
                return coordSys.dataToPoint(data);
            },
            size: bind(dataToCoordSize, coordSys)
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function dataToCoordSize$1(dataSize, dataItem) {
    dataItem = dataItem || [0, 0];
    return map([0, 1], function (dimIdx) {
        var val = dataItem[dimIdx];
        var halfSize = dataSize[dimIdx] / 2;
        var p1 = [];
        var p2 = [];
        p1[dimIdx] = val - halfSize;
        p2[dimIdx] = val + halfSize;
        p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx];
        return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]);
    }, this);
}

var prepareGeo = function (coordSys) {
    var rect = coordSys.getBoundingRect();
    return {
        coordSys: {
            type: 'geo',
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height,
            zoom: coordSys.getZoom()
        },
        api: {
            coord: function (data) {
                // do not provide "out" and noRoam param,
                // Compatible with this usage:
                // echarts.util.map(item.points, api.coord)
                return coordSys.dataToPoint(data);
            },
            size: bind(dataToCoordSize$1, coordSys)
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function dataToCoordSize$2(dataSize, dataItem) {
    // dataItem is necessary in log axis.
    var axis = this.getAxis();
    var val = dataItem instanceof Array ? dataItem[0] : dataItem;
    var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2;
    return axis.type === 'category'
        ? axis.getBandWidth()
        : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
}

var prepareSingleAxis = function (coordSys) {
    var rect = coordSys.getRect();

    return {
        coordSys: {
            type: 'singleAxis',
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
        },
        api: {
            coord: function (val) {
                // do not provide "out" param
                return coordSys.dataToPoint(val);
            },
            size: bind(dataToCoordSize$2, coordSys)
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function dataToCoordSize$3(dataSize, dataItem) {
    // dataItem is necessary in log axis.
    return map(['Radius', 'Angle'], function (dim, dimIdx) {
        var axis = this['get' + dim + 'Axis']();
        var val = dataItem[dimIdx];
        var halfSize = dataSize[dimIdx] / 2;
        var method = 'dataTo' + dim;

        var result = axis.type === 'category'
            ? axis.getBandWidth()
            : Math.abs(axis[method](val - halfSize) - axis[method](val + halfSize));

        if (dim === 'Angle') {
            result = result * Math.PI / 180;
        }

        return result;

    }, this);
}

var preparePolar = function (coordSys) {
    var radiusAxis = coordSys.getRadiusAxis();
    var angleAxis = coordSys.getAngleAxis();
    var radius = radiusAxis.getExtent();
    radius[0] > radius[1] && radius.reverse();

    return {
        coordSys: {
            type: 'polar',
            cx: coordSys.cx,
            cy: coordSys.cy,
            r: radius[1],
            r0: radius[0]
        },
        api: {
            coord: bind(function (data) {
                var radius = radiusAxis.dataToRadius(data[0]);
                var angle = angleAxis.dataToAngle(data[1]);
                var coord = coordSys.coordToPoint([radius, angle]);
                coord.push(radius, angle * Math.PI / 180);
                return coord;
            }),
            size: bind(dataToCoordSize$3, coordSys)
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var prepareCalendar = function (coordSys) {
    var rect = coordSys.getRect();
    var rangeInfo = coordSys.getRangeInfo();

    return {
        coordSys: {
            type: 'calendar',
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height,
            cellWidth: coordSys.getCellWidth(),
            cellHeight: coordSys.getCellHeight(),
            rangeInfo: {
                start: rangeInfo.start,
                end: rangeInfo.end,
                weeks: rangeInfo.weeks,
                dayCount: rangeInfo.allDay
            }
        },
        api: {
            coord: function (data, clamp) {
                return coordSys.dataToPoint(data, clamp);
            }
        }
    };
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var CACHED_LABEL_STYLE_PROPERTIES$1 = CACHED_LABEL_STYLE_PROPERTIES;
var ITEM_STYLE_NORMAL_PATH = ['itemStyle'];
var ITEM_STYLE_EMPHASIS_PATH = ['emphasis', 'itemStyle'];
var LABEL_NORMAL = ['label'];
var LABEL_EMPHASIS = ['emphasis', 'label'];
// Use prefix to avoid index to be the same as el.name,
// which will cause weird udpate animation.
var GROUP_DIFF_PREFIX = 'e\0\0';


/**
 * To reduce total package size of each coordinate systems, the modules `prepareCustom`
 * of each coordinate systems are not required by each coordinate systems directly, but
 * required by the module `custom`.
 *
 * prepareInfoForCustomSeries {Function}: optional
 *     @return {Object} {coordSys: {...}, api: {
 *         coord: function (data, clamp) {}, // return point in global.
 *         size: function (dataSize, dataItem) {} // return size of each axis in coordSys.
 *     }}
 */
var prepareCustoms = {
    cartesian2d: prepareCartesian2d,
    geo: prepareGeo,
    singleAxis: prepareSingleAxis,
    polar: preparePolar,
    calendar: prepareCalendar
};


// ------
// Model
// ------

SeriesModel.extend({

    type: 'series.custom',

    dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],

    defaultOption: {
        coordinateSystem: 'cartesian2d', // Can be set as 'none'
        zlevel: 0,
        z: 2,
        legendHoverLink: true,

        useTransform: true,

        // Custom series will not clip by default.
        // Some case will use custom series to draw label
        // For example https://echarts.apache.org/examples/en/editor.html?c=custom-gantt-flight
        // Only works on polar and cartesian2d coordinate system.
        clip: false

        // Cartesian coordinate system
        // xAxisIndex: 0,
        // yAxisIndex: 0,

        // Polar coordinate system
        // polarIndex: 0,

        // Geo coordinate system
        // geoIndex: 0,

        // label: {}
        // itemStyle: {}
    },

    /**
     * @override
     */
    getInitialData: function (option, ecModel) {
        return createListFromArray(this.getSource(), this);
    },

    /**
     * @override
     */
    getDataParams: function (dataIndex, dataType, el) {
        var params = SeriesModel.prototype.getDataParams.apply(this, arguments);
        el && (params.info = el.info);
        return params;
    }
});

// -----
// View
// -----

Chart.extend({

    type: 'custom',

    /**
     * @private
     * @type {module:echarts/data/List}
     */
    _data: null,

    /**
     * @override
     */
    render: function (customSeries, ecModel, api, payload) {
        var oldData = this._data;
        var data = customSeries.getData();
        var group = this.group;
        var renderItem = makeRenderItem(customSeries, data, ecModel, api);

        // By default, merge mode is applied. In most cases, custom series is
        // used in the scenario that data amount is not large but graphic elements
        // is complicated, where merge mode is probably necessary for optimization.
        // For example, reuse graphic elements and only update the transform when
        // roam or data zoom according to `actionType`.
        data.diff(oldData)
            .add(function (newIdx) {
                createOrUpdate$1(
                    null, newIdx, renderItem(newIdx, payload), customSeries, group, data
                );
            })
            .update(function (newIdx, oldIdx) {
                var el = oldData.getItemGraphicEl(oldIdx);
                createOrUpdate$1(
                    el, newIdx, renderItem(newIdx, payload), customSeries, group, data
                );
            })
            .remove(function (oldIdx) {
                var el = oldData.getItemGraphicEl(oldIdx);
                el && group.remove(el);
            })
            .execute();

        // Do clipping
        var clipPath = customSeries.get('clip', true)
            ? createClipPath(customSeries.coordinateSystem, false, customSeries)
            : null;
        if (clipPath) {
            group.setClipPath(clipPath);
        }
        else {
            group.removeClipPath();
        }

        this._data = data;
    },

    incrementalPrepareRender: function (customSeries, ecModel, api) {
        this.group.removeAll();
        this._data = null;
    },

    incrementalRender: function (params, customSeries, ecModel, api, payload) {
        var data = customSeries.getData();
        var renderItem = makeRenderItem(customSeries, data, ecModel, api);
        function setIncrementalAndHoverLayer(el) {
            if (!el.isGroup) {
                el.incremental = true;
                el.useHoverLayer = true;
            }
        }
        for (var idx = params.start; idx < params.end; idx++) {
            var el = createOrUpdate$1(null, idx, renderItem(idx, payload), customSeries, this.group, data);
            el.traverse(setIncrementalAndHoverLayer);
        }
    },

    /**
     * @override
     */
    dispose: noop,

    /**
     * @override
     */
    filterForExposedEvent: function (eventType, query, targetEl, packedEvent) {
        var elementName = query.element;
        if (elementName == null || targetEl.name === elementName) {
            return true;
        }

        // Enable to give a name on a group made by `renderItem`, and listen
        // events that triggerd by its descendents.
        while ((targetEl = targetEl.parent) && targetEl !== this.group) {
            if (targetEl.name === elementName) {
                return true;
            }
        }

        return false;
    }
});


function createEl(elOption) {
    var graphicType = elOption.type;
    var el;

    // Those graphic elements are not shapes. They should not be
    // overwritten by users, so do them first.
    if (graphicType === 'path') {
        var shape = elOption.shape;
        // Using pathRect brings convenience to users sacle svg path.
        var pathRect = (shape.width != null && shape.height != null)
            ? {
                x: shape.x || 0,
                y: shape.y || 0,
                width: shape.width,
                height: shape.height
            }
            : null;
        var pathData = getPathData(shape);
        // Path is also used for icon, so layout 'center' by default.
        el = makePath(pathData, null, pathRect, shape.layout || 'center');
        el.__customPathData = pathData;
    }
    else if (graphicType === 'image') {
        el = new ZImage({});
        el.__customImagePath = elOption.style.image;
    }
    else if (graphicType === 'text') {
        el = new Text({});
        el.__customText = elOption.style.text;
    }
    else if (graphicType === 'group') {
        el = new Group();
    }
    else if (graphicType === 'compoundPath') {
        throw new Error('"compoundPath" is not supported yet.');
    }
    else {
        var Clz = getShapeClass(graphicType);

        if (__DEV__) {
            assert$1(Clz, 'graphic type "' + graphicType + '" can not be found.');
        }

        el = new Clz();
    }

    el.__customGraphicType = graphicType;
    el.name = elOption.name;

    return el;
}

function updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot) {
    var transitionProps = {};
    var elOptionStyle = elOption.style || {};

    elOption.shape && (transitionProps.shape = clone(elOption.shape));
    elOption.position && (transitionProps.position = elOption.position.slice());
    elOption.scale && (transitionProps.scale = elOption.scale.slice());
    elOption.origin && (transitionProps.origin = elOption.origin.slice());
    elOption.rotation && (transitionProps.rotation = elOption.rotation);

    if (el.type === 'image' && elOption.style) {
        var targetStyle = transitionProps.style = {};
        each$1(['x', 'y', 'width', 'height'], function (prop) {
            prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit);
        });
    }

    if (el.type === 'text' && elOption.style) {
        var targetStyle = transitionProps.style = {};
        each$1(['x', 'y'], function (prop) {
            prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit);
        });
        // Compatible with previous: both support
        // textFill and fill, textStroke and stroke in 'text' element.
        !elOptionStyle.hasOwnProperty('textFill') && elOptionStyle.fill && (
            elOptionStyle.textFill = elOptionStyle.fill
        );
        !elOptionStyle.hasOwnProperty('textStroke') && elOptionStyle.stroke && (
            elOptionStyle.textStroke = elOptionStyle.stroke
        );
    }

    if (el.type !== 'group') {
        el.useStyle(elOptionStyle);

        // Init animation.
        if (isInit) {
            el.style.opacity = 0;
            var targetOpacity = elOptionStyle.opacity;
            targetOpacity == null && (targetOpacity = 1);
            initProps(el, {style: {opacity: targetOpacity}}, animatableModel, dataIndex);
        }
    }

    if (isInit) {
        el.attr(transitionProps);
    }
    else {
        updateProps(el, transitionProps, animatableModel, dataIndex);
    }

    // Merge by default.
    // z2 must not be null/undefined, otherwise sort error may occur.
    elOption.hasOwnProperty('z2') && el.attr('z2', elOption.z2 || 0);
    elOption.hasOwnProperty('silent') && el.attr('silent', elOption.silent);
    elOption.hasOwnProperty('invisible') && el.attr('invisible', elOption.invisible);
    elOption.hasOwnProperty('ignore') && el.attr('ignore', elOption.ignore);
    // `elOption.info` enables user to mount some info on
    // elements and use them in event handlers.
    // Update them only when user specified, otherwise, remain.
    elOption.hasOwnProperty('info') && el.attr('info', elOption.info);

    // If `elOption.styleEmphasis` is `false`, remove hover style. The
    // logic is ensured by `graphicUtil.setElementHoverStyle`.
    var styleEmphasis = elOption.styleEmphasis;
    // hoverStyle should always be set here, because if the hover style
    // may already be changed, where the inner cache should be reset.
    setElementHoverStyle(el, styleEmphasis);
    if (isRoot) {
        setAsHighDownDispatcher(el, styleEmphasis !== false);
    }
}

function prepareStyleTransition(prop, targetStyle, elOptionStyle, oldElStyle, isInit) {
    if (elOptionStyle[prop] != null && !isInit) {
        targetStyle[prop] = elOptionStyle[prop];
        elOptionStyle[prop] = oldElStyle[prop];
    }
}

function makeRenderItem(customSeries, data, ecModel, api) {
    var renderItem = customSeries.get('renderItem');
    var coordSys = customSeries.coordinateSystem;
    var prepareResult = {};

    if (coordSys) {
        if (__DEV__) {
            assert$1(renderItem, 'series.render is required.');
            assert$1(
                coordSys.prepareCustoms || prepareCustoms[coordSys.type],
                'This coordSys does not support custom series.'
            );
        }

        prepareResult = coordSys.prepareCustoms
            ? coordSys.prepareCustoms()
            : prepareCustoms[coordSys.type](coordSys);
    }

    var userAPI = defaults({
        getWidth: api.getWidth,
        getHeight: api.getHeight,
        getZr: api.getZr,
        getDevicePixelRatio: api.getDevicePixelRatio,
        value: value,
        style: style,
        styleEmphasis: styleEmphasis,
        visual: visual,
        barLayout: barLayout,
        currentSeriesIndices: currentSeriesIndices,
        font: font
    }, prepareResult.api || {});

    var userParams = {
        // The life cycle of context: current round of rendering.
        // The global life cycle is probably not necessary, because
        // user can store global status by themselves.
        context: {},
        seriesId: customSeries.id,
        seriesName: customSeries.name,
        seriesIndex: customSeries.seriesIndex,
        coordSys: prepareResult.coordSys,
        dataInsideLength: data.count(),
        encode: wrapEncodeDef(customSeries.getData())
    };

    // Do not support call `api` asynchronously without dataIndexInside input.
    var currDataIndexInside;
    var currDirty = true;
    var currItemModel;
    var currLabelNormalModel;
    var currLabelEmphasisModel;
    var currVisualColor;

    return function (dataIndexInside, payload) {
        currDataIndexInside = dataIndexInside;
        currDirty = true;

        return renderItem && renderItem(
            defaults({
                dataIndexInside: dataIndexInside,
                dataIndex: data.getRawIndex(dataIndexInside),
                // Can be used for optimization when zoom or roam.
                actionType: payload ? payload.type : null
            }, userParams),
            userAPI
        );
    };

    // Do not update cache until api called.
    function updateCache(dataIndexInside) {
        dataIndexInside == null && (dataIndexInside = currDataIndexInside);
        if (currDirty) {
            currItemModel = data.getItemModel(dataIndexInside);
            currLabelNormalModel = currItemModel.getModel(LABEL_NORMAL);
            currLabelEmphasisModel = currItemModel.getModel(LABEL_EMPHASIS);
            currVisualColor = data.getItemVisual(dataIndexInside, 'color');

            currDirty = false;
        }
    }

    /**
     * @public
     * @param {number|string} dim
     * @param {number} [dataIndexInside=currDataIndexInside]
     * @return {number|string} value
     */
    function value(dim, dataIndexInside) {
        dataIndexInside == null && (dataIndexInside = currDataIndexInside);
        return data.get(data.getDimension(dim || 0), dataIndexInside);
    }

    /**
     * By default, `visual` is applied to style (to support visualMap).
     * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`,
     * it can be implemented as:
     * `api.style({stroke: api.visual('color'), fill: null})`;
     * @public
     * @param {Object} [extra]
     * @param {number} [dataIndexInside=currDataIndexInside]
     */
    function style(extra, dataIndexInside) {
        dataIndexInside == null && (dataIndexInside = currDataIndexInside);
        updateCache(dataIndexInside);

        var itemStyle = currItemModel.getModel(ITEM_STYLE_NORMAL_PATH).getItemStyle();

        currVisualColor != null && (itemStyle.fill = currVisualColor);
        var opacity = data.getItemVisual(dataIndexInside, 'opacity');
        opacity != null && (itemStyle.opacity = opacity);

        var labelModel = extra
            ? applyExtraBefore(extra, currLabelNormalModel)
            : currLabelNormalModel;

        setTextStyle(itemStyle, labelModel, null, {
            autoColor: currVisualColor,
            isRectText: true
        });

        itemStyle.text = labelModel.getShallow('show')
            ? retrieve2(
                customSeries.getFormattedLabel(dataIndexInside, 'normal'),
                getDefaultLabel(data, dataIndexInside)
            )
            : null;

        extra && applyExtraAfter(itemStyle, extra);

        return itemStyle;
    }

    /**
     * @public
     * @param {Object} [extra]
     * @param {number} [dataIndexInside=currDataIndexInside]
     */
    function styleEmphasis(extra, dataIndexInside) {
        dataIndexInside == null && (dataIndexInside = currDataIndexInside);
        updateCache(dataIndexInside);

        var itemStyle = currItemModel.getModel(ITEM_STYLE_EMPHASIS_PATH).getItemStyle();

        var labelModel = extra
            ? applyExtraBefore(extra, currLabelEmphasisModel)
            : currLabelEmphasisModel;

        setTextStyle(itemStyle, labelModel, null, {
            isRectText: true
        }, true);

        itemStyle.text = labelModel.getShallow('show')
            ? retrieve3(
                customSeries.getFormattedLabel(dataIndexInside, 'emphasis'),
                customSeries.getFormattedLabel(dataIndexInside, 'normal'),
                getDefaultLabel(data, dataIndexInside)
            )
            : null;

        extra && applyExtraAfter(itemStyle, extra);

        return itemStyle;
    }

    /**
     * @public
     * @param {string} visualType
     * @param {number} [dataIndexInside=currDataIndexInside]
     */
    function visual(visualType, dataIndexInside) {
        dataIndexInside == null && (dataIndexInside = currDataIndexInside);
        return data.getItemVisual(dataIndexInside, visualType);
    }

    /**
     * @public
     * @param {number} opt.count Positive interger.
     * @param {number} [opt.barWidth]
     * @param {number} [opt.barMaxWidth]
     * @param {number} [opt.barMinWidth]
     * @param {number} [opt.barGap]
     * @param {number} [opt.barCategoryGap]
     * @return {Object} {width, offset, offsetCenter} is not support, return undefined.
     */
    function barLayout(opt) {
        if (coordSys.getBaseAxis) {
            var baseAxis = coordSys.getBaseAxis();
            return getLayoutOnAxis(defaults({axis: baseAxis}, opt), api);
        }
    }

    /**
     * @public
     * @return {Array.<number>}
     */
    function currentSeriesIndices() {
        return ecModel.getCurrentSeriesIndices();
    }

    /**
     * @public
     * @param {Object} opt
     * @param {string} [opt.fontStyle]
     * @param {number} [opt.fontWeight]
     * @param {number} [opt.fontSize]
     * @param {string} [opt.fontFamily]
     * @return {string} font string
     */
    function font(opt) {
        return getFont(opt, ecModel);
    }
}

function wrapEncodeDef(data) {
    var encodeDef = {};
    each$1(data.dimensions, function (dimName, dataDimIndex) {
        var dimInfo = data.getDimensionInfo(dimName);
        if (!dimInfo.isExtraCoord) {
            var coordDim = dimInfo.coordDim;
            var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || [];
            dataDims[dimInfo.coordDimIndex] = dataDimIndex;
        }
    });
    return encodeDef;
}

function createOrUpdate$1(el, dataIndex, elOption, animatableModel, group, data) {
    el = doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data, true);
    el && data.setItemGraphicEl(dataIndex, el);

    return el;
}

function doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data, isRoot) {

    // [Rule]
    // By default, follow merge mode.
    //     (It probably brings benifit for performance in some cases of large data, where
    //     user program can be optimized to that only updated props needed to be re-calculated,
    //     or according to `actionType` some calculation can be skipped.)
    // If `renderItem` returns `null`/`undefined`/`false`, remove the previous el if existing.
    //     (It seems that violate the "merge" principle, but most of users probably intuitively
    //     regard "return;" as "show nothing element whatever", so make a exception to meet the
    //     most cases.)

    var simplyRemove = !elOption; // `null`/`undefined`/`false`
    elOption = elOption || {};
    var elOptionType = elOption.type;
    var elOptionShape = elOption.shape;
    var elOptionStyle = elOption.style;

    if (el && (
        simplyRemove
        // || elOption.$merge === false
        // If `elOptionType` is `null`, follow the merge principle.
        || (elOptionType != null
            && elOptionType !== el.__customGraphicType
        )
        || (elOptionType === 'path'
            && hasOwnPathData(elOptionShape) && getPathData(elOptionShape) !== el.__customPathData
        )
        || (elOptionType === 'image'
            && hasOwn(elOptionStyle, 'image') && elOptionStyle.image !== el.__customImagePath
        )
        // FIXME test and remove this restriction?
        || (elOptionType === 'text'
            && hasOwn(elOptionShape, 'text') && elOptionStyle.text !== el.__customText
        )
    )) {
        group.remove(el);
        el = null;
    }

    // `elOption.type` is undefined when `renderItem` returns nothing.
    if (simplyRemove) {
        return;
    }

    var isInit = !el;
    !el && (el = createEl(elOption));
    updateEl(el, dataIndex, elOption, animatableModel, data, isInit, isRoot);

    if (elOptionType === 'group') {
        mergeChildren(el, dataIndex, elOption, animatableModel, data);
    }

    // Always add whatever already added to ensure sequence.
    group.add(el);

    return el;
}

// Usage:
// (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates that
//     the existing children will not be removed, and enables the feature that
//     update some of the props of some of the children simply by construct
//     the returned children of `renderItem` like:
//     `var children = group.children = []; children[3] = {opacity: 0.5};`
// (2) If `elOption.$mergeChildren` is `'byName'`, add/update/remove children
//     by child.name. But that might be lower performance.
// (3) If `elOption.$mergeChildren` is `false`, the existing children will be
//     replaced totally.
// (4) If `!elOption.children`, following the "merge" principle, nothing will happen.
//
// For implementation simpleness, do not provide a direct way to remove sinlge
// child (otherwise the total indicies of the children array have to be modified).
// User can remove a single child by set its `ignore` as `true` or replace
// it by another element, where its `$merge` can be set as `true` if necessary.
function mergeChildren(el, dataIndex, elOption, animatableModel, data) {
    var newChildren = elOption.children;
    var newLen = newChildren ? newChildren.length : 0;
    var mergeChildren = elOption.$mergeChildren;
    // `diffChildrenByName` has been deprecated.
    var byName = mergeChildren === 'byName' || elOption.diffChildrenByName;
    var notMerge = mergeChildren === false;

    // For better performance on roam update, only enter if necessary.
    if (!newLen && !byName && !notMerge) {
        return;
    }

    if (byName) {
        diffGroupChildren({
            oldChildren: el.children() || [],
            newChildren: newChildren || [],
            dataIndex: dataIndex,
            animatableModel: animatableModel,
            group: el,
            data: data
        });
        return;
    }

    notMerge && el.removeAll();

    // Mapping children of a group simply by index, which
    // might be better performance.
    var index = 0;
    for (; index < newLen; index++) {
        newChildren[index] && doCreateOrUpdate(
            el.childAt(index),
            dataIndex,
            newChildren[index],
            animatableModel,
            el,
            data
        );
    }
    if (__DEV__) {
        assert$1(
            !notMerge || el.childCount() === index,
            'MUST NOT contain empty item in children array when `group.$mergeChildren` is `false`.'
        );
    }
}

function diffGroupChildren(context) {
    (new DataDiffer(
        context.oldChildren,
        context.newChildren,
        getKey,
        getKey,
        context
    ))
        .add(processAddUpdate)
        .update(processAddUpdate)
        .remove(processRemove)
        .execute();
}

function getKey(item, idx) {
    var name = item && item.name;
    return name != null ? name : GROUP_DIFF_PREFIX + idx;
}

function processAddUpdate(newIndex, oldIndex) {
    var context = this.context;
    var childOption = newIndex != null ? context.newChildren[newIndex] : null;
    var child = oldIndex != null ? context.oldChildren[oldIndex] : null;

    doCreateOrUpdate(
        child,
        context.dataIndex,
        childOption,
        context.animatableModel,
        context.group,
        context.data
    );
}

// `graphic#applyDefaultTextStyle` will cache
// textFill, textStroke, textStrokeWidth.
// We have to do this trick.
function applyExtraBefore(extra, model) {
    var dummyModel = new Model({}, model);
    each$1(CACHED_LABEL_STYLE_PROPERTIES$1, function (stylePropName, modelPropName) {
        if (extra.hasOwnProperty(stylePropName)) {
            dummyModel.option[modelPropName] = extra[stylePropName];
        }
    });
    return dummyModel;
}

function applyExtraAfter(itemStyle, extra) {
    for (var key in extra) {
        if (extra.hasOwnProperty(key)
            || !CACHED_LABEL_STYLE_PROPERTIES$1.hasOwnProperty(key)
        ) {
            itemStyle[key] = extra[key];
        }
    }
}

function processRemove(oldIndex) {
    var context = this.context;
    var child = context.oldChildren[oldIndex];
    child && context.group.remove(child);
}

function getPathData(shape) {
    // "d" follows the SVG convention.
    return shape && (shape.pathData || shape.d);
}

function hasOwnPathData(shape) {
    return shape && (shape.hasOwnProperty('pathData') || shape.hasOwnProperty('d'));
}

function hasOwn(host, prop) {
    return host && host.hasOwnProperty(prop);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function getSeriesStackId$1(seriesModel) {
    return seriesModel.get('stack')
        || '__ec_stack_' + seriesModel.seriesIndex;
}

function getAxisKey$1(polar, axis) {
    return axis.dim + polar.model.componentIndex;
}

/**
 * @param {string} seriesType
 * @param {module:echarts/model/Global} ecModel
 * @param {module:echarts/ExtensionAPI} api
 */
function barLayoutPolar(seriesType, ecModel, api) {

    var lastStackCoords = {};

    var barWidthAndOffset = calRadialBar(
        filter(
            ecModel.getSeriesByType(seriesType),
            function (seriesModel) {
                return !ecModel.isSeriesFiltered(seriesModel)
                    && seriesModel.coordinateSystem
                    && seriesModel.coordinateSystem.type === 'polar';
            }
        )
    );

    ecModel.eachSeriesByType(seriesType, function (seriesModel) {

        // Check series coordinate, do layout for polar only
        if (seriesModel.coordinateSystem.type !== 'polar') {
            return;
        }

        var data = seriesModel.getData();
        var polar = seriesModel.coordinateSystem;
        var baseAxis = polar.getBaseAxis();
        var axisKey = getAxisKey$1(polar, baseAxis);

        var stackId = getSeriesStackId$1(seriesModel);
        var columnLayoutInfo = barWidthAndOffset[axisKey][stackId];
        var columnOffset = columnLayoutInfo.offset;
        var columnWidth = columnLayoutInfo.width;
        var valueAxis = polar.getOtherAxis(baseAxis);

        var cx = seriesModel.coordinateSystem.cx;
        var cy = seriesModel.coordinateSystem.cy;

        var barMinHeight = seriesModel.get('barMinHeight') || 0;
        var barMinAngle = seriesModel.get('barMinAngle') || 0;

        lastStackCoords[stackId] = lastStackCoords[stackId] || [];

        var valueDim = data.mapDimension(valueAxis.dim);
        var baseDim = data.mapDimension(baseAxis.dim);
        var stacked = isDimensionStacked(data, valueDim /*, baseDim*/);
        var clampLayout = baseAxis.dim !== 'radius'
            || !seriesModel.get('roundCap', true);

        var valueAxisStart = valueAxis.getExtent()[0];

        for (var idx = 0, len = data.count(); idx < len; idx++) {
            var value = data.get(valueDim, idx);
            var baseValue = data.get(baseDim, idx);

            if (isNaN(value)) {
                continue;
            }

            var sign = value >= 0 ? 'p' : 'n';
            var baseCoord = valueAxisStart;

            // Because of the barMinHeight, we can not use the value in
            // stackResultDimension directly.
            // Only ordinal axis can be stacked.
            if (stacked) {
                if (!lastStackCoords[stackId][baseValue]) {
                    lastStackCoords[stackId][baseValue] = {
                        p: valueAxisStart, // Positive stack
                        n: valueAxisStart  // Negative stack
                    };
                }
                // Should also consider #4243
                baseCoord = lastStackCoords[stackId][baseValue][sign];
            }

            var r0;
            var r;
            var startAngle;
            var endAngle;

            // radial sector
            if (valueAxis.dim === 'radius') {
                var radiusSpan = valueAxis.dataToRadius(value) - valueAxisStart;
                var angle = baseAxis.dataToAngle(baseValue);

                if (Math.abs(radiusSpan) < barMinHeight) {
                    radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight;
                }

                r0 = baseCoord;
                r = baseCoord + radiusSpan;
                startAngle = angle - columnOffset;
                endAngle = startAngle - columnWidth;

                stacked && (lastStackCoords[stackId][baseValue][sign] = r);
            }
            // tangential sector
            else {
                var angleSpan = valueAxis.dataToAngle(value, clampLayout) - valueAxisStart;
                var radius = baseAxis.dataToRadius(baseValue);

                if (Math.abs(angleSpan) < barMinAngle) {
                    angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle;
                }

                r0 = radius + columnOffset;
                r = r0 + columnWidth;
                startAngle = baseCoord;
                endAngle = baseCoord + angleSpan;

                // if the previous stack is at the end of the ring,
                // add a round to differentiate it from origin
                // var extent = angleAxis.getExtent();
                // var stackCoord = angle;
                // if (stackCoord === extent[0] && value > 0) {
                //     stackCoord = extent[1];
                // }
                // else if (stackCoord === extent[1] && value < 0) {
                //     stackCoord = extent[0];
                // }
                stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle);
            }

            data.setItemLayout(idx, {
                cx: cx,
                cy: cy,
                r0: r0,
                r: r,
                // Consider that positive angle is anti-clockwise,
                // while positive radian of sector is clockwise
                startAngle: -startAngle * Math.PI / 180,
                endAngle: -endAngle * Math.PI / 180
            });

        }

    }, this);

}

/**
 * Calculate bar width and offset for radial bar charts
 */
function calRadialBar(barSeries, api) {
    // Columns info on each category axis. Key is polar name
    var columnsMap = {};

    each$1(barSeries, function (seriesModel, idx) {
        var data = seriesModel.getData();
        var polar = seriesModel.coordinateSystem;

        var baseAxis = polar.getBaseAxis();
        var axisKey = getAxisKey$1(polar, baseAxis);

        var axisExtent = baseAxis.getExtent();
        var bandWidth = baseAxis.type === 'category'
            ? baseAxis.getBandWidth()
            : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count());

        var columnsOnAxis = columnsMap[axisKey] || {
            bandWidth: bandWidth,
            remainedWidth: bandWidth,
            autoWidthCount: 0,
            categoryGap: '20%',
            gap: '30%',
            stacks: {}
        };
        var stacks = columnsOnAxis.stacks;
        columnsMap[axisKey] = columnsOnAxis;

        var stackId = getSeriesStackId$1(seriesModel);

        if (!stacks[stackId]) {
            columnsOnAxis.autoWidthCount++;
        }
        stacks[stackId] = stacks[stackId] || {
            width: 0,
            maxWidth: 0
        };

        var barWidth = parsePercent$1(
            seriesModel.get('barWidth'),
            bandWidth
        );
        var barMaxWidth = parsePercent$1(
            seriesModel.get('barMaxWidth'),
            bandWidth
        );
        var barGap = seriesModel.get('barGap');
        var barCategoryGap = seriesModel.get('barCategoryGap');

        if (barWidth && !stacks[stackId].width) {
            barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
            stacks[stackId].width = barWidth;
            columnsOnAxis.remainedWidth -= barWidth;
        }

        barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
        (barGap != null) && (columnsOnAxis.gap = barGap);
        (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap);
    });


    var result = {};

    each$1(columnsMap, function (columnsOnAxis, coordSysName) {

        result[coordSysName] = {};

        var stacks = columnsOnAxis.stacks;
        var bandWidth = columnsOnAxis.bandWidth;
        var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth);
        var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1);

        var remainedWidth = columnsOnAxis.remainedWidth;
        var autoWidthCount = columnsOnAxis.autoWidthCount;
        var autoWidth = (remainedWidth - categoryGap)
            / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
        autoWidth = Math.max(autoWidth, 0);

        // Find if any auto calculated bar exceeded maxBarWidth
        each$1(stacks, function (column, stack) {
            var maxWidth = column.maxWidth;
            if (maxWidth && maxWidth < autoWidth) {
                maxWidth = Math.min(maxWidth, remainedWidth);
                if (column.width) {
                    maxWidth = Math.min(maxWidth, column.width);
                }
                remainedWidth -= maxWidth;
                column.width = maxWidth;
                autoWidthCount--;
            }
        });

        // Recalculate width again
        autoWidth = (remainedWidth - categoryGap)
            / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
        autoWidth = Math.max(autoWidth, 0);

        var widthSum = 0;
        var lastColumn;
        each$1(stacks, function (column, idx) {
            if (!column.width) {
                column.width = autoWidth;
            }
            lastColumn = column;
            widthSum += column.width * (1 + barGapPercent);
        });
        if (lastColumn) {
            widthSum -= lastColumn.width * barGapPercent;
        }

        var offset = -widthSum / 2;
        each$1(stacks, function (column, stackId) {
            result[coordSysName][stackId] = result[coordSysName][stackId] || {
                offset: offset,
                width: column.width
            };

            offset += column.width * (1 + barGapPercent);
        });
    });

    return result;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function RadiusAxis(scale, radiusExtent) {

    Axis.call(this, 'radius', scale, radiusExtent);

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = 'category';
}

RadiusAxis.prototype = {

    constructor: RadiusAxis,

    /**
     * @override
     */
    pointToData: function (point, clamp) {
        return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
    },

    dataToRadius: Axis.prototype.dataToCoord,

    radiusToData: Axis.prototype.coordToData
};

inherits(RadiusAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var inner$12 = makeInner();

function AngleAxis(scale, angleExtent) {

    angleExtent = angleExtent || [0, 360];

    Axis.call(this, 'angle', scale, angleExtent);

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = 'category';
}

AngleAxis.prototype = {

    constructor: AngleAxis,

    /**
     * @override
     */
    pointToData: function (point, clamp) {
        return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
    },

    dataToAngle: Axis.prototype.dataToCoord,

    angleToData: Axis.prototype.coordToData,

    /**
     * Only be called in category axis.
     * Angle axis uses text height to decide interval
     *
     * @override
     * @return {number} Auto interval for cateogry axis tick and label
     */
    calculateCategoryInterval: function () {
        var axis = this;
        var labelModel = axis.getLabelModel();

        var ordinalScale = axis.scale;
        var ordinalExtent = ordinalScale.getExtent();
        // Providing this method is for optimization:
        // avoid generating a long array by `getTicks`
        // in large category data case.
        var tickCount = ordinalScale.count();

        if (ordinalExtent[1] - ordinalExtent[0] < 1) {
            return 0;
        }

        var tickValue = ordinalExtent[0];
        var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
        var unitH = Math.abs(unitSpan);

        // Not precise, just use height as text width
        // and each distance from axis line yet.
        var rect = getBoundingRect(
            tickValue, labelModel.getFont(), 'center', 'top'
        );
        var maxH = Math.max(rect.height, 7);

        var dh = maxH / unitH;
        // 0/0 is NaN, 1/0 is Infinity.
        isNaN(dh) && (dh = Infinity);
        var interval = Math.max(0, Math.floor(dh));

        var cache = inner$12(axis.model);
        var lastAutoInterval = cache.lastAutoInterval;
        var lastTickCount = cache.lastTickCount;

        // Use cache to keep interval stable while moving zoom window,
        // otherwise the calculated interval might jitter when the zoom
        // window size is close to the interval-changing size.
        if (lastAutoInterval != null
            && lastTickCount != null
            && Math.abs(lastAutoInterval - interval) <= 1
            && Math.abs(lastTickCount - tickCount) <= 1
            // Always choose the bigger one, otherwise the critical
            // point is not the same when zooming in or zooming out.
            && lastAutoInterval > interval
        ) {
            interval = lastAutoInterval;
        }
        // Only update cache if cache not used, otherwise the
        // changing of interval is too insensitive.
        else {
            cache.lastTickCount = tickCount;
            cache.lastAutoInterval = interval;
        }

        return interval;
    }
};

inherits(AngleAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @module echarts/coord/polar/Polar
 */

/**
 * @alias {module:echarts/coord/polar/Polar}
 * @constructor
 * @param {string} name
 */
var Polar = function (name) {

    /**
     * @type {string}
     */
    this.name = name || '';

    /**
     * x of polar center
     * @type {number}
     */
    this.cx = 0;

    /**
     * y of polar center
     * @type {number}
     */
    this.cy = 0;

    /**
     * @type {module:echarts/coord/polar/RadiusAxis}
     * @private
     */
    this._radiusAxis = new RadiusAxis();

    /**
     * @type {module:echarts/coord/polar/AngleAxis}
     * @private
     */
    this._angleAxis = new AngleAxis();

    this._radiusAxis.polar = this._angleAxis.polar = this;
};

Polar.prototype = {

    type: 'polar',

    axisPointerEnabled: true,

    constructor: Polar,

    /**
     * @param {Array.<string>}
     * @readOnly
     */
    dimensions: ['radius', 'angle'],

    /**
     * @type {module:echarts/coord/PolarModel}
     */
    model: null,

    /**
     * If contain coord
     * @param {Array.<number>} point
     * @return {boolean}
     */
    containPoint: function (point) {
        var coord = this.pointToCoord(point);
        return this._radiusAxis.contain(coord[0])
            && this._angleAxis.contain(coord[1]);
    },

    /**
     * If contain data
     * @param {Array.<number>} data
     * @return {boolean}
     */
    containData: function (data) {
        return this._radiusAxis.containData(data[0])
            && this._angleAxis.containData(data[1]);
    },

    /**
     * @param {string} dim
     * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
     */
    getAxis: function (dim) {
        return this['_' + dim + 'Axis'];
    },

    /**
     * @return {Array.<module:echarts/coord/Axis>}
     */
    getAxes: function () {
        return [this._radiusAxis, this._angleAxis];
    },

    /**
     * Get axes by type of scale
     * @param {string} scaleType
     * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
     */
    getAxesByScale: function (scaleType) {
        var axes = [];
        var angleAxis = this._angleAxis;
        var radiusAxis = this._radiusAxis;
        angleAxis.scale.type === scaleType && axes.push(angleAxis);
        radiusAxis.scale.type === scaleType && axes.push(radiusAxis);

        return axes;
    },

    /**
     * @return {module:echarts/coord/polar/AngleAxis}
     */
    getAngleAxis: function () {
        return this._angleAxis;
    },

    /**
     * @return {module:echarts/coord/polar/RadiusAxis}
     */
    getRadiusAxis: function () {
        return this._radiusAxis;
    },

    /**
     * @param {module:echarts/coord/polar/Axis}
     * @return {module:echarts/coord/polar/Axis}
     */
    getOtherAxis: function (axis) {
        var angleAxis = this._angleAxis;
        return axis === angleAxis ? this._radiusAxis : angleAxis;
    },

    /**
     * Base axis will be used on stacking.
     *
     * @return {module:echarts/coord/polar/Axis}
     */
    getBaseAxis: function () {
        return this.getAxesByScale('ordinal')[0]
            || this.getAxesByScale('time')[0]
            || this.getAngleAxis();
    },

    /**
     * @param {string} [dim] 'radius' or 'angle' or 'auto' or null/undefined
     * @return {Object} {baseAxes: [], otherAxes: []}
     */
    getTooltipAxes: function (dim) {
        var baseAxis = (dim != null && dim !== 'auto')
            ? this.getAxis(dim) : this.getBaseAxis();
        return {
            baseAxes: [baseAxis],
            otherAxes: [this.getOtherAxis(baseAxis)]
        };
    },

    /**
     * Convert a single data item to (x, y) point.
     * Parameter data is an array which the first element is radius and the second is angle
     * @param {Array.<number>} data
     * @param {boolean} [clamp=false]
     * @return {Array.<number>}
     */
    dataToPoint: function (data, clamp) {
        return this.coordToPoint([
            this._radiusAxis.dataToRadius(data[0], clamp),
            this._angleAxis.dataToAngle(data[1], clamp)
        ]);
    },

    /**
     * Convert a (x, y) point to data
     * @param {Array.<number>} point
     * @param {boolean} [clamp=false]
     * @return {Array.<number>}
     */
    pointToData: function (point, clamp) {
        var coord = this.pointToCoord(point);
        return [
            this._radiusAxis.radiusToData(coord[0], clamp),
            this._angleAxis.angleToData(coord[1], clamp)
        ];
    },

    /**
     * Convert a (x, y) point to (radius, angle) coord
     * @param {Array.<number>} point
     * @return {Array.<number>}
     */
    pointToCoord: function (point) {
        var dx = point[0] - this.cx;
        var dy = point[1] - this.cy;
        var angleAxis = this.getAngleAxis();
        var extent = angleAxis.getExtent();
        var minAngle = Math.min(extent[0], extent[1]);
        var maxAngle = Math.max(extent[0], extent[1]);
        // Fix fixed extent in polarCreator
        // FIXME
        angleAxis.inverse
            ? (minAngle = maxAngle - 360)
            : (maxAngle = minAngle + 360);

        var radius = Math.sqrt(dx * dx + dy * dy);
        dx /= radius;
        dy /= radius;

        var radian = Math.atan2(-dy, dx) / Math.PI * 180;

        // move to angleExtent
        var dir = radian < minAngle ? 1 : -1;
        while (radian < minAngle || radian > maxAngle) {
            radian += dir * 360;
        }

        return [radius, radian];
    },

    /**
     * Convert a (radius, angle) coord to (x, y) point
     * @param {Array.<number>} coord
     * @return {Array.<number>}
     */
    coordToPoint: function (coord) {
        var radius = coord[0];
        var radian = coord[1] / 180 * Math.PI;
        var x = Math.cos(radian) * radius + this.cx;
        // Inverse the y
        var y = -Math.sin(radian) * radius + this.cy;

        return [x, y];
    },

    /**
     * Get ring area of cartesian.
     * Area will have a contain function to determine if a point is in the coordinate system.
     * @return {Ring}
     */
    getArea: function () {

        var angleAxis = this.getAngleAxis();
        var radiusAxis = this.getRadiusAxis();

        var radiusExtent = radiusAxis.getExtent().slice();
        radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse();
        var angleExtent = angleAxis.getExtent();

        var RADIAN = Math.PI / 180;

        return {
            cx: this.cx,
            cy: this.cy,
            r0: radiusExtent[0],
            r: radiusExtent[1],
            startAngle: -angleExtent[0] * RADIAN,
            endAngle: -angleExtent[1] * RADIAN,
            clockwise: angleAxis.inverse,
            contain: function (x, y) {
                // It's a ring shape.
                // Start angle and end angle don't matter
                var dx = x - this.cx;
                var dy = y - this.cy;
                var d2 = dx * dx + dy * dy;
                var r = this.r;
                var r0 = this.r0;

                return d2 <= r * r && d2 >= r0 * r0;
            }
        };
    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PolarAxisModel = ComponentModel.extend({

    type: 'polarAxis',

    /**
     * @type {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
     */
    axis: null,

    /**
     * @override
     */
    getCoordSysModel: function () {
        return this.ecModel.queryComponents({
            mainType: 'polar',
            index: this.option.polarIndex,
            id: this.option.polarId
        })[0];
    }

});

merge(PolarAxisModel.prototype, axisModelCommonMixin);

var polarAxisDefaultExtendedOption = {
    angle: {
        // polarIndex: 0,
        // polarId: '',

        startAngle: 90,

        clockwise: true,

        splitNumber: 12,

        axisLabel: {
            rotate: false
        }
    },
    radius: {
        // polarIndex: 0,
        // polarId: '',

        splitNumber: 5
    }
};

function getAxisType$3(axisDim, option) {
    // Default axis with data is category axis
    return option.type || (option.data ? 'category' : 'value');
}

axisModelCreator('angle', PolarAxisModel, getAxisType$3, polarAxisDefaultExtendedOption.angle);
axisModelCreator('radius', PolarAxisModel, getAxisType$3, polarAxisDefaultExtendedOption.radius);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentModel({

    type: 'polar',

    dependencies: ['polarAxis', 'angleAxis'],

    /**
     * @type {module:echarts/coord/polar/Polar}
     */
    coordinateSystem: null,

    /**
     * @param {string} axisType
     * @return {module:echarts/coord/polar/AxisModel}
     */
    findAxisModel: function (axisType) {
        var foundAxisModel;
        var ecModel = this.ecModel;

        ecModel.eachComponent(axisType, function (axisModel) {
            if (axisModel.getCoordSysModel() === this) {
                foundAxisModel = axisModel;
            }
        }, this);
        return foundAxisModel;
    },

    defaultOption: {

        zlevel: 0,

        z: 0,

        center: ['50%', '50%'],

        radius: '80%'
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO Axis scale

/**
 * Resize method bound to the polar
 * @param {module:echarts/coord/polar/PolarModel} polarModel
 * @param {module:echarts/ExtensionAPI} api
 */
function resizePolar(polar, polarModel, api) {
    var center = polarModel.get('center');
    var width = api.getWidth();
    var height = api.getHeight();

    polar.cx = parsePercent$1(center[0], width);
    polar.cy = parsePercent$1(center[1], height);

    var radiusAxis = polar.getRadiusAxis();
    var size = Math.min(width, height) / 2;

    var radius = polarModel.get('radius');
    if (radius == null) {
        radius = [0, '100%'];
    }
    else if (!isArray(radius)) {
        // r0 = 0
        radius = [0, radius];
    }
    radius = [
        parsePercent$1(radius[0], size),
        parsePercent$1(radius[1], size)
    ];

    radiusAxis.inverse
        ? radiusAxis.setExtent(radius[1], radius[0])
        : radiusAxis.setExtent(radius[0], radius[1]);
}

/**
 * Update polar
 */
function updatePolarScale(ecModel, api) {
    var polar = this;
    var angleAxis = polar.getAngleAxis();
    var radiusAxis = polar.getRadiusAxis();
    // Reset scale
    angleAxis.scale.setExtent(Infinity, -Infinity);
    radiusAxis.scale.setExtent(Infinity, -Infinity);

    ecModel.eachSeries(function (seriesModel) {
        if (seriesModel.coordinateSystem === polar) {
            var data = seriesModel.getData();
            each$1(data.mapDimension('radius', true), function (dim) {
                radiusAxis.scale.unionExtentFromData(
                    data, getStackedDimension(data, dim)
                );
            });
            each$1(data.mapDimension('angle', true), function (dim) {
                angleAxis.scale.unionExtentFromData(
                    data, getStackedDimension(data, dim)
                );
            });
        }
    });

    niceScaleExtent(angleAxis.scale, angleAxis.model);
    niceScaleExtent(radiusAxis.scale, radiusAxis.model);

    // Fix extent of category angle axis
    if (angleAxis.type === 'category' && !angleAxis.onBand) {
        var extent = angleAxis.getExtent();
        var diff = 360 / angleAxis.scale.count();
        angleAxis.inverse ? (extent[1] += diff) : (extent[1] -= diff);
        angleAxis.setExtent(extent[0], extent[1]);
    }
}

/**
 * Set common axis properties
 * @param {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
 * @param {module:echarts/coord/polar/AxisModel}
 * @inner
 */
function setAxis(axis, axisModel) {
    axis.type = axisModel.get('type');
    axis.scale = createScaleByModel(axisModel);
    axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category';
    axis.inverse = axisModel.get('inverse');

    if (axisModel.mainType === 'angleAxis') {
        axis.inverse ^= axisModel.get('clockwise');
        var startAngle = axisModel.get('startAngle');
        axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360));
    }

    // Inject axis instance
    axisModel.axis = axis;
    axis.model = axisModel;
}


var polarCreator = {

    dimensions: Polar.prototype.dimensions,

    create: function (ecModel, api) {
        var polarList = [];
        ecModel.eachComponent('polar', function (polarModel, idx) {
            var polar = new Polar(idx);
            // Inject resize and update method
            polar.update = updatePolarScale;

            var radiusAxis = polar.getRadiusAxis();
            var angleAxis = polar.getAngleAxis();

            var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
            var angleAxisModel = polarModel.findAxisModel('angleAxis');

            setAxis(radiusAxis, radiusAxisModel);
            setAxis(angleAxis, angleAxisModel);

            resizePolar(polar, polarModel, api);

            polarList.push(polar);

            polarModel.coordinateSystem = polar;
            polar.model = polarModel;
        });
        // Inject coordinateSystem to series
        ecModel.eachSeries(function (seriesModel) {
            if (seriesModel.get('coordinateSystem') === 'polar') {
                var polarModel = ecModel.queryComponents({
                    mainType: 'polar',
                    index: seriesModel.get('polarIndex'),
                    id: seriesModel.get('polarId')
                })[0];

                if (__DEV__) {
                    if (!polarModel) {
                        throw new Error(
                            'Polar "' + retrieve(
                                seriesModel.get('polarIndex'),
                                seriesModel.get('polarId'),
                                0
                            ) + '" not found'
                        );
                    }
                }
                seriesModel.coordinateSystem = polarModel.coordinateSystem;
            }
        });

        return polarList;
    }
};

CoordinateSystemManager.register('polar', polarCreator);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var elementList$1 = ['axisLine', 'axisLabel', 'axisTick', 'splitLine', 'splitArea'];

function getAxisLineShape(polar, rExtent, angle) {
    rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse());
    var start = polar.coordToPoint([rExtent[0], angle]);
    var end = polar.coordToPoint([rExtent[1], angle]);

    return {
        x1: start[0],
        y1: start[1],
        x2: end[0],
        y2: end[1]
    };
}

function getRadiusIdx(polar) {
    var radiusAxis = polar.getRadiusAxis();
    return radiusAxis.inverse ? 0 : 1;
}

// Remove the last tick which will overlap the first tick
function fixAngleOverlap(list) {
    var firstItem = list[0];
    var lastItem = list[list.length - 1];
    if (firstItem
        && lastItem
        && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4
    ) {
        list.pop();
    }
}

AxisView.extend({

    type: 'angleAxis',

    axisPointerClass: 'PolarAxisPointer',

    render: function (angleAxisModel, ecModel) {
        this.group.removeAll();
        if (!angleAxisModel.get('show')) {
            return;
        }

        var angleAxis = angleAxisModel.axis;
        var polar = angleAxis.polar;
        var radiusExtent = polar.getRadiusAxis().getExtent();

        var ticksAngles = angleAxis.getTicksCoords();
        var labels = map(angleAxis.getViewLabels(), function (labelItem) {
            var labelItem = clone(labelItem);
            labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
            return labelItem;
        });

        fixAngleOverlap(labels);
        fixAngleOverlap(ticksAngles);

        each$1(elementList$1, function (name) {
            if (angleAxisModel.get(name + '.show')
                && (!angleAxis.scale.isBlank() || name === 'axisLine')
            ) {
                this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent, labels);
            }
        }, this);
    },

    /**
     * @private
     */
    _axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
        var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle');

        // extent id of the axis radius (r0 and r)
        var rId = getRadiusIdx(polar);
        var r0Id = rId ? 0 : 1;

        var shape;
        if (radiusExtent[r0Id] === 0) {
            shape = new Circle({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: radiusExtent[rId]
                },
                style: lineStyleModel.getLineStyle(),
                z2: 1,
                silent: true
            });
        }
        else {
            shape = new Ring({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: radiusExtent[rId],
                    r0: radiusExtent[r0Id]
                },
                style: lineStyleModel.getLineStyle(),
                z2: 1,
                silent: true
            });
        }
        shape.style.fill = null;
        this.group.add(shape);
    },

    /**
     * @private
     */
    _axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
        var tickModel = angleAxisModel.getModel('axisTick');

        var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
        var radius = radiusExtent[getRadiusIdx(polar)];

        var lines = map(ticksAngles, function (tickAngleItem) {
            return new Line({
                shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
            });
        });
        this.group.add(mergePath(
            lines, {
                style: defaults(
                    tickModel.getModel('lineStyle').getLineStyle(),
                    {
                        stroke: angleAxisModel.get('axisLine.lineStyle.color')
                    }
                )
            }
        ));
    },

    /**
     * @private
     */
    _axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent, labels) {
        var rawCategoryData = angleAxisModel.getCategories(true);

        var commonLabelModel = angleAxisModel.getModel('axisLabel');

        var labelMargin = commonLabelModel.get('margin');
        var triggerEvent = angleAxisModel.get('triggerEvent');

        // Use length of ticksAngles because it may remove the last tick to avoid overlapping
        each$1(labels, function (labelItem, idx) {
            var labelModel = commonLabelModel;
            var tickValue = labelItem.tickValue;

            var r = radiusExtent[getRadiusIdx(polar)];
            var p = polar.coordToPoint([r + labelMargin, labelItem.coord]);
            var cx = polar.cx;
            var cy = polar.cy;

            var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3
                ? 'center' : (p[0] > cx ? 'left' : 'right');
            var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3
                ? 'middle' : (p[1] > cy ? 'top' : 'bottom');

            if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
                labelModel = new Model(
                    rawCategoryData[tickValue].textStyle, commonLabelModel, commonLabelModel.ecModel
                );
            }

            var textEl = new Text({
                silent: AxisBuilder.isLabelSilent(angleAxisModel)
            });
            this.group.add(textEl);
            setTextStyle(textEl.style, labelModel, {
                x: p[0],
                y: p[1],
                textFill: labelModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'),
                text: labelItem.formattedLabel,
                textAlign: labelTextAlign,
                textVerticalAlign: labelTextVerticalAlign
            });

            // Pack data for mouse event
            if (triggerEvent) {
                textEl.eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel);
                textEl.eventData.targetType = 'axisLabel';
                textEl.eventData.value = labelItem.rawLabel;
            }

        }, this);
    },

    /**
     * @private
     */
    _splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
        var splitLineModel = angleAxisModel.getModel('splitLine');
        var lineStyleModel = splitLineModel.getModel('lineStyle');
        var lineColors = lineStyleModel.get('color');
        var lineCount = 0;

        lineColors = lineColors instanceof Array ? lineColors : [lineColors];

        var splitLines = [];

        for (var i = 0; i < ticksAngles.length; i++) {
            var colorIndex = (lineCount++) % lineColors.length;
            splitLines[colorIndex] = splitLines[colorIndex] || [];
            splitLines[colorIndex].push(new Line({
                shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
            }));
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (var i = 0; i < splitLines.length; i++) {
            this.group.add(mergePath(splitLines[i], {
                style: defaults({
                    stroke: lineColors[i % lineColors.length]
                }, lineStyleModel.getLineStyle()),
                silent: true,
                z: angleAxisModel.get('z')
            }));
        }
    },

    /**
     * @private
     */
    _splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
        if (!ticksAngles.length) {
            return;
        }

        var splitAreaModel = angleAxisModel.getModel('splitArea');
        var areaStyleModel = splitAreaModel.getModel('areaStyle');
        var areaColors = areaStyleModel.get('color');
        var lineCount = 0;

        areaColors = areaColors instanceof Array ? areaColors : [areaColors];

        var splitAreas = [];

        var RADIAN = Math.PI / 180;
        var prevAngle = -ticksAngles[0].coord * RADIAN;
        var r0 = Math.min(radiusExtent[0], radiusExtent[1]);
        var r1 = Math.max(radiusExtent[0], radiusExtent[1]);

        var clockwise = angleAxisModel.get('clockwise');

        for (var i = 1; i < ticksAngles.length; i++) {
            var colorIndex = (lineCount++) % areaColors.length;
            splitAreas[colorIndex] = splitAreas[colorIndex] || [];
            splitAreas[colorIndex].push(new Sector({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r0: r0,
                    r: r1,
                    startAngle: prevAngle,
                    endAngle: -ticksAngles[i].coord * RADIAN,
                    clockwise: clockwise
                },
                silent: true
            }));
            prevAngle = -ticksAngles[i].coord * RADIAN;
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (var i = 0; i < splitAreas.length; i++) {
            this.group.add(mergePath(splitAreas[i], {
                style: defaults({
                    fill: areaColors[i % areaColors.length]
                }, areaStyleModel.getAreaStyle()),
                silent: true
            }));
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var axisBuilderAttrs$3 = [
    'axisLine', 'axisTickLabel', 'axisName'
];
var selfBuilderAttrs$1 = [
    'splitLine', 'splitArea'
];

AxisView.extend({

    type: 'radiusAxis',

    axisPointerClass: 'PolarAxisPointer',

    render: function (radiusAxisModel, ecModel) {
        this.group.removeAll();
        if (!radiusAxisModel.get('show')) {
            return;
        }
        var radiusAxis = radiusAxisModel.axis;
        var polar = radiusAxis.polar;
        var angleAxis = polar.getAngleAxis();
        var ticksCoords = radiusAxis.getTicksCoords();
        var axisAngle = angleAxis.getExtent()[0];
        var radiusExtent = radiusAxis.getExtent();

        var layout = layoutAxis(polar, radiusAxisModel, axisAngle);
        var axisBuilder = new AxisBuilder(radiusAxisModel, layout);
        each$1(axisBuilderAttrs$3, axisBuilder.add, axisBuilder);
        this.group.add(axisBuilder.getGroup());

        each$1(selfBuilderAttrs$1, function (name) {
            if (radiusAxisModel.get(name + '.show') && !radiusAxis.scale.isBlank()) {
                this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords);
            }
        }, this);
    },

    /**
     * @private
     */
    _splitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
        var splitLineModel = radiusAxisModel.getModel('splitLine');
        var lineStyleModel = splitLineModel.getModel('lineStyle');
        var lineColors = lineStyleModel.get('color');
        var lineCount = 0;

        lineColors = lineColors instanceof Array ? lineColors : [lineColors];

        var splitLines = [];

        for (var i = 0; i < ticksCoords.length; i++) {
            var colorIndex = (lineCount++) % lineColors.length;
            splitLines[colorIndex] = splitLines[colorIndex] || [];
            splitLines[colorIndex].push(new Circle({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: ticksCoords[i].coord
                },
                silent: true
            }));
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (var i = 0; i < splitLines.length; i++) {
            this.group.add(mergePath(splitLines[i], {
                style: defaults({
                    stroke: lineColors[i % lineColors.length],
                    fill: null
                }, lineStyleModel.getLineStyle()),
                silent: true
            }));
        }
    },

    /**
     * @private
     */
    _splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
        if (!ticksCoords.length) {
            return;
        }

        var splitAreaModel = radiusAxisModel.getModel('splitArea');
        var areaStyleModel = splitAreaModel.getModel('areaStyle');
        var areaColors = areaStyleModel.get('color');
        var lineCount = 0;

        areaColors = areaColors instanceof Array ? areaColors : [areaColors];

        var splitAreas = [];

        var prevRadius = ticksCoords[0].coord;
        for (var i = 1; i < ticksCoords.length; i++) {
            var colorIndex = (lineCount++) % areaColors.length;
            splitAreas[colorIndex] = splitAreas[colorIndex] || [];
            splitAreas[colorIndex].push(new Sector({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r0: prevRadius,
                    r: ticksCoords[i].coord,
                    startAngle: 0,
                    endAngle: Math.PI * 2
                },
                silent: true
            }));
            prevRadius = ticksCoords[i].coord;
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (var i = 0; i < splitAreas.length; i++) {
            this.group.add(mergePath(splitAreas[i], {
                style: defaults({
                    fill: areaColors[i % areaColors.length]
                }, areaStyleModel.getAreaStyle()),
                silent: true
            }));
        }
    }
});

/**
 * @inner
 */
function layoutAxis(polar, radiusAxisModel, axisAngle) {
    return {
        position: [polar.cx, polar.cy],
        rotation: axisAngle / 180 * Math.PI,
        labelDirection: -1,
        tickDirection: -1,
        nameDirection: 1,
        labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'),
        // Over splitLine and splitArea
        z2: 1
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PolarAxisPointer = BaseAxisPointer.extend({

    /**
     * @override
     */
    makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
        var axis = axisModel.axis;

        if (axis.dim === 'angle') {
            this.animationThreshold = Math.PI / 18;
        }

        var polar = axis.polar;
        var otherAxis = polar.getOtherAxis(axis);
        var otherExtent = otherAxis.getExtent();

        var coordValue;
        coordValue = axis['dataTo' + capitalFirst(axis.dim)](value);

        var axisPointerType = axisPointerModel.get('type');
        if (axisPointerType && axisPointerType !== 'none') {
            var elStyle = buildElStyle(axisPointerModel);
            var pointerOption = pointerShapeBuilder$2[axisPointerType](
                axis, polar, coordValue, otherExtent, elStyle
            );
            pointerOption.style = elStyle;
            elOption.graphicKey = pointerOption.type;
            elOption.pointer = pointerOption;
        }

        var labelMargin = axisPointerModel.get('label.margin');
        var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin);
        buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos);
    }

    // Do not support handle, utill any user requires it.

});

function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) {
    var axis = axisModel.axis;
    var coord = axis.dataToCoord(value);
    var axisAngle = polar.getAngleAxis().getExtent()[0];
    axisAngle = axisAngle / 180 * Math.PI;
    var radiusExtent = polar.getRadiusAxis().getExtent();
    var position;
    var align;
    var verticalAlign;

    if (axis.dim === 'radius') {
        var transform = create$1();
        rotate(transform, transform, axisAngle);
        translate(transform, transform, [polar.cx, polar.cy]);
        position = applyTransform$1([coord, -labelMargin], transform);

        var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0;
        var labelLayout = AxisBuilder.innerTextLayout(
            axisAngle, labelRotation * Math.PI / 180, -1
        );
        align = labelLayout.textAlign;
        verticalAlign = labelLayout.textVerticalAlign;
    }
    else { // angle axis
        var r = radiusExtent[1];
        position = polar.coordToPoint([r + labelMargin, coord]);
        var cx = polar.cx;
        var cy = polar.cy;
        align = Math.abs(position[0] - cx) / r < 0.3
            ? 'center' : (position[0] > cx ? 'left' : 'right');
        verticalAlign = Math.abs(position[1] - cy) / r < 0.3
            ? 'middle' : (position[1] > cy ? 'top' : 'bottom');
    }

    return {
        position: position,
        align: align,
        verticalAlign: verticalAlign
    };
}


var pointerShapeBuilder$2 = {

    line: function (axis, polar, coordValue, otherExtent, elStyle) {
        return axis.dim === 'angle'
            ? {
                type: 'Line',
                shape: makeLineShape(
                    polar.coordToPoint([otherExtent[0], coordValue]),
                    polar.coordToPoint([otherExtent[1], coordValue])
                )
            }
            : {
                type: 'Circle',
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: coordValue
                }
            };
    },

    shadow: function (axis, polar, coordValue, otherExtent, elStyle) {
        var bandWidth = Math.max(1, axis.getBandWidth());
        var radian = Math.PI / 180;

        return axis.dim === 'angle'
            ? {
                type: 'Sector',
                shape: makeSectorShape(
                    polar.cx, polar.cy,
                    otherExtent[0], otherExtent[1],
                    // In ECharts y is negative if angle is positive
                    (-coordValue - bandWidth / 2) * radian,
                    (-coordValue + bandWidth / 2) * radian
                )
            }
            : {
                type: 'Sector',
                shape: makeSectorShape(
                    polar.cx, polar.cy,
                    coordValue - bandWidth / 2,
                    coordValue + bandWidth / 2,
                    0, Math.PI * 2
                )
            };
    }
};

AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// For reducing size of echarts.min, barLayoutPolar is required by polar.
registerLayout(curry(barLayoutPolar, 'bar'));

// Polar view
extendComponentView({
    type: 'polar'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var GeoModel = ComponentModel.extend({

    type: 'geo',

    /**
     * @type {module:echarts/coord/geo/Geo}
     */
    coordinateSystem: null,

    layoutMode: 'box',

    init: function (option) {
        ComponentModel.prototype.init.apply(this, arguments);

        // Default label emphasis `show`
        defaultEmphasis(option, 'label', ['show']);
    },

    optionUpdated: function () {
        var option = this.option;
        var self = this;

        option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap);

        this._optionModelMap = reduce(option.regions || [], function (optionModelMap, regionOpt) {
            if (regionOpt.name) {
                optionModelMap.set(regionOpt.name, new Model(regionOpt, self));
            }
            return optionModelMap;
        }, createHashMap());

        this.updateSelectedMap(option.regions);
    },

    defaultOption: {

        zlevel: 0,

        z: 0,

        show: true,

        left: 'center',

        top: 'center',


        // width:,
        // height:,
        // right
        // bottom

        // Aspect is width / height. Inited to be geoJson bbox aspect
        // This parameter is used for scale this aspect
        // If svg used, aspectScale is 1 by default.
        // aspectScale: 0.75,
        aspectScale: null,

        ///// Layout with center and size
        // If you wan't to put map in a fixed size box with right aspect ratio
        // This two properties may more conveninet
        // layoutCenter: [50%, 50%]
        // layoutSize: 100

        silent: false,

        // Map type
        map: '',

        // Define left-top, right-bottom coords to control view
        // For example, [ [180, 90], [-180, -90] ]
        boundingCoords: null,

        // Default on center of map
        center: null,

        zoom: 1,

        scaleLimit: null,

        // selectedMode: false

        label: {
            show: false,
            color: '#000'
        },

        itemStyle: {
            // color: 各异,
            borderWidth: 0.5,
            borderColor: '#444',
            color: '#eee'
        },

        emphasis: {
            label: {
                show: true,
                color: 'rgb(100,0,0)'
            },
            itemStyle: {
                color: 'rgba(255,215,0,0.8)'
            }
        },

        regions: []
    },

    /**
     * Get model of region
     * @param  {string} name
     * @return {module:echarts/model/Model}
     */
    getRegionModel: function (name) {
        return this._optionModelMap.get(name) || new Model(null, this, this.ecModel);
    },

    /**
     * Format label
     * @param {string} name Region name
     * @param {string} [status='normal'] 'normal' or 'emphasis'
     * @return {string}
     */
    getFormattedLabel: function (name, status) {
        var regionModel = this.getRegionModel(name);
        var formatter = regionModel.get(
            'label'
            + (status === 'normal' ? '.' : status + '.')
            + 'formatter'
        );
        var params = {
            name: name
        };
        if (typeof formatter === 'function') {
            params.status = status;
            return formatter(params);
        }
        else if (typeof formatter === 'string') {
            return formatter.replace('{a}', name != null ? name : '');
        }
    },

    setZoom: function (zoom) {
        this.option.zoom = zoom;
    },

    setCenter: function (center) {
        this.option.center = center;
    }
});

mixin(GeoModel, selectableMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentView({

    type: 'geo',

    init: function (ecModel, api) {
        var mapDraw = new MapDraw(api, true);
        this._mapDraw = mapDraw;

        this.group.add(mapDraw.group);
    },

    render: function (geoModel, ecModel, api, payload) {
        // Not render if it is an toggleSelect action from self
        if (payload && payload.type === 'geoToggleSelect'
            && payload.from === this.uid
        ) {
            return;
        }

        var mapDraw = this._mapDraw;
        if (geoModel.get('show')) {
            mapDraw.draw(geoModel, ecModel, api, this, payload);
        }
        else {
            this._mapDraw.group.removeAll();
        }

        this.group.silent = geoModel.get('silent');
    },

    dispose: function () {
        this._mapDraw && this._mapDraw.remove();
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function makeAction(method, actionInfo) {
    actionInfo.update = 'updateView';
    registerAction(actionInfo, function (payload, ecModel) {
        var selected = {};

        ecModel.eachComponent(
            { mainType: 'geo', query: payload},
            function (geoModel) {
                geoModel[method](payload.name);
                var geo = geoModel.coordinateSystem;
                each$1(geo.regions, function (region) {
                    selected[region.name] = geoModel.isSelected(region.name) || false;
                });
            }
        );

        return {
            selected: selected,
            name: payload.name
        };
    });
}

makeAction('toggleSelected', {
    type: 'geoToggleSelect',
    event: 'geoselectchanged'
});
makeAction('select', {
    type: 'geoSelect',
    event: 'geoselected'
});
makeAction('unSelect', {
    type: 'geoUnSelect',
    event: 'geounselected'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// (24*60*60*1000)
var PROXIMATE_ONE_DAY = 86400000;

/**
 * Calendar
 *
 * @constructor
 *
 * @param {Object} calendarModel calendarModel
 * @param {Object} ecModel       ecModel
 * @param {Object} api           api
 */
function Calendar(calendarModel, ecModel, api) {
    this._model = calendarModel;
}

Calendar.prototype = {

    constructor: Calendar,

    type: 'calendar',

    dimensions: ['time', 'value'],

    // Required in createListFromData
    getDimensionsInfo: function () {
        return [{name: 'time', type: 'time'}, 'value'];
    },

    getRangeInfo: function () {
        return this._rangeInfo;
    },

    getModel: function () {
        return this._model;
    },

    getRect: function () {
        return this._rect;
    },

    getCellWidth: function () {
        return this._sw;
    },

    getCellHeight: function () {
        return this._sh;
    },

    getOrient: function () {
        return this._orient;
    },

    /**
     * getFirstDayOfWeek
     *
     * @example
     *     0 : start at Sunday
     *     1 : start at Monday
     *
     * @return {number}
     */
    getFirstDayOfWeek: function () {
        return this._firstDayOfWeek;
    },

    /**
     * get date info
     *
     * @param  {string|number} date date
     * @return {Object}
     * {
     *      y: string, local full year, eg., '1940',
     *      m: string, local month, from '01' ot '12',
     *      d: string, local date, from '01' to '31' (if exists),
     *      day: It is not date.getDay(). It is the location of the cell in a week, from 0 to 6,
     *      time: timestamp,
     *      formatedDate: string, yyyy-MM-dd,
     *      date: original date object.
     * }
     */
    getDateInfo: function (date) {

        date = parseDate(date);

        var y = date.getFullYear();

        var m = date.getMonth() + 1;
        m = m < 10 ? '0' + m : m;

        var d = date.getDate();
        d = d < 10 ? '0' + d : d;

        var day = date.getDay();

        day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7);

        return {
            y: y,
            m: m,
            d: d,
            day: day,
            time: date.getTime(),
            formatedDate: y + '-' + m + '-' + d,
            date: date
        };
    },

    getNextNDay: function (date, n) {
        n = n || 0;
        if (n === 0) {
            return this.getDateInfo(date);
        }

        date = new Date(this.getDateInfo(date).time);
        date.setDate(date.getDate() + n);

        return this.getDateInfo(date);
    },

    update: function (ecModel, api) {

        this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay');
        this._orient = this._model.get('orient');
        this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0;


        this._rangeInfo = this._getRangeInfo(this._initRangeOption());
        var weeks = this._rangeInfo.weeks || 1;
        var whNames = ['width', 'height'];
        var cellSize = this._model.get('cellSize').slice();
        var layoutParams = this._model.getBoxLayoutParams();
        var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks];

        each$1([0, 1], function (idx) {
            if (cellSizeSpecified(cellSize, idx)) {
                layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx];
            }
        });

        var whGlobal = {
            width: api.getWidth(),
            height: api.getHeight()
        };
        var calendarRect = this._rect = getLayoutRect(layoutParams, whGlobal);

        each$1([0, 1], function (idx) {
            if (!cellSizeSpecified(cellSize, idx)) {
                cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx];
            }
        });

        function cellSizeSpecified(cellSize, idx) {
            return cellSize[idx] != null && cellSize[idx] !== 'auto';
        }

        this._sw = cellSize[0];
        this._sh = cellSize[1];
    },


    /**
     * Convert a time data(time, value) item to (x, y) point.
     *
     * @override
     * @param  {Array|number} data data
     * @param  {boolean} [clamp=true] out of range
     * @return {Array} point
     */
    dataToPoint: function (data, clamp) {
        isArray(data) && (data = data[0]);
        clamp == null && (clamp = true);

        var dayInfo = this.getDateInfo(data);
        var range = this._rangeInfo;
        var date = dayInfo.formatedDate;

        // if not in range return [NaN, NaN]
        if (clamp && !(
            dayInfo.time >= range.start.time
            && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY
        )) {
            return [NaN, NaN];
        }

        var week = dayInfo.day;
        var nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek;

        if (this._orient === 'vertical') {
            return [
                this._rect.x + week * this._sw + this._sw / 2,
                this._rect.y + nthWeek * this._sh + this._sh / 2
            ];

        }

        return [
            this._rect.x + nthWeek * this._sw + this._sw / 2,
            this._rect.y + week * this._sh + this._sh / 2
        ];

    },

    /**
     * Convert a (x, y) point to time data
     *
     * @override
     * @param  {string} point point
     * @return {string}       data
     */
    pointToData: function (point) {

        var date = this.pointToDate(point);

        return date && date.time;
    },

    /**
     * Convert a time date item to (x, y) four point.
     *
     * @param  {Array} data  date[0] is date
     * @param  {boolean} [clamp=true]  out of range
     * @return {Object}       point
     */
    dataToRect: function (data, clamp) {
        var point = this.dataToPoint(data, clamp);

        return {
            contentShape: {
                x: point[0] - (this._sw - this._lineWidth) / 2,
                y: point[1] - (this._sh - this._lineWidth) / 2,
                width: this._sw - this._lineWidth,
                height: this._sh - this._lineWidth
            },

            center: point,

            tl: [
                point[0] - this._sw / 2,
                point[1] - this._sh / 2
            ],

            tr: [
                point[0] + this._sw / 2,
                point[1] - this._sh / 2
            ],

            br: [
                point[0] + this._sw / 2,
                point[1] + this._sh / 2
            ],

            bl: [
                point[0] - this._sw / 2,
                point[1] + this._sh / 2
            ]

        };
    },

    /**
     * Convert a (x, y) point to time date
     *
     * @param  {Array} point point
     * @return {Object}       date
     */
    pointToDate: function (point) {
        var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1;
        var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1;
        var range = this._rangeInfo.range;

        if (this._orient === 'vertical') {
            return this._getDateByWeeksAndDay(nthY, nthX - 1, range);
        }

        return this._getDateByWeeksAndDay(nthX, nthY - 1, range);
    },

    /**
     * @inheritDoc
     */
    convertToPixel: curry(doConvert$2, 'dataToPoint'),

    /**
     * @inheritDoc
     */
    convertFromPixel: curry(doConvert$2, 'pointToData'),

    /**
     * initRange
     *
     * @private
     * @return {Array} [start, end]
     */
    _initRangeOption: function () {
        var range = this._model.get('range');

        var rg = range;

        if (isArray(rg) && rg.length === 1) {
            rg = rg[0];
        }

        if (/^\d{4}$/.test(rg)) {
            range = [rg + '-01-01', rg + '-12-31'];
        }

        if (/^\d{4}[\/|-]\d{1,2}$/.test(rg)) {

            var start = this.getDateInfo(rg);
            var firstDay = start.date;
            firstDay.setMonth(firstDay.getMonth() + 1);

            var end = this.getNextNDay(firstDay, -1);
            range = [start.formatedDate, end.formatedDate];
        }

        if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rg)) {
            range = [rg, rg];
        }

        var tmp = this._getRangeInfo(range);

        if (tmp.start.time > tmp.end.time) {
            range.reverse();
        }

        return range;
    },

    /**
     * range info
     *
     * @private
     * @param  {Array} range range ['2017-01-01', '2017-07-08']
     *  If range[0] > range[1], they will not be reversed.
     * @return {Object}       obj
     */
    _getRangeInfo: function (range) {
        range = [
            this.getDateInfo(range[0]),
            this.getDateInfo(range[1])
        ];

        var reversed;
        if (range[0].time > range[1].time) {
            reversed = true;
            range.reverse();
        }

        var allDay = Math.floor(range[1].time / PROXIMATE_ONE_DAY)
            - Math.floor(range[0].time / PROXIMATE_ONE_DAY) + 1;

        // Consider case:
        // Firstly set system timezone as "Time Zone: America/Toronto",
        // ```
        // var first = new Date(1478412000000 - 3600 * 1000 * 2.5);
        // var second = new Date(1478412000000);
        // var allDays = Math.floor(second / ONE_DAY) - Math.floor(first / ONE_DAY) + 1;
        // ```
        // will get wrong result because of DST. So we should fix it.
        var date = new Date(range[0].time);
        var startDateNum = date.getDate();
        var endDateNum = range[1].date.getDate();
        date.setDate(startDateNum + allDay - 1);
        // The bias can not over a month, so just compare date.
        if (date.getDate() !== endDateNum) {
            var sign = date.getTime() - range[1].time > 0 ? 1 : -1;
            while (date.getDate() !== endDateNum && (date.getTime() - range[1].time) * sign > 0) {
                allDay -= sign;
                date.setDate(startDateNum + allDay - 1);
            }
        }

        var weeks = Math.floor((allDay + range[0].day + 6) / 7);
        var nthWeek = reversed ? -weeks + 1 : weeks - 1;

        reversed && range.reverse();

        return {
            range: [range[0].formatedDate, range[1].formatedDate],
            start: range[0],
            end: range[1],
            allDay: allDay,
            weeks: weeks,
            // From 0.
            nthWeek: nthWeek,
            fweek: range[0].day,
            lweek: range[1].day
        };
    },

    /**
     * get date by nthWeeks and week day in range
     *
     * @private
     * @param  {number} nthWeek the week
     * @param  {number} day   the week day
     * @param  {Array} range [d1, d2]
     * @return {Object}
     */
    _getDateByWeeksAndDay: function (nthWeek, day, range) {
        var rangeInfo = this._getRangeInfo(range);

        if (nthWeek > rangeInfo.weeks
            || (nthWeek === 0 && day < rangeInfo.fweek)
            || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek)
        ) {
            return false;
        }

        var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day;
        var date = new Date(rangeInfo.start.time);
        date.setDate(rangeInfo.start.d + nthDay);

        return this.getDateInfo(date);
    }
};

Calendar.dimensions = Calendar.prototype.dimensions;

Calendar.getDimensionsInfo = Calendar.prototype.getDimensionsInfo;

Calendar.create = function (ecModel, api) {
    var calendarList = [];

    ecModel.eachComponent('calendar', function (calendarModel) {
        var calendar = new Calendar(calendarModel, ecModel, api);
        calendarList.push(calendar);
        calendarModel.coordinateSystem = calendar;
    });

    ecModel.eachSeries(function (calendarSeries) {
        if (calendarSeries.get('coordinateSystem') === 'calendar') {
            // Inject coordinate system
            calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
        }
    });
    return calendarList;
};

function doConvert$2(methodName, ecModel, finder, value) {
    var calendarModel = finder.calendarModel;
    var seriesModel = finder.seriesModel;

    var coordSys = calendarModel
        ? calendarModel.coordinateSystem
        : seriesModel
        ? seriesModel.coordinateSystem
        : null;

    return coordSys === this ? coordSys[methodName](value) : null;
}

CoordinateSystemManager.register('calendar', Calendar);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var CalendarModel = ComponentModel.extend({

    type: 'calendar',

    /**
     * @type {module:echarts/coord/calendar/Calendar}
     */
    coordinateSystem: null,

    defaultOption: {
        zlevel: 0,
        z: 2,
        left: 80,
        top: 60,

        cellSize: 20,

        // horizontal vertical
        orient: 'horizontal',

        // month separate line style
        splitLine: {
            show: true,
            lineStyle: {
                color: '#000',
                width: 1,
                type: 'solid'
            }
        },

        // rect style  temporarily unused emphasis
        itemStyle: {
            color: '#fff',
            borderWidth: 1,
            borderColor: '#ccc'
        },

        // week text style
        dayLabel: {
            show: true,

            // a week first day
            firstDay: 0,

            // start end
            position: 'start',
            margin: '50%', // 50% of cellSize
            nameMap: 'en',
            color: '#000'
        },

        // month text style
        monthLabel: {
            show: true,

            // start end
            position: 'start',
            margin: 5,

            // center or left
            align: 'center',

            // cn en []
            nameMap: 'en',
            formatter: null,
            color: '#000'
        },

        // year text style
        yearLabel: {
            show: true,

            // top bottom left right
            position: null,
            margin: 30,
            formatter: null,
            color: '#ccc',
            fontFamily: 'sans-serif',
            fontWeight: 'bolder',
            fontSize: 20
        }
    },

    /**
     * @override
     */
    init: function (option, parentModel, ecModel, extraOpt) {
        var inputPositionParams = getLayoutParams(option);

        CalendarModel.superApply(this, 'init', arguments);

        mergeAndNormalizeLayoutParams(option, inputPositionParams);
    },

    /**
     * @override
     */
    mergeOption: function (option, extraOpt) {
        CalendarModel.superApply(this, 'mergeOption', arguments);

        mergeAndNormalizeLayoutParams(this.option, option);
    }
});

function mergeAndNormalizeLayoutParams(target, raw) {
    // Normalize cellSize
    var cellSize = target.cellSize;

    if (!isArray(cellSize)) {
        cellSize = target.cellSize = [cellSize, cellSize];
    }
    else if (cellSize.length === 1) {
        cellSize[1] = cellSize[0];
    }

    var ignoreSize = map([0, 1], function (hvIdx) {
        // If user have set `width` or both `left` and `right`, cellSize
        // will be automatically set to 'auto', otherwise the default
        // setting of cellSize will make `width` setting not work.
        if (sizeCalculable(raw, hvIdx)) {
            cellSize[hvIdx] = 'auto';
        }
        return cellSize[hvIdx] != null && cellSize[hvIdx] !== 'auto';
    });

    mergeLayoutParam(target, raw, {
        type: 'box', ignoreSize: ignoreSize
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var MONTH_TEXT = {
    EN: [
        'Jan', 'Feb', 'Mar',
        'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep',
        'Oct', 'Nov', 'Dec'
    ],
    CN: [
        '一月', '二月', '三月',
        '四月', '五月', '六月',
        '七月', '八月', '九月',
        '十月', '十一月', '十二月'
    ]
};

var WEEK_TEXT = {
    EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    CN: ['日', '一', '二', '三', '四', '五', '六']
};

extendComponentView({

    type: 'calendar',

    /**
     * top/left line points
     *  @private
     */
    _tlpoints: null,

    /**
     * bottom/right line points
     *  @private
     */
    _blpoints: null,

    /**
     * first day of month
     *  @private
     */
    _firstDayOfMonth: null,

    /**
     * first day point of month
     *  @private
     */
    _firstDayPoints: null,

    render: function (calendarModel, ecModel, api) {

        var group = this.group;

        group.removeAll();

        var coordSys = calendarModel.coordinateSystem;

        // range info
        var rangeData = coordSys.getRangeInfo();
        var orient = coordSys.getOrient();

        this._renderDayRect(calendarModel, rangeData, group);

        // _renderLines must be called prior to following function
        this._renderLines(calendarModel, rangeData, orient, group);

        this._renderYearText(calendarModel, rangeData, orient, group);

        this._renderMonthText(calendarModel, orient, group);

        this._renderWeekText(calendarModel, rangeData, orient, group);
    },

    // render day rect
    _renderDayRect: function (calendarModel, rangeData, group) {
        var coordSys = calendarModel.coordinateSystem;
        var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle();
        var sw = coordSys.getCellWidth();
        var sh = coordSys.getCellHeight();

        for (var i = rangeData.start.time;
            i <= rangeData.end.time;
            i = coordSys.getNextNDay(i, 1).time
        ) {

            var point = coordSys.dataToRect([i], false).tl;

            // every rect
            var rect = new Rect({
                shape: {
                    x: point[0],
                    y: point[1],
                    width: sw,
                    height: sh
                },
                cursor: 'default',
                style: itemRectStyleModel
            });

            group.add(rect);
        }

    },

    // render separate line
    _renderLines: function (calendarModel, rangeData, orient, group) {

        var self = this;

        var coordSys = calendarModel.coordinateSystem;

        var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
        var show = calendarModel.get('splitLine.show');

        var lineWidth = lineStyleModel.lineWidth;

        this._tlpoints = [];
        this._blpoints = [];
        this._firstDayOfMonth = [];
        this._firstDayPoints = [];


        var firstDay = rangeData.start;

        for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
            addPoints(firstDay.formatedDate);

            if (i === 0) {
                firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
            }

            var date = firstDay.date;
            date.setMonth(date.getMonth() + 1);
            firstDay = coordSys.getDateInfo(date);
        }

        addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);

        function addPoints(date) {

            self._firstDayOfMonth.push(coordSys.getDateInfo(date));
            self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);

            var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);

            self._tlpoints.push(points[0]);
            self._blpoints.push(points[points.length - 1]);

            show && self._drawSplitline(points, lineStyleModel, group);
        }


        // render top/left line
        show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);

        // render bottom/right line
        show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);

    },

    // get points at both ends
    _getEdgesPoints: function (points, lineWidth, orient) {
        var rs = [points[0].slice(), points[points.length - 1].slice()];
        var idx = orient === 'horizontal' ? 0 : 1;

        // both ends of the line are extend half lineWidth
        rs[0][idx] = rs[0][idx] - lineWidth / 2;
        rs[1][idx] = rs[1][idx] + lineWidth / 2;

        return rs;
    },

    // render split line
    _drawSplitline: function (points, lineStyleModel, group) {

        var poyline = new Polyline({
            z2: 20,
            shape: {
                points: points
            },
            style: lineStyleModel
        });

        group.add(poyline);
    },

    // render month line of one week points
    _getLinePointsOfOneWeek: function (calendarModel, date, orient) {

        var coordSys = calendarModel.coordinateSystem;
        date = coordSys.getDateInfo(date);

        var points = [];

        for (var i = 0; i < 7; i++) {

            var tmpD = coordSys.getNextNDay(date.time, i);
            var point = coordSys.dataToRect([tmpD.time], false);

            points[2 * tmpD.day] = point.tl;
            points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
        }

        return points;

    },

    _formatterLabel: function (formatter, params) {

        if (typeof formatter === 'string' && formatter) {
            return formatTplSimple(formatter, params);
        }

        if (typeof formatter === 'function') {
            return formatter(params);
        }

        return params.nameMap;

    },

    _yearTextPositionControl: function (textEl, point, orient, position, margin) {

        point = point.slice();
        var aligns = ['center', 'bottom'];

        if (position === 'bottom') {
            point[1] += margin;
            aligns = ['center', 'top'];
        }
        else if (position === 'left') {
            point[0] -= margin;
        }
        else if (position === 'right') {
            point[0] += margin;
            aligns = ['center', 'top'];
        }
        else { // top
            point[1] -= margin;
        }

        var rotate = 0;
        if (position === 'left' || position === 'right') {
            rotate = Math.PI / 2;
        }

        return {
            rotation: rotate,
            position: point,
            style: {
                textAlign: aligns[0],
                textVerticalAlign: aligns[1]
            }
        };
    },

    // render year
    _renderYearText: function (calendarModel, rangeData, orient, group) {
        var yearLabel = calendarModel.getModel('yearLabel');

        if (!yearLabel.get('show')) {
            return;
        }

        var margin = yearLabel.get('margin');
        var pos = yearLabel.get('position');

        if (!pos) {
            pos = orient !== 'horizontal' ? 'top' : 'left';
        }

        var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
        var xc = (points[0][0] + points[1][0]) / 2;
        var yc = (points[0][1] + points[1][1]) / 2;

        var idx = orient === 'horizontal' ? 0 : 1;

        var posPoints = {
            top: [xc, points[idx][1]],
            bottom: [xc, points[1 - idx][1]],
            left: [points[1 - idx][0], yc],
            right: [points[idx][0], yc]
        };

        var name = rangeData.start.y;

        if (+rangeData.end.y > +rangeData.start.y) {
            name = name + '-' + rangeData.end.y;
        }

        var formatter = yearLabel.get('formatter');

        var params = {
            start: rangeData.start.y,
            end: rangeData.end.y,
            nameMap: name
        };

        var content = this._formatterLabel(formatter, params);

        var yearText = new Text({z2: 30});
        setTextStyle(yearText.style, yearLabel, {text: content}),
        yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));

        group.add(yearText);
    },

    _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
        var align = 'left';
        var vAlign = 'top';
        var x = point[0];
        var y = point[1];

        if (orient === 'horizontal') {
            y = y + margin;

            if (isCenter) {
                align = 'center';
            }

            if (position === 'start') {
                vAlign = 'bottom';
            }
        }
        else {
            x = x + margin;

            if (isCenter) {
                vAlign = 'middle';
            }

            if (position === 'start') {
                align = 'right';
            }
        }

        return {
            x: x,
            y: y,
            textAlign: align,
            textVerticalAlign: vAlign
        };
    },

    // render month and year text
    _renderMonthText: function (calendarModel, orient, group) {
        var monthLabel = calendarModel.getModel('monthLabel');

        if (!monthLabel.get('show')) {
            return;
        }

        var nameMap = monthLabel.get('nameMap');
        var margin = monthLabel.get('margin');
        var pos = monthLabel.get('position');
        var align = monthLabel.get('align');

        var termPoints = [this._tlpoints, this._blpoints];

        if (isString(nameMap)) {
            nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
        }

        var idx = pos === 'start' ? 0 : 1;
        var axis = orient === 'horizontal' ? 0 : 1;
        margin = pos === 'start' ? -margin : margin;
        var isCenter = (align === 'center');

        for (var i = 0; i < termPoints[idx].length - 1; i++) {

            var tmp = termPoints[idx][i].slice();
            var firstDay = this._firstDayOfMonth[i];

            if (isCenter) {
                var firstDayPoints = this._firstDayPoints[i];
                tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
            }

            var formatter = monthLabel.get('formatter');
            var name = nameMap[+firstDay.m - 1];
            var params = {
                yyyy: firstDay.y,
                yy: (firstDay.y + '').slice(2),
                MM: firstDay.m,
                M: +firstDay.m,
                nameMap: name
            };

            var content = this._formatterLabel(formatter, params);

            var monthText = new Text({z2: 30});
            extend(
                setTextStyle(monthText.style, monthLabel, {text: content}),
                this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)
            );

            group.add(monthText);
        }
    },

    _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
        var align = 'center';
        var vAlign = 'middle';
        var x = point[0];
        var y = point[1];
        var isStart = position === 'start';

        if (orient === 'horizontal') {
            x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
            align = isStart ? 'right' : 'left';
        }
        else {
            y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
            vAlign = isStart ? 'bottom' : 'top';
        }

        return {
            x: x,
            y: y,
            textAlign: align,
            textVerticalAlign: vAlign
        };
    },

    // render weeks
    _renderWeekText: function (calendarModel, rangeData, orient, group) {
        var dayLabel = calendarModel.getModel('dayLabel');

        if (!dayLabel.get('show')) {
            return;
        }

        var coordSys = calendarModel.coordinateSystem;
        var pos = dayLabel.get('position');
        var nameMap = dayLabel.get('nameMap');
        var margin = dayLabel.get('margin');
        var firstDayOfWeek = coordSys.getFirstDayOfWeek();

        if (isString(nameMap)) {
            nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
        }

        var start = coordSys.getNextNDay(
            rangeData.end.time, (7 - rangeData.lweek)
        ).time;

        var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
        margin = parsePercent$1(margin, cellSize[orient === 'horizontal' ? 0 : 1]);

        if (pos === 'start') {
            start = coordSys.getNextNDay(
                rangeData.start.time, -(7 + rangeData.fweek)
            ).time;
            margin = -margin;
        }

        for (var i = 0; i < 7; i++) {

            var tmpD = coordSys.getNextNDay(start, i);
            var point = coordSys.dataToRect([tmpD.time], false).center;
            var day = i;
            day = Math.abs((i + firstDayOfWeek) % 7);
            var weekText = new Text({z2: 30});

            extend(
                setTextStyle(weekText.style, dayLabel, {text: nameMap[day]}),
                this._weekTextPositionControl(point, orient, pos, margin, cellSize)
            );
            group.add(weekText);
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var _nonShapeGraphicElements = {

    // Reserved but not supported in graphic component.
    path: null,
    compoundPath: null,

    // Supported in graphic component.
    group: Group,
    image: ZImage,
    text: Text
};

// -------------
// Preprocessor
// -------------

registerPreprocessor(function (option) {
    var graphicOption = option.graphic;

    // Convert
    // {graphic: [{left: 10, type: 'circle'}, ...]}
    // or
    // {graphic: {left: 10, type: 'circle'}}
    // to
    // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]}
    if (isArray(graphicOption)) {
        if (!graphicOption[0] || !graphicOption[0].elements) {
            option.graphic = [{elements: graphicOption}];
        }
        else {
            // Only one graphic instance can be instantiated. (We dont
            // want that too many views are created in echarts._viewMap)
            option.graphic = [option.graphic[0]];
        }
    }
    else if (graphicOption && !graphicOption.elements) {
        option.graphic = [{elements: [graphicOption]}];
    }
});

// ------
// Model
// ------

var GraphicModel = extendComponentModel({

    type: 'graphic',

    defaultOption: {

        // Extra properties for each elements:
        //
        // left/right/top/bottom: (like 12, '22%', 'center', default undefined)
        //      If left/rigth is set, shape.x/shape.cx/position will not be used.
        //      If top/bottom is set, shape.y/shape.cy/position will not be used.
        //      This mechanism is useful when you want to position a group/element
        //      against the right side or the center of this container.
        //
        // width/height: (can only be pixel value, default 0)
        //      Only be used to specify contianer(group) size, if needed. And
        //      can not be percentage value (like '33%'). See the reason in the
        //      layout algorithm below.
        //
        // bounding: (enum: 'all' (default) | 'raw')
        //      Specify how to calculate boundingRect when locating.
        //      'all': Get uioned and transformed boundingRect
        //          from both itself and its descendants.
        //          This mode simplies confining a group of elements in the bounding
        //          of their ancester container (e.g., using 'right: 0').
        //      'raw': Only use the boundingRect of itself and before transformed.
        //          This mode is similar to css behavior, which is useful when you
        //          want an element to be able to overflow its container. (Consider
        //          a rotated circle needs to be located in a corner.)
        // info: custom info. enables user to mount some info on elements and use them
        //      in event handlers. Update them only when user specified, otherwise, remain.

        // Note: elements is always behind its ancestors in this elements array.
        elements: [],
        parentId: null
    },

    /**
     * Save el options for the sake of the performance (only update modified graphics).
     * The order is the same as those in option. (ancesters -> descendants)
     *
     * @private
     * @type {Array.<Object>}
     */
    _elOptionsToUpdate: null,

    /**
     * @override
     */
    mergeOption: function (option) {
        // Prevent default merge to elements
        var elements = this.option.elements;
        this.option.elements = null;

        GraphicModel.superApply(this, 'mergeOption', arguments);

        this.option.elements = elements;
    },

    /**
     * @override
     */
    optionUpdated: function (newOption, isInit) {
        var thisOption = this.option;
        var newList = (isInit ? thisOption : newOption).elements;
        var existList = thisOption.elements = isInit ? [] : thisOption.elements;

        var flattenedList = [];
        this._flatten(newList, flattenedList);

        var mappingResult = mappingToExists(existList, flattenedList);
        makeIdAndName(mappingResult);

        // Clear elOptionsToUpdate
        var elOptionsToUpdate = this._elOptionsToUpdate = [];

        each$1(mappingResult, function (resultItem, index) {
            var newElOption = resultItem.option;

            if (__DEV__) {
                assert$1(
                    isObject$1(newElOption) || resultItem.exist,
                    'Empty graphic option definition'
                );
            }

            if (!newElOption) {
                return;
            }

            elOptionsToUpdate.push(newElOption);

            setKeyInfoToNewElOption(resultItem, newElOption);

            mergeNewElOptionToExist(existList, index, newElOption);

            setLayoutInfoToExist(existList[index], newElOption);

        }, this);

        // Clean
        for (var i = existList.length - 1; i >= 0; i--) {
            if (existList[i] == null) {
                existList.splice(i, 1);
            }
            else {
                // $action should be volatile, otherwise option gotten from
                // `getOption` will contain unexpected $action.
                delete existList[i].$action;
            }
        }
    },

    /**
     * Convert
     * [{
     *  type: 'group',
     *  id: 'xx',
     *  children: [{type: 'circle'}, {type: 'polygon'}]
     * }]
     * to
     * [
     *  {type: 'group', id: 'xx'},
     *  {type: 'circle', parentId: 'xx'},
     *  {type: 'polygon', parentId: 'xx'}
     * ]
     *
     * @private
     * @param {Array.<Object>} optionList option list
     * @param {Array.<Object>} result result of flatten
     * @param {Object} parentOption parent option
     */
    _flatten: function (optionList, result, parentOption) {
        each$1(optionList, function (option) {
            if (!option) {
                return;
            }

            if (parentOption) {
                option.parentOption = parentOption;
            }

            result.push(option);

            var children = option.children;
            if (option.type === 'group' && children) {
                this._flatten(children, result, option);
            }
            // Deleting for JSON output, and for not affecting group creation.
            delete option.children;
        }, this);
    },

    // FIXME
    // Pass to view using payload? setOption has a payload?
    useElOptionsToUpdate: function () {
        var els = this._elOptionsToUpdate;
        // Clear to avoid render duplicately when zooming.
        this._elOptionsToUpdate = null;
        return els;
    }
});

// -----
// View
// -----

extendComponentView({

    type: 'graphic',

    /**
     * @override
     */
    init: function (ecModel, api) {

        /**
         * @private
         * @type {module:zrender/core/util.HashMap}
         */
        this._elMap = createHashMap();

        /**
         * @private
         * @type {module:echarts/graphic/GraphicModel}
         */
        this._lastGraphicModel;
    },

    /**
     * @override
     */
    render: function (graphicModel, ecModel, api) {

        // Having leveraged between use cases and algorithm complexity, a very
        // simple layout mechanism is used:
        // The size(width/height) can be determined by itself or its parent (not
        // implemented yet), but can not by its children. (Top-down travel)
        // The location(x/y) can be determined by the bounding rect of itself
        // (can including its descendants or not) and the size of its parent.
        // (Bottom-up travel)

        // When `chart.clear()` or `chart.setOption({...}, true)` with the same id,
        // view will be reused.
        if (graphicModel !== this._lastGraphicModel) {
            this._clear();
        }
        this._lastGraphicModel = graphicModel;

        this._updateElements(graphicModel);
        this._relocate(graphicModel, api);
    },

    /**
     * Update graphic elements.
     *
     * @private
     * @param {Object} graphicModel graphic model
     */
    _updateElements: function (graphicModel) {
        var elOptionsToUpdate = graphicModel.useElOptionsToUpdate();

        if (!elOptionsToUpdate) {
            return;
        }

        var elMap = this._elMap;
        var rootGroup = this.group;

        // Top-down tranverse to assign graphic settings to each elements.
        each$1(elOptionsToUpdate, function (elOption) {
            var $action = elOption.$action;
            var id = elOption.id;
            var existEl = elMap.get(id);
            var parentId = elOption.parentId;
            var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup;

            var elOptionStyle = elOption.style;
            if (elOption.type === 'text' && elOptionStyle) {
                // In top/bottom mode, textVerticalAlign should not be used, which cause
                // inaccurately locating.
                if (elOption.hv && elOption.hv[1]) {
                    elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = null;
                }

                // Compatible with previous setting: both support fill and textFill,
                // stroke and textStroke.
                !elOptionStyle.hasOwnProperty('textFill') && elOptionStyle.fill && (
                    elOptionStyle.textFill = elOptionStyle.fill
                );
                !elOptionStyle.hasOwnProperty('textStroke') && elOptionStyle.stroke && (
                    elOptionStyle.textStroke = elOptionStyle.stroke
                );
            }

            // Remove unnecessary props to avoid potential problems.
            var elOptionCleaned = getCleanedElOption(elOption);

            // For simple, do not support parent change, otherwise reorder is needed.
            if (__DEV__) {
                existEl && assert$1(
                    targetElParent === existEl.parent,
                    'Changing parent is not supported.'
                );
            }

            if (!$action || $action === 'merge') {
                existEl
                    ? existEl.attr(elOptionCleaned)
                    : createEl$1(id, targetElParent, elOptionCleaned, elMap);
            }
            else if ($action === 'replace') {
                removeEl(existEl, elMap);
                createEl$1(id, targetElParent, elOptionCleaned, elMap);
            }
            else if ($action === 'remove') {
                removeEl(existEl, elMap);
            }

            var el = elMap.get(id);
            if (el) {
                el.__ecGraphicWidthOption = elOption.width;
                el.__ecGraphicHeightOption = elOption.height;
                setEventData(el, graphicModel, elOption);
            }
        });
    },

    /**
     * Locate graphic elements.
     *
     * @private
     * @param {Object} graphicModel graphic model
     * @param {module:echarts/ExtensionAPI} api extension API
     */
    _relocate: function (graphicModel, api) {
        var elOptions = graphicModel.option.elements;
        var rootGroup = this.group;
        var elMap = this._elMap;
        var apiWidth = api.getWidth();
        var apiHeight = api.getHeight();

        // Top-down to calculate percentage width/height of group
        for (var i = 0; i < elOptions.length; i++) {
            var elOption = elOptions[i];
            var el = elMap.get(elOption.id);

            if (!el || !el.isGroup) {
                continue;
            }
            var parentEl = el.parent;
            var isParentRoot = parentEl === rootGroup;
            // Like 'position:absolut' in css, default 0.
            el.__ecGraphicWidth = parsePercent$1(
                el.__ecGraphicWidthOption,
                isParentRoot ? apiWidth : parentEl.__ecGraphicWidth
            ) || 0;
            el.__ecGraphicHeight = parsePercent$1(
                el.__ecGraphicHeightOption,
                isParentRoot ? apiHeight : parentEl.__ecGraphicHeight
            ) || 0;
        }

        // Bottom-up tranvese all elements (consider ec resize) to locate elements.
        for (var i = elOptions.length - 1; i >= 0; i--) {
            var elOption = elOptions[i];
            var el = elMap.get(elOption.id);

            if (!el) {
                continue;
            }

            var parentEl = el.parent;
            var containerInfo = parentEl === rootGroup
                ? {
                    width: apiWidth,
                    height: apiHeight
                }
                : {
                    width: parentEl.__ecGraphicWidth,
                    height: parentEl.__ecGraphicHeight
                };

            // PENDING
            // Currently, when `bounding: 'all'`, the union bounding rect of the group
            // does not include the rect of [0, 0, group.width, group.height], which
            // is probably weird for users. Should we make a break change for it?
            positionElement(
                el, elOption, containerInfo, null,
                {hv: elOption.hv, boundingMode: elOption.bounding}
            );
        }
    },

    /**
     * Clear all elements.
     *
     * @private
     */
    _clear: function () {
        var elMap = this._elMap;
        elMap.each(function (el) {
            removeEl(el, elMap);
        });
        this._elMap = createHashMap();
    },

    /**
     * @override
     */
    dispose: function () {
        this._clear();
    }
});

function createEl$1(id, targetElParent, elOption, elMap) {
    var graphicType = elOption.type;

    if (__DEV__) {
        assert$1(graphicType, 'graphic type MUST be set');
    }

    var Clz = _nonShapeGraphicElements.hasOwnProperty(graphicType)
        // Those graphic elements are not shapes. They should not be
        // overwritten by users, so do them first.
        ? _nonShapeGraphicElements[graphicType]
        : getShapeClass(graphicType);

    if (__DEV__) {
        assert$1(Clz, 'graphic type can not be found');
    }

    var el = new Clz(elOption);
    targetElParent.add(el);
    elMap.set(id, el);
    el.__ecGraphicId = id;
}

function removeEl(existEl, elMap) {
    var existElParent = existEl && existEl.parent;
    if (existElParent) {
        existEl.type === 'group' && existEl.traverse(function (el) {
            removeEl(el, elMap);
        });
        elMap.removeKey(existEl.__ecGraphicId);
        existElParent.remove(existEl);
    }
}

// Remove unnecessary props to avoid potential problems.
function getCleanedElOption(elOption) {
    elOption = extend({}, elOption);
    each$1(
        ['id', 'parentId', '$action', 'hv', 'bounding'].concat(LOCATION_PARAMS),
        function (name) {
            delete elOption[name];
        }
    );
    return elOption;
}

function isSetLoc(obj, props) {
    var isSet;
    each$1(props, function (prop) {
        obj[prop] != null && obj[prop] !== 'auto' && (isSet = true);
    });
    return isSet;
}

function setKeyInfoToNewElOption(resultItem, newElOption) {
    var existElOption = resultItem.exist;

    // Set id and type after id assigned.
    newElOption.id = resultItem.keyInfo.id;
    !newElOption.type && existElOption && (newElOption.type = existElOption.type);

    // Set parent id if not specified
    if (newElOption.parentId == null) {
        var newElParentOption = newElOption.parentOption;
        if (newElParentOption) {
            newElOption.parentId = newElParentOption.id;
        }
        else if (existElOption) {
            newElOption.parentId = existElOption.parentId;
        }
    }

    // Clear
    newElOption.parentOption = null;
}

function mergeNewElOptionToExist(existList, index, newElOption) {
    // Update existing options, for `getOption` feature.
    var newElOptCopy = extend({}, newElOption);
    var existElOption = existList[index];

    var $action = newElOption.$action || 'merge';
    if ($action === 'merge') {
        if (existElOption) {

            if (__DEV__) {
                var newType = newElOption.type;
                assert$1(
                    !newType || existElOption.type === newType,
                    'Please set $action: "replace" to change `type`'
                );
            }

            // We can ensure that newElOptCopy and existElOption are not
            // the same object, so `merge` will not change newElOptCopy.
            merge(existElOption, newElOptCopy, true);
            // Rigid body, use ignoreSize.
            mergeLayoutParam(existElOption, newElOptCopy, {ignoreSize: true});
            // Will be used in render.
            copyLayoutParams(newElOption, existElOption);
        }
        else {
            existList[index] = newElOptCopy;
        }
    }
    else if ($action === 'replace') {
        existList[index] = newElOptCopy;
    }
    else if ($action === 'remove') {
        // null will be cleaned later.
        existElOption && (existList[index] = null);
    }
}

function setLayoutInfoToExist(existItem, newElOption) {
    if (!existItem) {
        return;
    }
    existItem.hv = newElOption.hv = [
        // Rigid body, dont care `width`.
        isSetLoc(newElOption, ['left', 'right']),
        // Rigid body, dont care `height`.
        isSetLoc(newElOption, ['top', 'bottom'])
    ];
    // Give default group size. Otherwise layout error may occur.
    if (existItem.type === 'group') {
        existItem.width == null && (existItem.width = newElOption.width = 0);
        existItem.height == null && (existItem.height = newElOption.height = 0);
    }
}

function setEventData(el, graphicModel, elOption) {
    var eventData = el.eventData;
    // Simple optimize for large amount of elements that no need event.
    if (!el.silent && !el.ignore && !eventData) {
        eventData = el.eventData = {
            componentType: 'graphic',
            componentIndex: graphicModel.componentIndex,
            name: el.name
        };
    }

    // `elOption.info` enables user to mount some info on
    // elements and use them in event handlers.
    if (eventData) {
        eventData.info = el.info;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


var features = {};

function register$1(name, ctor) {
    features[name] = ctor;
}

function get$1(name) {
    return features[name];
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var ToolboxModel = extendComponentModel({

    type: 'toolbox',

    layoutMode: {
        type: 'box',
        ignoreSize: true
    },

    optionUpdated: function () {
        ToolboxModel.superApply(this, 'optionUpdated', arguments);

        each$1(this.option.feature, function (featureOpt, featureName) {
            var Feature = get$1(featureName);
            Feature && merge(featureOpt, Feature.defaultOption);
        });
    },

    defaultOption: {

        show: true,

        z: 6,

        zlevel: 0,

        orient: 'horizontal',

        left: 'right',

        top: 'top',

        // right
        // bottom

        backgroundColor: 'transparent',

        borderColor: '#ccc',

        borderRadius: 0,

        borderWidth: 0,

        padding: 5,

        itemSize: 15,

        itemGap: 8,

        showTitle: true,

        iconStyle: {
            borderColor: '#666',
            color: 'none'
        },
        emphasis: {
            iconStyle: {
                borderColor: '#3E98C5'
            }
        },
        // textStyle: {},

        // feature

        tooltip: {
            show: false
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Layout list like component.
 * It will box layout each items in group of component and then position the whole group in the viewport
 * @param {module:zrender/group/Group} group
 * @param {module:echarts/model/Component} componentModel
 * @param {module:echarts/ExtensionAPI}
 */
function layout$3(group, componentModel, api) {
    var boxLayoutParams = componentModel.getBoxLayoutParams();
    var padding = componentModel.get('padding');
    var viewportSize = {width: api.getWidth(), height: api.getHeight()};

    var rect = getLayoutRect(
        boxLayoutParams,
        viewportSize,
        padding
    );

    box(
        componentModel.get('orient'),
        group,
        componentModel.get('itemGap'),
        rect.width,
        rect.height
    );

    positionElement(
        group,
        boxLayoutParams,
        viewportSize,
        padding
    );
}

function makeBackground(rect, componentModel) {
    var padding = normalizeCssArray$1(
        componentModel.get('padding')
    );
    var style = componentModel.getItemStyle(['color', 'opacity']);
    style.fill = componentModel.get('backgroundColor');
    var rect = new Rect({
        shape: {
            x: rect.x - padding[3],
            y: rect.y - padding[0],
            width: rect.width + padding[1] + padding[3],
            height: rect.height + padding[0] + padding[2],
            r: componentModel.get('borderRadius')
        },
        style: style,
        silent: true,
        z2: -1
    });
    // FIXME
    // `subPixelOptimizeRect` may bring some gap between edge of viewpart
    // and background rect when setting like `left: 0`, `top: 0`.
    // graphic.subPixelOptimizeRect(rect);

    return rect;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentView({

    type: 'toolbox',

    render: function (toolboxModel, ecModel, api, payload) {
        var group = this.group;
        group.removeAll();

        if (!toolboxModel.get('show')) {
            return;
        }

        var itemSize = +toolboxModel.get('itemSize');
        var featureOpts = toolboxModel.get('feature') || {};
        var features = this._features || (this._features = {});

        var featureNames = [];
        each$1(featureOpts, function (opt, name) {
            featureNames.push(name);
        });

        (new DataDiffer(this._featureNames || [], featureNames))
            .add(processFeature)
            .update(processFeature)
            .remove(curry(processFeature, null))
            .execute();

        // Keep for diff.
        this._featureNames = featureNames;

        function processFeature(newIndex, oldIndex) {
            var featureName = featureNames[newIndex];
            var oldName = featureNames[oldIndex];
            var featureOpt = featureOpts[featureName];
            var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
            var feature;

            if (featureName && !oldName) { // Create
                if (isUserFeatureName(featureName)) {
                    feature = {
                        model: featureModel,
                        onclick: featureModel.option.onclick,
                        featureName: featureName
                    };
                }
                else {
                    var Feature = get$1(featureName);
                    if (!Feature) {
                        return;
                    }
                    feature = new Feature(featureModel, ecModel, api);
                }
                features[featureName] = feature;
            }
            else {
                feature = features[oldName];
                // If feature does not exsit.
                if (!feature) {
                    return;
                }
                feature.model = featureModel;
                feature.ecModel = ecModel;
                feature.api = api;
            }

            if (!featureName && oldName) {
                feature.dispose && feature.dispose(ecModel, api);
                return;
            }

            if (!featureModel.get('show') || feature.unusable) {
                feature.remove && feature.remove(ecModel, api);
                return;
            }

            createIconPaths(featureModel, feature, featureName);

            featureModel.setIconStatus = function (iconName, status) {
                var option = this.option;
                var iconPaths = this.iconPaths;
                option.iconStatus = option.iconStatus || {};
                option.iconStatus[iconName] = status;
                // FIXME
                iconPaths[iconName] && iconPaths[iconName].trigger(status);
            };

            if (feature.render) {
                feature.render(featureModel, ecModel, api, payload);
            }
        }

        function createIconPaths(featureModel, feature, featureName) {
            var iconStyleModel = featureModel.getModel('iconStyle');
            var iconStyleEmphasisModel = featureModel.getModel('emphasis.iconStyle');

            // If one feature has mutiple icon. they are orginaized as
            // {
            //     icon: {
            //         foo: '',
            //         bar: ''
            //     },
            //     title: {
            //         foo: '',
            //         bar: ''
            //     }
            // }
            var icons = feature.getIcons ? feature.getIcons() : featureModel.get('icon');
            var titles = featureModel.get('title') || {};
            if (typeof icons === 'string') {
                var icon = icons;
                var title = titles;
                icons = {};
                titles = {};
                icons[featureName] = icon;
                titles[featureName] = title;
            }
            var iconPaths = featureModel.iconPaths = {};
            each$1(icons, function (iconStr, iconName) {
                var path = createIcon(
                    iconStr,
                    {},
                    {
                        x: -itemSize / 2,
                        y: -itemSize / 2,
                        width: itemSize,
                        height: itemSize
                    }
                );
                path.setStyle(iconStyleModel.getItemStyle());
                path.hoverStyle = iconStyleEmphasisModel.getItemStyle();

                // Text position calculation
                path.setStyle({
                    text: titles[iconName],
                    textAlign: iconStyleEmphasisModel.get('textAlign'),
                    textBorderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
                    textPadding: iconStyleEmphasisModel.get('textPadding'),
                    textFill: null
                });

                var tooltipModel = toolboxModel.getModel('tooltip');
                if (tooltipModel && tooltipModel.get('show')) {
                    path.attr('tooltip', extend({
                        content: titles[iconName],
                        formatter: tooltipModel.get('formatter', true)
                            || function () {
                                return titles[iconName];
                            },
                        formatterParams: {
                            componentType: 'toolbox',
                            name: iconName,
                            title: titles[iconName],
                            $vars: ['name', 'title']
                        },
                        position: tooltipModel.get('position', true) || 'bottom'
                    }, tooltipModel.option));
                }

                setHoverStyle(path);

                if (toolboxModel.get('showTitle')) {
                    path.__title = titles[iconName];
                    path.on('mouseover', function () {
                            // Should not reuse above hoverStyle, which might be modified.
                            var hoverStyle = iconStyleEmphasisModel.getItemStyle();
                            var defaultTextPosition = toolboxModel.get('orient') === 'vertical'
                                ? (toolboxModel.get('right') == null ? 'right' : 'left')
                                : (toolboxModel.get('bottom') == null ? 'bottom' : 'top');
                            path.setStyle({
                                textFill: iconStyleEmphasisModel.get('textFill')
                                    || hoverStyle.fill || hoverStyle.stroke || '#000',
                                textBackgroundColor: iconStyleEmphasisModel.get('textBackgroundColor'),
                                textPosition: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition
                            });
                        })
                        .on('mouseout', function () {
                            path.setStyle({
                                textFill: null,
                                textBackgroundColor: null
                            });
                        });
                }
                path.trigger(featureModel.get('iconStatus.' + iconName) || 'normal');

                group.add(path);
                path.on('click', bind(
                    feature.onclick, feature, ecModel, api, iconName
                ));

                iconPaths[iconName] = path;
            });
        }

        layout$3(group, toolboxModel, api);
        // Render background after group is layout
        // FIXME
        group.add(makeBackground(group.getBoundingRect(), toolboxModel));

        // Adjust icon title positions to avoid them out of screen
        group.eachChild(function (icon) {
            var titleText = icon.__title;
            var hoverStyle = icon.hoverStyle;
            // May be background element
            if (hoverStyle && titleText) {
                var rect = getBoundingRect(
                    titleText, makeFont(hoverStyle)
                );
                var offsetX = icon.position[0] + group.position[0];
                var offsetY = icon.position[1] + group.position[1] + itemSize;

                var needPutOnTop = false;
                if (offsetY + rect.height > api.getHeight()) {
                    hoverStyle.textPosition = 'top';
                    needPutOnTop = true;
                }
                var topOffset = needPutOnTop ? (-5 - rect.height) : (itemSize + 8);
                if (offsetX + rect.width / 2 > api.getWidth()) {
                    hoverStyle.textPosition = ['100%', topOffset];
                    hoverStyle.textAlign = 'right';
                }
                else if (offsetX - rect.width / 2 < 0) {
                    hoverStyle.textPosition = [0, topOffset];
                    hoverStyle.textAlign = 'left';
                }
            }
        });
    },

    updateView: function (toolboxModel, ecModel, api, payload) {
        each$1(this._features, function (feature) {
            feature.updateView && feature.updateView(feature.model, ecModel, api, payload);
        });
    },

    // updateLayout: function (toolboxModel, ecModel, api, payload) {
    //     zrUtil.each(this._features, function (feature) {
    //         feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload);
    //     });
    // },

    remove: function (ecModel, api) {
        each$1(this._features, function (feature) {
            feature.remove && feature.remove(ecModel, api);
        });
        this.group.removeAll();
    },

    dispose: function (ecModel, api) {
        each$1(this._features, function (feature) {
            feature.dispose && feature.dispose(ecModel, api);
        });
    }
});

function isUserFeatureName(featureName) {
    return featureName.indexOf('my') === 0;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/* global Uint8Array */

var saveAsImageLang = lang.toolbox.saveAsImage;

function SaveAsImage(model) {
    this.model = model;
}

SaveAsImage.defaultOption = {
    show: true,
    icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0',
    title: saveAsImageLang.title,
    type: 'png',
    // Default use option.backgroundColor
    // backgroundColor: '#fff',
    connectedBackgroundColor: '#fff',
    name: '',
    excludeComponents: ['toolbox'],
    pixelRatio: 1,
    lang: saveAsImageLang.lang.slice()
};

SaveAsImage.prototype.unusable = !env$1.canvasSupported;

var proto$2 = SaveAsImage.prototype;

proto$2.onclick = function (ecModel, api) {
    var model = this.model;
    var title = model.get('name') || ecModel.get('title.0.text') || 'echarts';
    var type = model.get('type', true) || 'png';
    var url = api.getConnectedDataURL({
        type: type,
        backgroundColor: model.get('backgroundColor', true)
            || ecModel.get('backgroundColor') || '#fff',
        connectedBackgroundColor: model.get('connectedBackgroundColor'),
        excludeComponents: model.get('excludeComponents'),
        pixelRatio: model.get('pixelRatio')
    });
    // Chrome and Firefox
    if (typeof MouseEvent === 'function' && !env$1.browser.ie && !env$1.browser.edge) {
        var $a = document.createElement('a');
        $a.download = title + '.' + type;
        $a.target = '_blank';
        $a.href = url;
        var evt = new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: false
        });
        $a.dispatchEvent(evt);
    }
    // IE
    else {
        if (window.navigator.msSaveOrOpenBlob) {
            var bstr = atob(url.split(',')[1]);
            var n = bstr.length;
            var u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            var blob = new Blob([u8arr]);
            window.navigator.msSaveOrOpenBlob(blob, title + '.' + type);
        }
        else {
            var lang$$1 = model.get('lang');
            var html = ''
                + '<body style="margin:0;">'
                + '<img src="' + url + '" style="max-width:100%;" title="' + ((lang$$1 && lang$$1[0]) || '') + '" />'
                + '</body>';
            var tab = window.open();
            tab.document.write(html);
        }
    }
};

register$1(
    'saveAsImage', SaveAsImage
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var magicTypeLang = lang.toolbox.magicType;

function MagicType(model) {
    this.model = model;
}

MagicType.defaultOption = {
    show: true,
    type: [],
    // Icon group
    icon: {
        /* eslint-disable */
        line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
        bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
        stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z', // jshint ignore:line
        tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z'
        /* eslint-enable */
    },
    // `line`, `bar`, `stack`, `tiled`
    title: clone(magicTypeLang.title),
    option: {},
    seriesIndex: {}
};

var proto$3 = MagicType.prototype;

proto$3.getIcons = function () {
    var model = this.model;
    var availableIcons = model.get('icon');
    var icons = {};
    each$1(model.get('type'), function (type) {
        if (availableIcons[type]) {
            icons[type] = availableIcons[type];
        }
    });
    return icons;
};

var seriesOptGenreator = {
    'line': function (seriesType, seriesId, seriesModel, model) {
        if (seriesType === 'bar') {
            return merge({
                id: seriesId,
                type: 'line',
                // Preserve data related option
                data: seriesModel.get('data'),
                stack: seriesModel.get('stack'),
                markPoint: seriesModel.get('markPoint'),
                markLine: seriesModel.get('markLine')
            }, model.get('option.line') || {}, true);
        }
    },
    'bar': function (seriesType, seriesId, seriesModel, model) {
        if (seriesType === 'line') {
            return merge({
                id: seriesId,
                type: 'bar',
                // Preserve data related option
                data: seriesModel.get('data'),
                stack: seriesModel.get('stack'),
                markPoint: seriesModel.get('markPoint'),
                markLine: seriesModel.get('markLine')
            }, model.get('option.bar') || {}, true);
        }
    },
    'stack': function (seriesType, seriesId, seriesModel, model) {
        if (seriesType === 'line' || seriesType === 'bar') {
            return merge({
                id: seriesId,
                stack: '__ec_magicType_stack__'
            }, model.get('option.stack') || {}, true);
        }
    },
    'tiled': function (seriesType, seriesId, seriesModel, model) {
        if (seriesType === 'line' || seriesType === 'bar') {
            return merge({
                id: seriesId,
                stack: ''
            }, model.get('option.tiled') || {}, true);
        }
    }
};

var radioTypes = [
    ['line', 'bar'],
    ['stack', 'tiled']
];

proto$3.onclick = function (ecModel, api, type) {
    var model = this.model;
    var seriesIndex = model.get('seriesIndex.' + type);
    // Not supported magicType
    if (!seriesOptGenreator[type]) {
        return;
    }
    var newOption = {
        series: []
    };
    var generateNewSeriesTypes = function (seriesModel) {
        var seriesType = seriesModel.subType;
        var seriesId = seriesModel.id;
        var newSeriesOpt = seriesOptGenreator[type](
            seriesType, seriesId, seriesModel, model
        );
        if (newSeriesOpt) {
            // PENDING If merge original option?
            defaults(newSeriesOpt, seriesModel.option);
            newOption.series.push(newSeriesOpt);
        }
        // Modify boundaryGap
        var coordSys = seriesModel.coordinateSystem;
        if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) {
            var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
            if (categoryAxis) {
                var axisDim = categoryAxis.dim;
                var axisType = axisDim + 'Axis';
                var axisModel = ecModel.queryComponents({
                    mainType: axisType,
                    index: seriesModel.get(name + 'Index'),
                    id: seriesModel.get(name + 'Id')
                })[0];
                var axisIndex = axisModel.componentIndex;

                newOption[axisType] = newOption[axisType] || [];
                for (var i = 0; i <= axisIndex; i++) {
                    newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {};
                }
                newOption[axisType][axisIndex].boundaryGap = type === 'bar';
            }
        }
    };

    each$1(radioTypes, function (radio) {
        if (indexOf(radio, type) >= 0) {
            each$1(radio, function (item) {
                model.setIconStatus(item, 'normal');
            });
        }
    });

    model.setIconStatus(type, 'emphasis');

    ecModel.eachComponent(
        {
            mainType: 'series',
            query: seriesIndex == null ? null : {
                seriesIndex: seriesIndex
            }
        }, generateNewSeriesTypes
    );
    api.dispatchAction({
        type: 'changeMagicType',
        currentType: type,
        newOption: newOption
    });
};

registerAction({
    type: 'changeMagicType',
    event: 'magicTypeChanged',
    update: 'prepareAndUpdate'
}, function (payload, ecModel) {
    ecModel.mergeOption(payload.newOption);
});

register$1('magicType', MagicType);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var dataViewLang = lang.toolbox.dataView;

var BLOCK_SPLITER = new Array(60).join('-');
var ITEM_SPLITER = '\t';
/**
 * Group series into two types
 *  1. on category axis, like line, bar
 *  2. others, like scatter, pie
 * @param {module:echarts/model/Global} ecModel
 * @return {Object}
 * @inner
 */
function groupSeries(ecModel) {
    var seriesGroupByCategoryAxis = {};
    var otherSeries = [];
    var meta = [];
    ecModel.eachRawSeries(function (seriesModel) {
        var coordSys = seriesModel.coordinateSystem;

        if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) {
            var baseAxis = coordSys.getBaseAxis();
            if (baseAxis.type === 'category') {
                var key = baseAxis.dim + '_' + baseAxis.index;
                if (!seriesGroupByCategoryAxis[key]) {
                    seriesGroupByCategoryAxis[key] = {
                        categoryAxis: baseAxis,
                        valueAxis: coordSys.getOtherAxis(baseAxis),
                        series: []
                    };
                    meta.push({
                        axisDim: baseAxis.dim,
                        axisIndex: baseAxis.index
                    });
                }
                seriesGroupByCategoryAxis[key].series.push(seriesModel);
            }
            else {
                otherSeries.push(seriesModel);
            }
        }
        else {
            otherSeries.push(seriesModel);
        }
    });

    return {
        seriesGroupByCategoryAxis: seriesGroupByCategoryAxis,
        other: otherSeries,
        meta: meta
    };
}

/**
 * Assemble content of series on cateogory axis
 * @param {Array.<module:echarts/model/Series>} series
 * @return {string}
 * @inner
 */
function assembleSeriesWithCategoryAxis(series) {
    var tables = [];
    each$1(series, function (group, key) {
        var categoryAxis = group.categoryAxis;
        var valueAxis = group.valueAxis;
        var valueAxisDim = valueAxis.dim;

        var headers = [' '].concat(map(group.series, function (series) {
            return series.name;
        }));
        var columns = [categoryAxis.model.getCategories()];
        each$1(group.series, function (series) {
            columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
                return val;
            }));
        });
        // Assemble table content
        var lines = [headers.join(ITEM_SPLITER)];
        for (var i = 0; i < columns[0].length; i++) {
            var items = [];
            for (var j = 0; j < columns.length; j++) {
                items.push(columns[j][i]);
            }
            lines.push(items.join(ITEM_SPLITER));
        }
        tables.push(lines.join('\n'));
    });
    return tables.join('\n\n' + BLOCK_SPLITER + '\n\n');
}

/**
 * Assemble content of other series
 * @param {Array.<module:echarts/model/Series>} series
 * @return {string}
 * @inner
 */
function assembleOtherSeries(series) {
    return map(series, function (series) {
        var data = series.getRawData();
        var lines = [series.name];
        var vals = [];
        data.each(data.dimensions, function () {
            var argLen = arguments.length;
            var dataIndex = arguments[argLen - 1];
            var name = data.getName(dataIndex);
            for (var i = 0; i < argLen - 1; i++) {
                vals[i] = arguments[i];
            }
            lines.push((name ? (name + ITEM_SPLITER) : '') + vals.join(ITEM_SPLITER));
        });
        return lines.join('\n');
    }).join('\n\n' + BLOCK_SPLITER + '\n\n');
}

/**
 * @param {module:echarts/model/Global}
 * @return {Object}
 * @inner
 */
function getContentFromModel(ecModel) {

    var result = groupSeries(ecModel);

    return {
        value: filter([
                assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis),
                assembleOtherSeries(result.other)
            ], function (str) {
                return str.replace(/[\n\t\s]/g, '');
            }).join('\n\n' + BLOCK_SPLITER + '\n\n'),

        meta: result.meta
    };
}


function trim$1(str) {
    return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
/**
 * If a block is tsv format
 */
function isTSVFormat(block) {
    // Simple method to find out if a block is tsv format
    var firstLine = block.slice(0, block.indexOf('\n'));
    if (firstLine.indexOf(ITEM_SPLITER) >= 0) {
        return true;
    }
}

var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g');
/**
 * @param {string} tsv
 * @return {Object}
 */
function parseTSVContents(tsv) {
    var tsvLines = tsv.split(/\n+/g);
    var headers = trim$1(tsvLines.shift()).split(itemSplitRegex);

    var categories = [];
    var series = map(headers, function (header) {
        return {
            name: header,
            data: []
        };
    });
    for (var i = 0; i < tsvLines.length; i++) {
        var items = trim$1(tsvLines[i]).split(itemSplitRegex);
        categories.push(items.shift());
        for (var j = 0; j < items.length; j++) {
            series[j] && (series[j].data[i] = items[j]);
        }
    }
    return {
        series: series,
        categories: categories
    };
}

/**
 * @param {string} str
 * @return {Array.<Object>}
 * @inner
 */
function parseListContents(str) {
    var lines = str.split(/\n+/g);
    var seriesName = trim$1(lines.shift());

    var data = [];
    for (var i = 0; i < lines.length; i++) {
        var items = trim$1(lines[i]).split(itemSplitRegex);
        var name = '';
        var value;
        var hasName = false;
        if (isNaN(items[0])) { // First item is name
            hasName = true;
            name = items[0];
            items = items.slice(1);
            data[i] = {
                name: name,
                value: []
            };
            value = data[i].value;
        }
        else {
            value = data[i] = [];
        }
        for (var j = 0; j < items.length; j++) {
            value.push(+items[j]);
        }
        if (value.length === 1) {
            hasName ? (data[i].value = value[0]) : (data[i] = value[0]);
        }
    }

    return {
        name: seriesName,
        data: data
    };
}

/**
 * @param {string} str
 * @param {Array.<Object>} blockMetaList
 * @return {Object}
 * @inner
 */
function parseContents(str, blockMetaList) {
    var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g'));
    var newOption = {
        series: []
    };
    each$1(blocks, function (block, idx) {
        if (isTSVFormat(block)) {
            var result = parseTSVContents(block);
            var blockMeta = blockMetaList[idx];
            var axisKey = blockMeta.axisDim + 'Axis';

            if (blockMeta) {
                newOption[axisKey] = newOption[axisKey] || [];
                newOption[axisKey][blockMeta.axisIndex] = {
                    data: result.categories
                };
                newOption.series = newOption.series.concat(result.series);
            }
        }
        else {
            var result = parseListContents(block);
            newOption.series.push(result);
        }
    });
    return newOption;
}

/**
 * @alias {module:echarts/component/toolbox/feature/DataView}
 * @constructor
 * @param {module:echarts/model/Model} model
 */
function DataView(model) {

    this._dom = null;

    this.model = model;
}

DataView.defaultOption = {
    show: true,
    readOnly: false,
    optionToContent: null,
    contentToOption: null,

    icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28',
    title: clone(dataViewLang.title),
    lang: clone(dataViewLang.lang),
    backgroundColor: '#fff',
    textColor: '#000',
    textareaColor: '#fff',
    textareaBorderColor: '#333',
    buttonColor: '#c23531',
    buttonTextColor: '#fff'
};

DataView.prototype.onclick = function (ecModel, api) {
    var container = api.getDom();
    var model = this.model;
    if (this._dom) {
        container.removeChild(this._dom);
    }
    var root = document.createElement('div');
    root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;';
    root.style.backgroundColor = model.get('backgroundColor') || '#fff';

    // Create elements
    var header = document.createElement('h4');
    var lang$$1 = model.get('lang') || [];
    header.innerHTML = lang$$1[0] || model.get('title');
    header.style.cssText = 'margin: 10px 20px;';
    header.style.color = model.get('textColor');

    var viewMain = document.createElement('div');
    var textarea = document.createElement('textarea');
    viewMain.style.cssText = 'display:block;width:100%;overflow:auto;';

    var optionToContent = model.get('optionToContent');
    var contentToOption = model.get('contentToOption');
    var result = getContentFromModel(ecModel);
    if (typeof optionToContent === 'function') {
        var htmlOrDom = optionToContent(api.getOption());
        if (typeof htmlOrDom === 'string') {
            viewMain.innerHTML = htmlOrDom;
        }
        else if (isDom(htmlOrDom)) {
            viewMain.appendChild(htmlOrDom);
        }
    }
    else {
        // Use default textarea
        viewMain.appendChild(textarea);
        textarea.readOnly = model.get('readOnly');
        textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;';
        textarea.style.color = model.get('textColor');
        textarea.style.borderColor = model.get('textareaBorderColor');
        textarea.style.backgroundColor = model.get('textareaColor');
        textarea.value = result.value;
    }

    var blockMetaList = result.meta;

    var buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;';

    var buttonStyle = 'float:right;margin-right:20px;border:none;'
        + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px';
    var closeButton = document.createElement('div');
    var refreshButton = document.createElement('div');

    buttonStyle += ';background-color:' + model.get('buttonColor');
    buttonStyle += ';color:' + model.get('buttonTextColor');

    var self = this;

    function close() {
        container.removeChild(root);
        self._dom = null;
    }
    addEventListener(closeButton, 'click', close);

    addEventListener(refreshButton, 'click', function () {
        var newOption;
        try {
            if (typeof contentToOption === 'function') {
                newOption = contentToOption(viewMain, api.getOption());
            }
            else {
                newOption = parseContents(textarea.value, blockMetaList);
            }
        }
        catch (e) {
            close();
            throw new Error('Data view format error ' + e);
        }
        if (newOption) {
            api.dispatchAction({
                type: 'changeDataView',
                newOption: newOption
            });
        }

        close();
    });

    closeButton.innerHTML = lang$$1[1];
    refreshButton.innerHTML = lang$$1[2];
    refreshButton.style.cssText = buttonStyle;
    closeButton.style.cssText = buttonStyle;

    !model.get('readOnly') && buttonContainer.appendChild(refreshButton);
    buttonContainer.appendChild(closeButton);

    root.appendChild(header);
    root.appendChild(viewMain);
    root.appendChild(buttonContainer);

    viewMain.style.height = (container.clientHeight - 80) + 'px';

    container.appendChild(root);
    this._dom = root;
};

DataView.prototype.remove = function (ecModel, api) {
    this._dom && api.getDom().removeChild(this._dom);
};

DataView.prototype.dispose = function (ecModel, api) {
    this.remove(ecModel, api);
};

/**
 * @inner
 */
function tryMergeDataOption(newData, originalData) {
    return map(newData, function (newVal, idx) {
        var original = originalData && originalData[idx];
        if (isObject$1(original) && !isArray(original)) {
            if (isObject$1(newVal) && !isArray(newVal)) {
                newVal = newVal.value;
            }
            // Original data has option
            return defaults({
                value: newVal
            }, original);
        }
        else {
            return newVal;
        }
    });
}

register$1('dataView', DataView);

registerAction({
    type: 'changeDataView',
    event: 'dataViewChanged',
    update: 'prepareAndUpdate'
}, function (payload, ecModel) {
    var newSeriesOptList = [];
    each$1(payload.newOption.series, function (seriesOpt) {
        var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0];
        if (!seriesModel) {
            // New created series
            // Geuss the series type
            newSeriesOptList.push(extend({
                // Default is scatter
                type: 'scatter'
            }, seriesOpt));
        }
        else {
            var originalData = seriesModel.get('data');
            newSeriesOptList.push({
                name: seriesOpt.name,
                data: tryMergeDataOption(seriesOpt.data, originalData)
            });
        }
    });

    ecModel.mergeOption(defaults({
        series: newSeriesOptList
    }, payload.newOption));
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$17 = each$1;
var indexOf$1 = indexOf;
var curry$4 = curry;

var COORD_CONVERTS = ['dataToPoint', 'pointToData'];

// FIXME
// how to genarialize to more coordinate systems.
var INCLUDE_FINDER_MAIN_TYPES = [
    'grid', 'xAxis', 'yAxis', 'geo', 'graph',
    'polar', 'radiusAxis', 'angleAxis', 'bmap'
];

/**
 * [option in constructor]:
 * {
 *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.
 * }
 *
 *
 * [targetInfo]:
 *
 * There can be multiple axes in a single targetInfo. Consider the case
 * of `grid` component, a targetInfo represents a grid which contains one or more
 * cartesian and one or more axes. And consider the case of parallel system,
 * which has multiple axes in a coordinate system.
 * Can be {
 *     panelId: ...,
 *     coordSys: <a representitive cartesian in grid (first cartesian by default)>,
 *     coordSyses: all cartesians.
 *     gridModel: <grid component>
 *     xAxes: correspond to coordSyses on index
 *     yAxes: correspond to coordSyses on index
 * }
 * or {
 *     panelId: ...,
 *     coordSys: <geo coord sys>
 *     coordSyses: [<geo coord sys>]
 *     geoModel: <geo component>
 * }
 *
 *
 * [panelOpt]:
 *
 * Make from targetInfo. Input to BrushController.
 * {
 *     panelId: ...,
 *     rect: ...
 * }
 *
 *
 * [area]:
 *
 * Generated by BrushController or user input.
 * {
 *     panelId: Used to locate coordInfo directly. If user inpput, no panelId.
 *     brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y').
 *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.
 *     range: pixel range.
 *     coordRange: representitive coord range (the first one of coordRanges).
 *     coordRanges: <Array> coord ranges, used in multiple cartesian in one grid.
 * }
 */

/**
 * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid
 *        Each can be {number|Array.<number>}. like: {xAxisIndex: [3, 4]}
 * @param {module:echarts/model/Global} ecModel
 * @param {Object} [opt]
 * @param {Array.<string>} [opt.include] include coordinate system types.
 */
function BrushTargetManager(option, ecModel, opt) {
    /**
     * @private
     * @type {Array.<Object>}
     */
    var targetInfoList = this._targetInfoList = [];
    var info = {};
    var foundCpts = parseFinder$1(ecModel, option);

    each$17(targetInfoBuilders, function (builder, type) {
        if (!opt || !opt.include || indexOf$1(opt.include, type) >= 0) {
            builder(foundCpts, targetInfoList, info);
        }
    });
}

var proto$5 = BrushTargetManager.prototype;

proto$5.setOutputRanges = function (areas, ecModel) {
    this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
        (area.coordRanges || (area.coordRanges = [])).push(coordRange);
        // area.coordRange is the first of area.coordRanges
        if (!area.coordRange) {
            area.coordRange = coordRange;
            // In 'category' axis, coord to pixel is not reversible, so we can not
            // rebuild range by coordRange accrately, which may bring trouble when
            // brushing only one item. So we use __rangeOffset to rebuilding range
            // by coordRange. And this it only used in brush component so it is no
            // need to be adapted to coordRanges.
            var result = coordConvert[area.brushType](0, coordSys, coordRange);
            area.__rangeOffset = {
                offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]),
                xyMinMax: result.xyMinMax
            };
        }
    });
};

proto$5.matchOutputRanges = function (areas, ecModel, cb) {
    each$17(areas, function (area) {
        var targetInfo = this.findTargetInfo(area, ecModel);

        if (targetInfo && targetInfo !== true) {
            each$1(
                targetInfo.coordSyses,
                function (coordSys) {
                    var result = coordConvert[area.brushType](1, coordSys, area.range);
                    cb(area, result.values, coordSys, ecModel);
                }
            );
        }
    }, this);
};

proto$5.setInputRanges = function (areas, ecModel) {
    each$17(areas, function (area) {
        var targetInfo = this.findTargetInfo(area, ecModel);

        if (__DEV__) {
            assert$1(
                !targetInfo || targetInfo === true || area.coordRange,
                'coordRange must be specified when coord index specified.'
            );
            assert$1(
                !targetInfo || targetInfo !== true || area.range,
                'range must be specified in global brush.'
            );
        }

        area.range = area.range || [];

        // convert coordRange to global range and set panelId.
        if (targetInfo && targetInfo !== true) {
            area.panelId = targetInfo.panelId;
            // (1) area.range shoule always be calculate from coordRange but does
            // not keep its original value, for the sake of the dataZoom scenario,
            // where area.coordRange remains unchanged but area.range may be changed.
            // (2) Only support converting one coordRange to pixel range in brush
            // component. So do not consider `coordRanges`.
            // (3) About __rangeOffset, see comment above.
            var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange);
            var rangeOffset = area.__rangeOffset;
            area.range = rangeOffset
                ? diffProcessor[area.brushType](
                    result.values,
                    rangeOffset.offset,
                    getScales(result.xyMinMax, rangeOffset.xyMinMax)
                )
                : result.values;
        }
    }, this);
};

proto$5.makePanelOpts = function (api, getDefaultBrushType) {
    return map(this._targetInfoList, function (targetInfo) {
        var rect = targetInfo.getPanelRect();
        return {
            panelId: targetInfo.panelId,
            defaultBrushType: getDefaultBrushType && getDefaultBrushType(targetInfo),
            clipPath: makeRectPanelClipPath(rect),
            isTargetByCursor: makeRectIsTargetByCursor(
                rect, api, targetInfo.coordSysModel
            ),
            getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect)
        };
    });
};

proto$5.controlSeries = function (area, seriesModel, ecModel) {
    // Check whether area is bound in coord, and series do not belong to that coord.
    // If do not do this check, some brush (like lineX) will controll all axes.
    var targetInfo = this.findTargetInfo(area, ecModel);
    return targetInfo === true || (
        targetInfo && indexOf$1(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0
    );
};

/**
 * If return Object, a coord found.
 * If reutrn true, global found.
 * Otherwise nothing found.
 *
 * @param {Object} area
 * @param {Array} targetInfoList
 * @return {Object|boolean}
 */
proto$5.findTargetInfo = function (area, ecModel) {
    var targetInfoList = this._targetInfoList;
    var foundCpts = parseFinder$1(ecModel, area);

    for (var i = 0; i < targetInfoList.length; i++) {
        var targetInfo = targetInfoList[i];
        var areaPanelId = area.panelId;
        if (areaPanelId) {
            if (targetInfo.panelId === areaPanelId) {
                return targetInfo;
            }
        }
        else {
            for (var i = 0; i < targetInfoMatchers.length; i++) {
                if (targetInfoMatchers[i](foundCpts, targetInfo)) {
                    return targetInfo;
                }
            }
        }
    }

    return true;
};

function formatMinMax(minMax) {
    minMax[0] > minMax[1] && minMax.reverse();
    return minMax;
}

function parseFinder$1(ecModel, option) {
    return parseFinder(
        ecModel, option, {includeMainTypes: INCLUDE_FINDER_MAIN_TYPES}
    );
}

var targetInfoBuilders = {

    grid: function (foundCpts, targetInfoList) {
        var xAxisModels = foundCpts.xAxisModels;
        var yAxisModels = foundCpts.yAxisModels;
        var gridModels = foundCpts.gridModels;
        // Remove duplicated.
        var gridModelMap = createHashMap();
        var xAxesHas = {};
        var yAxesHas = {};

        if (!xAxisModels && !yAxisModels && !gridModels) {
            return;
        }

        each$17(xAxisModels, function (axisModel) {
            var gridModel = axisModel.axis.grid.model;
            gridModelMap.set(gridModel.id, gridModel);
            xAxesHas[gridModel.id] = true;
        });
        each$17(yAxisModels, function (axisModel) {
            var gridModel = axisModel.axis.grid.model;
            gridModelMap.set(gridModel.id, gridModel);
            yAxesHas[gridModel.id] = true;
        });
        each$17(gridModels, function (gridModel) {
            gridModelMap.set(gridModel.id, gridModel);
            xAxesHas[gridModel.id] = true;
            yAxesHas[gridModel.id] = true;
        });

        gridModelMap.each(function (gridModel) {
            var grid = gridModel.coordinateSystem;
            var cartesians = [];

            each$17(grid.getCartesians(), function (cartesian, index) {
                if (indexOf$1(xAxisModels, cartesian.getAxis('x').model) >= 0
                    || indexOf$1(yAxisModels, cartesian.getAxis('y').model) >= 0
                ) {
                    cartesians.push(cartesian);
                }
            });
            targetInfoList.push({
                panelId: 'grid--' + gridModel.id,
                gridModel: gridModel,
                coordSysModel: gridModel,
                // Use the first one as the representitive coordSys.
                coordSys: cartesians[0],
                coordSyses: cartesians,
                getPanelRect: panelRectBuilder.grid,
                xAxisDeclared: xAxesHas[gridModel.id],
                yAxisDeclared: yAxesHas[gridModel.id]
            });
        });
    },

    geo: function (foundCpts, targetInfoList) {
        each$17(foundCpts.geoModels, function (geoModel) {
            var coordSys = geoModel.coordinateSystem;
            targetInfoList.push({
                panelId: 'geo--' + geoModel.id,
                geoModel: geoModel,
                coordSysModel: geoModel,
                coordSys: coordSys,
                coordSyses: [coordSys],
                getPanelRect: panelRectBuilder.geo
            });
        });
    }
};

var targetInfoMatchers = [

    // grid
    function (foundCpts, targetInfo) {
        var xAxisModel = foundCpts.xAxisModel;
        var yAxisModel = foundCpts.yAxisModel;
        var gridModel = foundCpts.gridModel;

        !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model);
        !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model);

        return gridModel && gridModel === targetInfo.gridModel;
    },

    // geo
    function (foundCpts, targetInfo) {
        var geoModel = foundCpts.geoModel;
        return geoModel && geoModel === targetInfo.geoModel;
    }
];

var panelRectBuilder = {

    grid: function () {
        // grid is not Transformable.
        return this.coordSys.grid.getRect().clone();
    },

    geo: function () {
        var coordSys = this.coordSys;
        var rect = coordSys.getBoundingRect().clone();
        // geo roam and zoom transform
        rect.applyTransform(getTransform(coordSys));
        return rect;
    }
};

var coordConvert = {

    lineX: curry$4(axisConvert, 0),

    lineY: curry$4(axisConvert, 1),

    rect: function (to, coordSys, rangeOrCoordRange) {
        var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]);
        var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]);
        var values = [
            formatMinMax([xminymin[0], xmaxymax[0]]),
            formatMinMax([xminymin[1], xmaxymax[1]])
        ];
        return {values: values, xyMinMax: values};
    },

    polygon: function (to, coordSys, rangeOrCoordRange) {
        var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]];
        var values = map(rangeOrCoordRange, function (item) {
            var p = coordSys[COORD_CONVERTS[to]](item);
            xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]);
            xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]);
            xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]);
            xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]);
            return p;
        });
        return {values: values, xyMinMax: xyMinMax};
    }
};

function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) {
    if (__DEV__) {
        assert$1(
            coordSys.type === 'cartesian2d',
            'lineX/lineY brush is available only in cartesian2d.'
        );
    }

    var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]);
    var values = formatMinMax(map([0, 1], function (i) {
        return to
            ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i]))
            : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i]));
    }));
    var xyMinMax = [];
    xyMinMax[axisNameIndex] = values;
    xyMinMax[1 - axisNameIndex] = [NaN, NaN];

    return {values: values, xyMinMax: xyMinMax};
}

var diffProcessor = {
    lineX: curry$4(axisDiffProcessor, 0),

    lineY: curry$4(axisDiffProcessor, 1),

    rect: function (values, refer, scales) {
        return [
            [values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]],
            [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]
        ];
    },

    polygon: function (values, refer, scales) {
        return map(values, function (item, idx) {
            return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]];
        });
    }
};

function axisDiffProcessor(axisNameIndex, values, refer, scales) {
    return [
        values[0] - scales[axisNameIndex] * refer[0],
        values[1] - scales[axisNameIndex] * refer[1]
    ];
}

// We have to process scale caused by dataZoom manually,
// although it might be not accurate.
function getScales(xyMinMaxCurr, xyMinMaxOrigin) {
    var sizeCurr = getSize(xyMinMaxCurr);
    var sizeOrigin = getSize(xyMinMaxOrigin);
    var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]];
    isNaN(scales[0]) && (scales[0] = 1);
    isNaN(scales[1]) && (scales[1] = 1);
    return scales;
}

function getSize(xyMinMax) {
    return xyMinMax
        ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]]
        : [NaN, NaN];
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$18 = each$1;

var ATTR$1 = '\0_ec_hist_store';

/**
 * @param {module:echarts/model/Global} ecModel
 * @param {Object} newSnapshot {dataZoomId, batch: [payloadInfo, ...]}
 */
function push(ecModel, newSnapshot) {
    var store = giveStore(ecModel);

    // If previous dataZoom can not be found,
    // complete an range with current range.
    each$18(newSnapshot, function (batchItem, dataZoomId) {
        var i = store.length - 1;
        for (; i >= 0; i--) {
            var snapshot = store[i];
            if (snapshot[dataZoomId]) {
                break;
            }
        }
        if (i < 0) {
            // No origin range set, create one by current range.
            var dataZoomModel = ecModel.queryComponents(
                {mainType: 'dataZoom', subType: 'select', id: dataZoomId}
            )[0];
            if (dataZoomModel) {
                var percentRange = dataZoomModel.getPercentRange();
                store[0][dataZoomId] = {
                    dataZoomId: dataZoomId,
                    start: percentRange[0],
                    end: percentRange[1]
                };
            }
        }
    });

    store.push(newSnapshot);
}

/**
 * @param {module:echarts/model/Global} ecModel
 * @return {Object} snapshot
 */
function pop(ecModel) {
    var store = giveStore(ecModel);
    var head = store[store.length - 1];
    store.length > 1 && store.pop();

    // Find top for all dataZoom.
    var snapshot = {};
    each$18(head, function (batchItem, dataZoomId) {
        for (var i = store.length - 1; i >= 0; i--) {
            var batchItem = store[i][dataZoomId];
            if (batchItem) {
                snapshot[dataZoomId] = batchItem;
                break;
            }
        }
    });

    return snapshot;
}

/**
 * @param {module:echarts/model/Global} ecModel
 */
function clear$1(ecModel) {
    ecModel[ATTR$1] = null;
}

/**
 * @param {module:echarts/model/Global} ecModel
 * @return {number} records. always >= 1.
 */
function count(ecModel) {
    return giveStore(ecModel).length;
}

/**
 * [{key: dataZoomId, value: {dataZoomId, range}}, ...]
 * History length of each dataZoom may be different.
 * this._history[0] is used to store origin range.
 * @type {Array.<Object>}
 */
function giveStore(ecModel) {
    var store = ecModel[ATTR$1];
    if (!store) {
        store = ecModel[ATTR$1] = [{}];
    }
    return store;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

ComponentModel.registerSubTypeDefaulter('dataZoom', function () {
    // Default 'slider' when no type specified.
    return 'slider';
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single'];
// Supported coords.
var COORDS = ['cartesian2d', 'polar', 'singleAxis'];

/**
 * @param {string} coordType
 * @return {boolean}
 */
function isCoordSupported(coordType) {
    return indexOf(COORDS, coordType) >= 0;
}

/**
 * Create "each" method to iterate names.
 *
 * @pubilc
 * @param  {Array.<string>} names
 * @param  {Array.<string>=} attrs
 * @return {Function}
 */
function createNameEach(names, attrs) {
    names = names.slice();
    var capitalNames = map(names, capitalFirst);
    attrs = (attrs || []).slice();
    var capitalAttrs = map(attrs, capitalFirst);

    return function (callback, context) {
        each$1(names, function (name, index) {
            var nameObj = {name: name, capital: capitalNames[index]};

            for (var j = 0; j < attrs.length; j++) {
                nameObj[attrs[j]] = name + capitalAttrs[j];
            }

            callback.call(context, nameObj);
        });
    };
}

/**
 * Iterate each dimension name.
 *
 * @public
 * @param {Function} callback The parameter is like:
 *                            {
 *                                name: 'angle',
 *                                capital: 'Angle',
 *                                axis: 'angleAxis',
 *                                axisIndex: 'angleAixs',
 *                                index: 'angleIndex'
 *                            }
 * @param {Object} context
 */
var eachAxisDim$1 = createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index', 'id']);

/**
 * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'.
 * dataZoomModels and 'links' make up one or more graphics.
 * This function finds the graphic where the source dataZoomModel is in.
 *
 * @public
 * @param {Function} forEachNode Node iterator.
 * @param {Function} forEachEdgeType edgeType iterator
 * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id.
 * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}}
 */
function createLinkedNodesFinder(forEachNode, forEachEdgeType, edgeIdGetter) {

    return function (sourceNode) {
        var result = {
            nodes: [],
            records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean).
        };

        forEachEdgeType(function (edgeType) {
            result.records[edgeType.name] = {};
        });

        if (!sourceNode) {
            return result;
        }

        absorb(sourceNode, result);

        var existsLink;
        do {
            existsLink = false;
            forEachNode(processSingleNode);
        }
        while (existsLink);

        function processSingleNode(node) {
            if (!isNodeAbsorded(node, result) && isLinked(node, result)) {
                absorb(node, result);
                existsLink = true;
            }
        }

        return result;
    };

    function isNodeAbsorded(node, result) {
        return indexOf(result.nodes, node) >= 0;
    }

    function isLinked(node, result) {
        var hasLink = false;
        forEachEdgeType(function (edgeType) {
            each$1(edgeIdGetter(node, edgeType) || [], function (edgeId) {
                result.records[edgeType.name][edgeId] && (hasLink = true);
            });
        });
        return hasLink;
    }

    function absorb(node, result) {
        result.nodes.push(node);
        forEachEdgeType(function (edgeType) {
            each$1(edgeIdGetter(node, edgeType) || [], function (edgeId) {
                result.records[edgeType.name][edgeId] = true;
            });
        });
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$20 = each$1;
var asc$1 = asc;

/**
 * Operate single axis.
 * One axis can only operated by one axis operator.
 * Different dataZoomModels may be defined to operate the same axis.
 * (i.e. 'inside' data zoom and 'slider' data zoom components)
 * So dataZoomModels share one axisProxy in that case.
 *
 * @class
 */
var AxisProxy = function (dimName, axisIndex, dataZoomModel, ecModel) {

    /**
     * @private
     * @type {string}
     */
    this._dimName = dimName;

    /**
     * @private
     */
    this._axisIndex = axisIndex;

    /**
     * @private
     * @type {Array.<number>}
     */
    this._valueWindow;

    /**
     * @private
     * @type {Array.<number>}
     */
    this._percentWindow;

    /**
     * @private
     * @type {Array.<number>}
     */
    this._dataExtent;

    /**
     * {minSpan, maxSpan, minValueSpan, maxValueSpan}
     * @private
     * @type {Object}
     */
    this._minMaxSpan;

    /**
     * @readOnly
     * @type {module: echarts/model/Global}
     */
    this.ecModel = ecModel;

    /**
     * @private
     * @type {module: echarts/component/dataZoom/DataZoomModel}
     */
    this._dataZoomModel = dataZoomModel;

    // /**
    //  * @readOnly
    //  * @private
    //  */
    // this.hasSeriesStacked;
};

AxisProxy.prototype = {

    constructor: AxisProxy,

    /**
     * Whether the axisProxy is hosted by dataZoomModel.
     *
     * @public
     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
     * @return {boolean}
     */
    hostedBy: function (dataZoomModel) {
        return this._dataZoomModel === dataZoomModel;
    },

    /**
     * @return {Array.<number>} Value can only be NaN or finite value.
     */
    getDataValueWindow: function () {
        return this._valueWindow.slice();
    },

    /**
     * @return {Array.<number>}
     */
    getDataPercentWindow: function () {
        return this._percentWindow.slice();
    },

    /**
     * @public
     * @param {number} axisIndex
     * @return {Array} seriesModels
     */
    getTargetSeriesModels: function () {
        var seriesModels = [];
        var ecModel = this.ecModel;

        ecModel.eachSeries(function (seriesModel) {
            if (isCoordSupported(seriesModel.get('coordinateSystem'))) {
                var dimName = this._dimName;
                var axisModel = ecModel.queryComponents({
                    mainType: dimName + 'Axis',
                    index: seriesModel.get(dimName + 'AxisIndex'),
                    id: seriesModel.get(dimName + 'AxisId')
                })[0];
                if (this._axisIndex === (axisModel && axisModel.componentIndex)) {
                    seriesModels.push(seriesModel);
                }
            }
        }, this);

        return seriesModels;
    },

    getAxisModel: function () {
        return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex);
    },

    getOtherAxisModel: function () {
        var axisDim = this._dimName;
        var ecModel = this.ecModel;
        var axisModel = this.getAxisModel();
        var isCartesian = axisDim === 'x' || axisDim === 'y';
        var otherAxisDim;
        var coordSysIndexName;
        if (isCartesian) {
            coordSysIndexName = 'gridIndex';
            otherAxisDim = axisDim === 'x' ? 'y' : 'x';
        }
        else {
            coordSysIndexName = 'polarIndex';
            otherAxisDim = axisDim === 'angle' ? 'radius' : 'angle';
        }
        var foundOtherAxisModel;
        ecModel.eachComponent(otherAxisDim + 'Axis', function (otherAxisModel) {
            if ((otherAxisModel.get(coordSysIndexName) || 0)
                === (axisModel.get(coordSysIndexName) || 0)
            ) {
                foundOtherAxisModel = otherAxisModel;
            }
        });
        return foundOtherAxisModel;
    },

    getMinMaxSpan: function () {
        return clone(this._minMaxSpan);
    },

    /**
     * Only calculate by given range and this._dataExtent, do not change anything.
     *
     * @param {Object} opt
     * @param {number} [opt.start]
     * @param {number} [opt.end]
     * @param {number} [opt.startValue]
     * @param {number} [opt.endValue]
     */
    calculateDataWindow: function (opt) {
        var dataExtent = this._dataExtent;
        var axisModel = this.getAxisModel();
        var scale = axisModel.axis.scale;
        var rangePropMode = this._dataZoomModel.getRangePropMode();
        var percentExtent = [0, 100];
        var percentWindow = [];
        var valueWindow = [];
        var hasPropModeValue;

        each$20(['start', 'end'], function (prop, idx) {
            var boundPercent = opt[prop];
            var boundValue = opt[prop + 'Value'];

            // Notice: dataZoom is based either on `percentProp` ('start', 'end') or
            // on `valueProp` ('startValue', 'endValue'). (They are based on the data extent
            // but not min/max of axis, which will be calculated by data window then).
            // The former one is suitable for cases that a dataZoom component controls multiple
            // axes with different unit or extent, and the latter one is suitable for accurate
            // zoom by pixel (e.g., in dataZoomSelect).
            // we use `getRangePropMode()` to mark which prop is used. `rangePropMode` is updated
            // only when setOption or dispatchAction, otherwise it remains its original value.
            // (Why not only record `percentProp` and always map to `valueProp`? Because
            // the map `valueProp` -> `percentProp` -> `valueProp` probably not the original
            // `valueProp`. consider two axes constrolled by one dataZoom. They have different
            // data extent. All of values that are overflow the `dataExtent` will be calculated
            // to percent '100%').

            if (rangePropMode[idx] === 'percent') {
                boundPercent == null && (boundPercent = percentExtent[idx]);
                // Use scale.parse to math round for category or time axis.
                boundValue = scale.parse(linearMap(
                    boundPercent, percentExtent, dataExtent
                ));
            }
            else {
                hasPropModeValue = true;
                boundValue = boundValue == null ? dataExtent[idx] : scale.parse(boundValue);
                // Calculating `percent` from `value` may be not accurate, because
                // This calculation can not be inversed, because all of values that
                // are overflow the `dataExtent` will be calculated to percent '100%'
                boundPercent = linearMap(
                    boundValue, dataExtent, percentExtent
                );
            }

            // valueWindow[idx] = round(boundValue);
            // percentWindow[idx] = round(boundPercent);
            valueWindow[idx] = boundValue;
            percentWindow[idx] = boundPercent;
        });

        asc$1(valueWindow);
        asc$1(percentWindow);

        // The windows from user calling of `dispatchAction` might be out of the extent,
        // or do not obey the `min/maxSpan`, `min/maxValueSpan`. But we dont restrict window
        // by `zoomLock` here, because we see `zoomLock` just as a interaction constraint,
        // where API is able to initialize/modify the window size even though `zoomLock`
        // specified.
        var spans = this._minMaxSpan;
        hasPropModeValue
            ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false)
            : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true);

        function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) {
            var suffix = toValue ? 'Span' : 'ValueSpan';
            sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]);
            for (var i = 0; i < 2; i++) {
                toWindow[i] = linearMap(fromWindow[i], fromExtent, toExtent, true);
                toValue && (toWindow[i] = scale.parse(toWindow[i]));
            }
        }

        return {
            valueWindow: valueWindow,
            percentWindow: percentWindow
        };
    },

    /**
     * Notice: reset should not be called before series.restoreData() called,
     * so it is recommanded to be called in "process stage" but not "model init
     * stage".
     *
     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
     */
    reset: function (dataZoomModel) {
        if (dataZoomModel !== this._dataZoomModel) {
            return;
        }

        var targetSeries = this.getTargetSeriesModels();
        // Culculate data window and data extent, and record them.
        this._dataExtent = calculateDataExtent(this, this._dimName, targetSeries);

        // this.hasSeriesStacked = false;
        // each(targetSeries, function (series) {
            // var data = series.getData();
            // var dataDim = data.mapDimension(this._dimName);
            // var stackedDimension = data.getCalculationInfo('stackedDimension');
            // if (stackedDimension && stackedDimension === dataDim) {
                // this.hasSeriesStacked = true;
            // }
        // }, this);

        // `calculateDataWindow` uses min/maxSpan.
        setMinMaxSpan(this);

        var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption);

        this._valueWindow = dataWindow.valueWindow;
        this._percentWindow = dataWindow.percentWindow;

        // Update axis setting then.
        setAxisModel(this);
    },

    /**
     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
     */
    restore: function (dataZoomModel) {
        if (dataZoomModel !== this._dataZoomModel) {
            return;
        }

        this._valueWindow = this._percentWindow = null;
        setAxisModel(this, true);
    },

    /**
     * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
     */
    filterData: function (dataZoomModel, api) {
        if (dataZoomModel !== this._dataZoomModel) {
            return;
        }

        var axisDim = this._dimName;
        var seriesModels = this.getTargetSeriesModels();
        var filterMode = dataZoomModel.get('filterMode');
        var valueWindow = this._valueWindow;

        if (filterMode === 'none') {
            return;
        }

        // FIXME
        // Toolbox may has dataZoom injected. And if there are stacked bar chart
        // with NaN data, NaN will be filtered and stack will be wrong.
        // So we need to force the mode to be set empty.
        // In fect, it is not a big deal that do not support filterMode-'filter'
        // when using toolbox#dataZoom, utill tooltip#dataZoom support "single axis
        // selection" some day, which might need "adapt to data extent on the
        // otherAxis", which is disabled by filterMode-'empty'.
        // But currently, stack has been fixed to based on value but not index,
        // so this is not an issue any more.
        // var otherAxisModel = this.getOtherAxisModel();
        // if (dataZoomModel.get('$fromToolbox')
        //     && otherAxisModel
        //     && otherAxisModel.hasSeriesStacked
        // ) {
        //     filterMode = 'empty';
        // }

        // TODO
        // filterMode 'weakFilter' and 'empty' is not optimized for huge data yet.

        each$20(seriesModels, function (seriesModel) {
            var seriesData = seriesModel.getData();
            var dataDims = seriesData.mapDimension(axisDim, true);

            if (!dataDims.length) {
                return;
            }

            if (filterMode === 'weakFilter') {
                seriesData.filterSelf(function (dataIndex) {
                    var leftOut;
                    var rightOut;
                    var hasValue;
                    for (var i = 0; i < dataDims.length; i++) {
                        var value = seriesData.get(dataDims[i], dataIndex);
                        var thisHasValue = !isNaN(value);
                        var thisLeftOut = value < valueWindow[0];
                        var thisRightOut = value > valueWindow[1];
                        if (thisHasValue && !thisLeftOut && !thisRightOut) {
                            return true;
                        }
                        thisHasValue && (hasValue = true);
                        thisLeftOut && (leftOut = true);
                        thisRightOut && (rightOut = true);
                    }
                    // If both left out and right out, do not filter.
                    return hasValue && leftOut && rightOut;
                });
            }
            else {
                each$20(dataDims, function (dim) {
                    if (filterMode === 'empty') {
                        seriesModel.setData(
                            seriesData = seriesData.map(dim, function (value) {
                                return !isInWindow(value) ? NaN : value;
                            })
                        );
                    }
                    else {
                        var range = {};
                        range[dim] = valueWindow;

                        // console.time('select');
                        seriesData.selectRange(range);
                        // console.timeEnd('select');
                    }
                });
            }

            each$20(dataDims, function (dim) {
                seriesData.setApproximateExtent(valueWindow, dim);
            });
        });

        function isInWindow(value) {
            return value >= valueWindow[0] && value <= valueWindow[1];
        }
    }
};

function calculateDataExtent(axisProxy, axisDim, seriesModels) {
    var dataExtent = [Infinity, -Infinity];

    each$20(seriesModels, function (seriesModel) {
        var seriesData = seriesModel.getData();
        if (seriesData) {
            each$20(seriesData.mapDimension(axisDim, true), function (dim) {
                var seriesExtent = seriesData.getApproximateExtent(dim);
                seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]);
                seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]);
            });
        }
    });

    if (dataExtent[1] < dataExtent[0]) {
        dataExtent = [NaN, NaN];
    }

    // It is important to get "consistent" extent when more then one axes is
    // controlled by a `dataZoom`, otherwise those axes will not be synchronized
    // when zooming. But it is difficult to know what is "consistent", considering
    // axes have different type or even different meanings (For example, two
    // time axes are used to compare data of the same date in different years).
    // So basically dataZoom just obtains extent by series.data (in category axis
    // extent can be obtained from axis.data).
    // Nevertheless, user can set min/max/scale on axes to make extent of axes
    // consistent.
    fixExtentByAxis(axisProxy, dataExtent);

    return dataExtent;
}

function fixExtentByAxis(axisProxy, dataExtent) {
    var axisModel = axisProxy.getAxisModel();
    var min = axisModel.getMin(true);

    // For category axis, if min/max/scale are not set, extent is determined
    // by axis.data by default.
    var isCategoryAxis = axisModel.get('type') === 'category';
    var axisDataLen = isCategoryAxis && axisModel.getCategories().length;

    if (min != null && min !== 'dataMin' && typeof min !== 'function') {
        dataExtent[0] = min;
    }
    else if (isCategoryAxis) {
        dataExtent[0] = axisDataLen > 0 ? 0 : NaN;
    }

    var max = axisModel.getMax(true);
    if (max != null && max !== 'dataMax' && typeof max !== 'function') {
        dataExtent[1] = max;
    }
    else if (isCategoryAxis) {
        dataExtent[1] = axisDataLen > 0 ? axisDataLen - 1 : NaN;
    }

    if (!axisModel.get('scale', true)) {
        dataExtent[0] > 0 && (dataExtent[0] = 0);
        dataExtent[1] < 0 && (dataExtent[1] = 0);
    }

    // For value axis, if min/max/scale are not set, we just use the extent obtained
    // by series data, which may be a little different from the extent calculated by
    // `axisHelper.getScaleExtent`. But the different just affects the experience a
    // little when zooming. So it will not be fixed until some users require it strongly.

    return dataExtent;
}

function setAxisModel(axisProxy, isRestore) {
    var axisModel = axisProxy.getAxisModel();

    var percentWindow = axisProxy._percentWindow;
    var valueWindow = axisProxy._valueWindow;

    if (!percentWindow) {
        return;
    }

    // [0, 500]: arbitrary value, guess axis extent.
    var precision = getPixelPrecision(valueWindow, [0, 500]);
    precision = Math.min(precision, 20);
    // isRestore or isFull
    var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100);

    axisModel.setRange(
        useOrigin ? null : +valueWindow[0].toFixed(precision),
        useOrigin ? null : +valueWindow[1].toFixed(precision)
    );
}

function setMinMaxSpan(axisProxy) {
    var minMaxSpan = axisProxy._minMaxSpan = {};
    var dataZoomModel = axisProxy._dataZoomModel;
    var dataExtent = axisProxy._dataExtent;

    each$20(['min', 'max'], function (minMax) {
        var percentSpan = dataZoomModel.get(minMax + 'Span');
        var valueSpan = dataZoomModel.get(minMax + 'ValueSpan');
        valueSpan != null && (valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan));

        // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
        if (valueSpan != null) {
            percentSpan = linearMap(
                dataExtent[0] + valueSpan, dataExtent, [0, 100], true
            );
        }
        else if (percentSpan != null) {
            valueSpan = linearMap(
                percentSpan, [0, 100], dataExtent, true
            ) - dataExtent[0];
        }

        minMaxSpan[minMax + 'Span'] = percentSpan;
        minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$19 = each$1;
var eachAxisDim = eachAxisDim$1;

var DataZoomModel = extendComponentModel({

    type: 'dataZoom',

    dependencies: [
        'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series'
    ],

    /**
     * @protected
     */
    defaultOption: {
        zlevel: 0,
        z: 4,                   // Higher than normal component (z: 2).
        orient: null,           // Default auto by axisIndex. Possible value: 'horizontal', 'vertical'.
        xAxisIndex: null,       // Default the first horizontal category axis.
        yAxisIndex: null,       // Default the first vertical category axis.

        filterMode: 'filter',   // Possible values: 'filter' or 'empty' or 'weakFilter'.
                                // 'filter': data items which are out of window will be removed. This option is
                                //          applicable when filtering outliers. For each data item, it will be
                                //          filtered if one of the relevant dimensions is out of the window.
                                // 'weakFilter': data items which are out of window will be removed. This option
                                //          is applicable when filtering outliers. For each data item, it will be
                                //          filtered only if all  of the relevant dimensions are out of the same
                                //          side of the window.
                                // 'empty': data items which are out of window will be set to empty.
                                //          This option is applicable when user should not neglect
                                //          that there are some data items out of window.
                                // 'none': Do not filter.
                                // Taking line chart as an example, line will be broken in
                                // the filtered points when filterModel is set to 'empty', but
                                // be connected when set to 'filter'.

        throttle: null,         // Dispatch action by the fixed rate, avoid frequency.
                                // default 100. Do not throttle when use null/undefined.
                                // If animation === true and animationDurationUpdate > 0,
                                // default value is 100, otherwise 20.
        start: 0,               // Start percent. 0 ~ 100
        end: 100,               // End percent. 0 ~ 100
        startValue: null,       // Start value. If startValue specified, start is ignored.
        endValue: null,         // End value. If endValue specified, end is ignored.
        minSpan: null,          // 0 ~ 100
        maxSpan: null,          // 0 ~ 100
        minValueSpan: null,     // The range of dataZoom can not be smaller than that.
        maxValueSpan: null,     // The range of dataZoom can not be larger than that.
        rangeMode: null         // Array, can be 'value' or 'percent'.
    },

    /**
     * @override
     */
    init: function (option, parentModel, ecModel) {

        /**
         * key like x_0, y_1
         * @private
         * @type {Object}
         */
        this._dataIntervalByAxis = {};

        /**
         * @private
         */
        this._dataInfo = {};

        /**
         * key like x_0, y_1
         * @private
         */
        this._axisProxies = {};

        /**
         * @readOnly
         */
        this.textStyleModel;

        /**
         * @private
         */
        this._autoThrottle = true;

        /**
         * It is `[rangeModeForMin, rangeModeForMax]`.
         * The optional values for `rangeMode`:
         * + `'value'` mode: the axis extent will always be determined by
         *     `dataZoom.startValue` and `dataZoom.endValue`, despite
         *     how data like and how `axis.min` and `axis.max` are.
         * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,
         *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,
         *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.
         *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.
         *
         * For example, when users are using dynamic data (update data periodically via `setOption`),
         * if in `'value`' mode, the window will be kept in a fixed value range despite how
         * data are appended, while if in `'percent'` mode, whe window range will be changed alone with
         * the appended data (suppose `axis.min` and `axis.max` are not specified).
         *
         * @private
         */
        this._rangePropMode = ['percent', 'percent'];

        var inputRawOption = retrieveRawOption(option);

        /**
         * Suppose a "main process" start at the point that model prepared (that is,
         * model initialized or merged or method called in `action`).
         * We should keep the `main process` idempotent, that is, given a set of values
         * on `option`, we get the same result.
         *
         * But sometimes, values on `option` will be updated for providing users
         * a "final calculated value" (`dataZoomProcessor` will do that). Those value
         * should not be the base/input of the `main process`.
         *
         * So in that case we should save and keep the input of the `main process`
         * separately, called `settledOption`.
         *
         * For example, consider the case:
         * (Step_1) brush zoom the grid by `toolbox.dataZoom`,
         *     where the original input `option.startValue`, `option.endValue` are earsed by
         *     calculated value.
         * (Step)2) click the legend to hide and show a series,
         *     where the new range is calculated by the earsed `startValue` and `endValue`,
         *     which brings incorrect result.
         *
         * @readOnly
         */
        this.settledOption = inputRawOption;

        this.mergeDefaultAndTheme(option, ecModel);

        this.doInit(inputRawOption);
    },

    /**
     * @override
     */
    mergeOption: function (newOption) {
        var inputRawOption = retrieveRawOption(newOption);

        //FIX #2591
        merge(this.option, newOption, true);
        merge(this.settledOption, inputRawOption, true);

        this.doInit(inputRawOption);
    },

    /**
     * @protected
     */
    doInit: function (inputRawOption) {
        var thisOption = this.option;

        // Disable realtime view update if canvas is not supported.
        if (!env$1.canvasSupported) {
            thisOption.realtime = false;
        }

        this._setDefaultThrottle(inputRawOption);

        updateRangeUse(this, inputRawOption);

        var settledOption = this.settledOption;
        each$19([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
            // start/end has higher priority over startValue/endValue if they
            // both set, but we should make chart.setOption({endValue: 1000})
            // effective, rather than chart.setOption({endValue: 1000, end: null}).
            if (this._rangePropMode[index] === 'value') {
                thisOption[names[0]] = settledOption[names[0]] = null;
            }
            // Otherwise do nothing and use the merge result.
        }, this);

        this.textStyleModel = this.getModel('textStyle');

        this._resetTarget();

        this._giveAxisProxies();
    },

    /**
     * @private
     */
    _giveAxisProxies: function () {
        var axisProxies = this._axisProxies;

        this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) {
            var axisModel = this.dependentModels[dimNames.axis][axisIndex];

            // If exists, share axisProxy with other dataZoomModels.
            var axisProxy = axisModel.__dzAxisProxy || (
                // Use the first dataZoomModel as the main model of axisProxy.
                axisModel.__dzAxisProxy = new AxisProxy(
                    dimNames.name, axisIndex, this, ecModel
                )
            );
            // FIXME
            // dispose __dzAxisProxy

            axisProxies[dimNames.name + '_' + axisIndex] = axisProxy;
        }, this);
    },

    /**
     * @private
     */
    _resetTarget: function () {
        var thisOption = this.option;

        var autoMode = this._judgeAutoMode();

        eachAxisDim(function (dimNames) {
            var axisIndexName = dimNames.axisIndex;
            thisOption[axisIndexName] = normalizeToArray(
                thisOption[axisIndexName]
            );
        }, this);

        if (autoMode === 'axisIndex') {
            this._autoSetAxisIndex();
        }
        else if (autoMode === 'orient') {
            this._autoSetOrient();
        }
    },

    /**
     * @private
     */
    _judgeAutoMode: function () {
        // Auto set only works for setOption at the first time.
        // The following is user's reponsibility. So using merged
        // option is OK.
        var thisOption = this.option;

        var hasIndexSpecified = false;
        eachAxisDim(function (dimNames) {
            // When user set axisIndex as a empty array, we think that user specify axisIndex
            // but do not want use auto mode. Because empty array may be encountered when
            // some error occured.
            if (thisOption[dimNames.axisIndex] != null) {
                hasIndexSpecified = true;
            }
        }, this);

        var orient = thisOption.orient;

        if (orient == null && hasIndexSpecified) {
            return 'orient';
        }
        else if (!hasIndexSpecified) {
            if (orient == null) {
                thisOption.orient = 'horizontal';
            }
            return 'axisIndex';
        }
    },

    /**
     * @private
     */
    _autoSetAxisIndex: function () {
        var autoAxisIndex = true;
        var orient = this.get('orient', true);
        var thisOption = this.option;
        var dependentModels = this.dependentModels;

        if (autoAxisIndex) {
            // Find axis that parallel to dataZoom as default.
            var dimName = orient === 'vertical' ? 'y' : 'x';

            if (dependentModels[dimName + 'Axis'].length) {
                thisOption[dimName + 'AxisIndex'] = [0];
                autoAxisIndex = false;
            }
            else {
                each$19(dependentModels.singleAxis, function (singleAxisModel) {
                    if (autoAxisIndex && singleAxisModel.get('orient', true) === orient) {
                        thisOption.singleAxisIndex = [singleAxisModel.componentIndex];
                        autoAxisIndex = false;
                    }
                });
            }
        }

        if (autoAxisIndex) {
            // Find the first category axis as default. (consider polar)
            eachAxisDim(function (dimNames) {
                if (!autoAxisIndex) {
                    return;
                }
                var axisIndices = [];
                var axisModels = this.dependentModels[dimNames.axis];
                if (axisModels.length && !axisIndices.length) {
                    for (var i = 0, len = axisModels.length; i < len; i++) {
                        if (axisModels[i].get('type') === 'category') {
                            axisIndices.push(i);
                        }
                    }
                }
                thisOption[dimNames.axisIndex] = axisIndices;
                if (axisIndices.length) {
                    autoAxisIndex = false;
                }
            }, this);
        }

        if (autoAxisIndex) {
            // FIXME
            // 这里是兼容ec2的写法（没指定xAxisIndex和yAxisIndex时把scatter和双数值轴折柱纳入dataZoom控制），
            // 但是实际是否需要Grid.js#getScaleByOption来判断（考虑time，log等axis type）？

            // If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified,
            // dataZoom component auto adopts series that reference to
            // both xAxis and yAxis which type is 'value'.
            this.ecModel.eachSeries(function (seriesModel) {
                if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) {
                    eachAxisDim(function (dimNames) {
                        var axisIndices = thisOption[dimNames.axisIndex];

                        var axisIndex = seriesModel.get(dimNames.axisIndex);
                        var axisId = seriesModel.get(dimNames.axisId);

                        var axisModel = seriesModel.ecModel.queryComponents({
                            mainType: dimNames.axis,
                            index: axisIndex,
                            id: axisId
                        })[0];

                        if (__DEV__) {
                            if (!axisModel) {
                                throw new Error(
                                    dimNames.axis + ' "' + retrieve(
                                        axisIndex,
                                        axisId,
                                        0
                                    ) + '" not found'
                                );
                            }
                        }
                        axisIndex = axisModel.componentIndex;

                        if (indexOf(axisIndices, axisIndex) < 0) {
                            axisIndices.push(axisIndex);
                        }
                    });
                }
            }, this);
        }
    },

    /**
     * @private
     */
    _autoSetOrient: function () {
        var dim;

        // Find the first axis
        this.eachTargetAxis(function (dimNames) {
            !dim && (dim = dimNames.name);
        }, this);

        this.option.orient = dim === 'y' ? 'vertical' : 'horizontal';
    },

    /**
     * @private
     */
    _isSeriesHasAllAxesTypeOf: function (seriesModel, axisType) {
        // FIXME
        // 需要series的xAxisIndex和yAxisIndex都首先自动设置上。
        // 例如series.type === scatter时。

        var is = true;
        eachAxisDim(function (dimNames) {
            var seriesAxisIndex = seriesModel.get(dimNames.axisIndex);
            var axisModel = this.dependentModels[dimNames.axis][seriesAxisIndex];

            if (!axisModel || axisModel.get('type') !== axisType) {
                is = false;
            }
        }, this);
        return is;
    },

    /**
     * @private
     */
    _setDefaultThrottle: function (inputRawOption) {
        // When first time user set throttle, auto throttle ends.
        if (inputRawOption.hasOwnProperty('throttle')) {
            this._autoThrottle = false;
        }
        if (this._autoThrottle) {
            var globalOption = this.ecModel.option;
            this.option.throttle = (
                globalOption.animation && globalOption.animationDurationUpdate > 0
            ) ? 100 : 20;
        }
    },

    /**
     * @public
     */
    getFirstTargetAxisModel: function () {
        var firstAxisModel;
        eachAxisDim(function (dimNames) {
            if (firstAxisModel == null) {
                var indices = this.get(dimNames.axisIndex);
                if (indices.length) {
                    firstAxisModel = this.dependentModels[dimNames.axis][indices[0]];
                }
            }
        }, this);

        return firstAxisModel;
    },

    /**
     * @public
     * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel
     */
    eachTargetAxis: function (callback, context) {
        var ecModel = this.ecModel;
        eachAxisDim(function (dimNames) {
            each$19(
                this.get(dimNames.axisIndex),
                function (axisIndex) {
                    callback.call(context, dimNames, axisIndex, this, ecModel);
                },
                this
            );
        }, this);
    },

    /**
     * @param {string} dimName
     * @param {number} axisIndex
     * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined.
     */
    getAxisProxy: function (dimName, axisIndex) {
        return this._axisProxies[dimName + '_' + axisIndex];
    },

    /**
     * @param {string} dimName
     * @param {number} axisIndex
     * @return {module:echarts/model/Model} If not found, return null/undefined.
     */
    getAxisModel: function (dimName, axisIndex) {
        var axisProxy = this.getAxisProxy(dimName, axisIndex);
        return axisProxy && axisProxy.getAxisModel();
    },

    /**
     * If not specified, set to undefined.
     *
     * @public
     * @param {Object} opt
     * @param {number} [opt.start]
     * @param {number} [opt.end]
     * @param {number} [opt.startValue]
     * @param {number} [opt.endValue]
     */
    setRawRange: function (opt) {
        var thisOption = this.option;
        var settledOption = this.settledOption;
        each$19([['start', 'startValue'], ['end', 'endValue']], function (names) {
            // Consider the pair <start, startValue>:
            // If one has value and the other one is `null/undefined`, we both set them
            // to `settledOption`. This strategy enables the feature to clear the original
            // value in `settledOption` to `null/undefined`.
            // But if both of them are `null/undefined`, we do not set them to `settledOption`
            // and keep `settledOption` with the original value. This strategy enables users to
            // only set <end or endValue> but not set <start or startValue> when calling
            // `dispatchAction`.
            // The pair <end, endValue> is treated in the same way.
            if (opt[names[0]] != null || opt[names[1]] != null) {
                thisOption[names[0]] = settledOption[names[0]] = opt[names[0]];
                thisOption[names[1]] = settledOption[names[1]] = opt[names[1]];
            }
        }, this);

        updateRangeUse(this, opt);
    },

    /**
     * @public
     * @param {Object} opt
     * @param {number} [opt.start]
     * @param {number} [opt.end]
     * @param {number} [opt.startValue]
     * @param {number} [opt.endValue]
     */
    setCalculatedRange: function (opt) {
        var option = this.option;
        each$19(['start', 'startValue', 'end', 'endValue'], function (name) {
            option[name] = opt[name];
        });
    },

    /**
     * @public
     * @return {Array.<number>} [startPercent, endPercent]
     */
    getPercentRange: function () {
        var axisProxy = this.findRepresentativeAxisProxy();
        if (axisProxy) {
            return axisProxy.getDataPercentWindow();
        }
    },

    /**
     * @public
     * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0);
     *
     * @param {string} [axisDimName]
     * @param {number} [axisIndex]
     * @return {Array.<number>} [startValue, endValue] value can only be '-' or finite number.
     */
    getValueRange: function (axisDimName, axisIndex) {
        if (axisDimName == null && axisIndex == null) {
            var axisProxy = this.findRepresentativeAxisProxy();
            if (axisProxy) {
                return axisProxy.getDataValueWindow();
            }
        }
        else {
            return this.getAxisProxy(axisDimName, axisIndex).getDataValueWindow();
        }
    },

    /**
     * @public
     * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy
     *      corresponding to the axisModel
     * @return {module:echarts/component/dataZoom/AxisProxy}
     */
    findRepresentativeAxisProxy: function (axisModel) {
        if (axisModel) {
            return axisModel.__dzAxisProxy;
        }

        // Find the first hosted axisProxy
        var axisProxies = this._axisProxies;
        for (var key in axisProxies) {
            if (axisProxies.hasOwnProperty(key) && axisProxies[key].hostedBy(this)) {
                return axisProxies[key];
            }
        }

        // If no hosted axis find not hosted axisProxy.
        // Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis,
        // and the option.start or option.end settings are different. The percentRange
        // should follow axisProxy.
        // (We encounter this problem in toolbox data zoom.)
        for (var key in axisProxies) {
            if (axisProxies.hasOwnProperty(key) && !axisProxies[key].hostedBy(this)) {
                return axisProxies[key];
            }
        }
    },

    /**
     * @return {Array.<string>}
     */
    getRangePropMode: function () {
        return this._rangePropMode.slice();
    }

});

/**
 * Retrieve the those raw params from option, which will be cached separately.
 * becasue they will be overwritten by normalized/calculated values in the main
 * process.
 */
function retrieveRawOption(option) {
    var ret = {};
    each$19(
        ['start', 'end', 'startValue', 'endValue', 'throttle'],
        function (name) {
            option.hasOwnProperty(name) && (ret[name] = option[name]);
        }
    );
    return ret;
}

function updateRangeUse(dataZoomModel, inputRawOption) {
    var rangePropMode = dataZoomModel._rangePropMode;
    var rangeModeInOption = dataZoomModel.get('rangeMode');

    each$19([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
        var percentSpecified = inputRawOption[names[0]] != null;
        var valueSpecified = inputRawOption[names[1]] != null;
        if (percentSpecified && !valueSpecified) {
            rangePropMode[index] = 'percent';
        }
        else if (!percentSpecified && valueSpecified) {
            rangePropMode[index] = 'value';
        }
        else if (rangeModeInOption) {
            rangePropMode[index] = rangeModeInOption[index];
        }
        else if (percentSpecified) { // percentSpecified && valueSpecified
            rangePropMode[index] = 'percent';
        }
        // else remain its original setting.
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DataZoomView = Component$1.extend({

    type: 'dataZoom',

    render: function (dataZoomModel, ecModel, api, payload) {
        this.dataZoomModel = dataZoomModel;
        this.ecModel = ecModel;
        this.api = api;
    },

    /**
     * Find the first target coordinate system.
     *
     * @protected
     * @return {Object} {
     *                   grid: [
     *                       {model: coord0, axisModels: [axis1, axis3], coordIndex: 1},
     *                       {model: coord1, axisModels: [axis0, axis2], coordIndex: 0},
     *                       ...
     *                   ],  // cartesians must not be null/undefined.
     *                   polar: [
     *                       {model: coord0, axisModels: [axis4], coordIndex: 0},
     *                       ...
     *                   ],  // polars must not be null/undefined.
     *                   singleAxis: [
     *                       {model: coord0, axisModels: [], coordIndex: 0}
     *                   ]
     */
    getTargetCoordInfo: function () {
        var dataZoomModel = this.dataZoomModel;
        var ecModel = this.ecModel;
        var coordSysLists = {};

        dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) {
            var axisModel = ecModel.getComponent(dimNames.axis, axisIndex);
            if (axisModel) {
                var coordModel = axisModel.getCoordSysModel();
                coordModel && save(
                    coordModel,
                    axisModel,
                    coordSysLists[coordModel.mainType] || (coordSysLists[coordModel.mainType] = []),
                    coordModel.componentIndex
                );
            }
        }, this);

        function save(coordModel, axisModel, store, coordIndex) {
            var item;
            for (var i = 0; i < store.length; i++) {
                if (store[i].model === coordModel) {
                    item = store[i];
                    break;
                }
            }
            if (!item) {
                store.push(item = {
                    model: coordModel, axisModels: [], coordIndex: coordIndex
                });
            }
            item.axisModels.push(axisModel);
        }

        return coordSysLists;
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

DataZoomModel.extend({
    type: 'dataZoom.select'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

DataZoomView.extend({
    type: 'dataZoom.select'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerProcessor({

    // `dataZoomProcessor` will only be performed in needed series. Consider if
    // there is a line series and a pie series, it is better not to update the
    // line series if only pie series is needed to be updated.
    getTargetSeries: function (ecModel) {
        var seriesModelMap = createHashMap();

        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
            dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) {
                var axisProxy = dataZoomModel.getAxisProxy(dimNames.name, axisIndex);
                each$1(axisProxy.getTargetSeriesModels(), function (seriesModel) {
                    seriesModelMap.set(seriesModel.uid, seriesModel);
                });
            });
        });

        return seriesModelMap;
    },

    modifyOutputEnd: true,

    // Consider appendData, where filter should be performed. Because data process is
    // in block mode currently, it is not need to worry about that the overallProgress
    // execute every frame.
    overallReset: function (ecModel, api) {

        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
            // We calculate window and reset axis here but not in model
            // init stage and not after action dispatch handler, because
            // reset should be called after seriesData.restoreData.
            dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) {
                dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel, api);
            });

            // Caution: data zoom filtering is order sensitive when using
            // percent range and no min/max/scale set on axis.
            // For example, we have dataZoom definition:
            // [
            //      {xAxisIndex: 0, start: 30, end: 70},
            //      {yAxisIndex: 0, start: 20, end: 80}
            // ]
            // In this case, [20, 80] of y-dataZoom should be based on data
            // that have filtered by x-dataZoom using range of [30, 70],
            // but should not be based on full raw data. Thus sliding
            // x-dataZoom will change both ranges of xAxis and yAxis,
            // while sliding y-dataZoom will only change the range of yAxis.
            // So we should filter x-axis after reset x-axis immediately,
            // and then reset y-axis and filter y-axis.
            dataZoomModel.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel) {
                dataZoomModel.getAxisProxy(dimNames.name, axisIndex).filterData(dataZoomModel, api);
            });
        });

        ecModel.eachComponent('dataZoom', function (dataZoomModel) {
            // Fullfill all of the range props so that user
            // is able to get them from chart.getOption().
            var axisProxy = dataZoomModel.findRepresentativeAxisProxy();
            var percentRange = axisProxy.getDataPercentWindow();
            var valueRange = axisProxy.getDataValueWindow();

            dataZoomModel.setCalculatedRange({
                start: percentRange[0],
                end: percentRange[1],
                startValue: valueRange[0],
                endValue: valueRange[1]
            });
        });
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerAction('dataZoom', function (payload, ecModel) {

    var linkedNodesFinder = createLinkedNodesFinder(
        bind(ecModel.eachComponent, ecModel, 'dataZoom'),
        eachAxisDim$1,
        function (model, dimNames) {
            return model.get(dimNames.axisIndex);
        }
    );

    var effectedModels = [];

    ecModel.eachComponent(
        {mainType: 'dataZoom', query: payload},
        function (model, index) {
            effectedModels.push.apply(
                effectedModels, linkedNodesFinder(model).nodes
            );
        }
    );

    each$1(effectedModels, function (dataZoomModel, index) {
        dataZoomModel.setRawRange({
            start: payload.start,
            end: payload.end,
            startValue: payload.startValue,
            endValue: payload.endValue
        });
    });

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Only work for toolbox dataZoom. User
 * MUST NOT import this module directly.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Use dataZoomSelect
var dataZoomLang = lang.toolbox.dataZoom;
var each$16 = each$1;

// Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId
var DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_';

function DataZoom(model, ecModel, api) {

    /**
     * @private
     * @type {module:echarts/component/helper/BrushController}
     */
    (this._brushController = new BrushController(api.getZr()))
        .on('brush', bind(this._onBrush, this))
        .mount();

    /**
     * @private
     * @type {boolean}
     */
    this._isZoomActive;
}

DataZoom.defaultOption = {
    show: true,
    filterMode: 'filter',
    // Icon group
    icon: {
        zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
        back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
    },
    // `zoom`, `back`
    title: clone(dataZoomLang.title)
};

var proto$4 = DataZoom.prototype;

proto$4.render = function (featureModel, ecModel, api, payload) {
    this.model = featureModel;
    this.ecModel = ecModel;
    this.api = api;

    updateZoomBtnStatus(featureModel, ecModel, this, payload, api);
    updateBackBtnStatus(featureModel, ecModel);
};

proto$4.onclick = function (ecModel, api, type) {
    handlers$1[type].call(this);
};

proto$4.remove = function (ecModel, api) {
    this._brushController.unmount();
};

proto$4.dispose = function (ecModel, api) {
    this._brushController.dispose();
};

/**
 * @private
 */
var handlers$1 = {

    zoom: function () {
        var nextActive = !this._isZoomActive;

        this.api.dispatchAction({
            type: 'takeGlobalCursor',
            key: 'dataZoomSelect',
            dataZoomSelectActive: nextActive
        });
    },

    back: function () {
        this._dispatchZoomAction(pop(this.ecModel));
    }
};

/**
 * @private
 */
proto$4._onBrush = function (areas, opt) {
    if (!opt.isEnd || !areas.length) {
        return;
    }
    var snapshot = {};
    var ecModel = this.ecModel;

    this._brushController.updateCovers([]); // remove cover

    var brushTargetManager = new BrushTargetManager(
        retrieveAxisSetting(this.model.option), ecModel, {include: ['grid']}
    );
    brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
        if (coordSys.type !== 'cartesian2d') {
            return;
        }

        var brushType = area.brushType;
        if (brushType === 'rect') {
            setBatch('x', coordSys, coordRange[0]);
            setBatch('y', coordSys, coordRange[1]);
        }
        else {
            setBatch(({lineX: 'x', lineY: 'y'})[brushType], coordSys, coordRange);
        }
    });

    push(ecModel, snapshot);

    this._dispatchZoomAction(snapshot);

    function setBatch(dimName, coordSys, minMax) {
        var axis = coordSys.getAxis(dimName);
        var axisModel = axis.model;
        var dataZoomModel = findDataZoom(dimName, axisModel, ecModel);

        // Restrict range.
        var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan();
        if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) {
            minMax = sliderMove(
                0, minMax.slice(), axis.scale.getExtent(), 0,
                minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan
            );
        }

        dataZoomModel && (snapshot[dataZoomModel.id] = {
            dataZoomId: dataZoomModel.id,
            startValue: minMax[0],
            endValue: minMax[1]
        });
    }

    function findDataZoom(dimName, axisModel, ecModel) {
        var found;
        ecModel.eachComponent({mainType: 'dataZoom', subType: 'select'}, function (dzModel) {
            var has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
            has && (found = dzModel);
        });
        return found;
    }
};

/**
 * @private
 */
proto$4._dispatchZoomAction = function (snapshot) {
    var batch = [];

    // Convert from hash map to array.
    each$16(snapshot, function (batchItem, dataZoomId) {
        batch.push(clone(batchItem));
    });

    batch.length && this.api.dispatchAction({
        type: 'dataZoom',
        from: this.uid,
        batch: batch
    });
};

function retrieveAxisSetting(option) {
    var setting = {};
    // Compatible with previous setting: null => all axis, false => no axis.
    each$1(['xAxisIndex', 'yAxisIndex'], function (name) {
        setting[name] = option[name];
        setting[name] == null && (setting[name] = 'all');
        (setting[name] === false || setting[name] === 'none') && (setting[name] = []);
    });
    return setting;
}

function updateBackBtnStatus(featureModel, ecModel) {
    featureModel.setIconStatus(
        'back',
        count(ecModel) > 1 ? 'emphasis' : 'normal'
    );
}

function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
    var zoomActive = view._isZoomActive;

    if (payload && payload.type === 'takeGlobalCursor') {
        zoomActive = payload.key === 'dataZoomSelect'
            ? payload.dataZoomSelectActive : false;
    }

    view._isZoomActive = zoomActive;

    featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal');

    var brushTargetManager = new BrushTargetManager(
        retrieveAxisSetting(featureModel.option), ecModel, {include: ['grid']}
    );

    view._brushController
        .setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) {
            return (targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared)
                ? 'lineX'
                : (!targetInfo.xAxisDeclared && targetInfo.yAxisDeclared)
                ? 'lineY'
                : 'rect';
        }))
        .enableBrush(
            zoomActive
            ? {
                brushType: 'auto',
                brushStyle: {
                    // FIXME user customized?
                    lineWidth: 0,
                    fill: 'rgba(0,0,0,0.2)'
                }
            }
            : false
        );
}


register$1('dataZoom', DataZoom);


// Create special dataZoom option for select
// FIXME consider the case of merge option, where axes options are not exists.
registerPreprocessor(function (option) {
    if (!option) {
        return;
    }

    var dataZoomOpts = option.dataZoom || (option.dataZoom = []);
    if (!isArray(dataZoomOpts)) {
        option.dataZoom = dataZoomOpts = [dataZoomOpts];
    }

    var toolboxOpt = option.toolbox;
    if (toolboxOpt) {
        // Assume there is only one toolbox
        if (isArray(toolboxOpt)) {
            toolboxOpt = toolboxOpt[0];
        }

        if (toolboxOpt && toolboxOpt.feature) {
            var dataZoomOpt = toolboxOpt.feature.dataZoom;
            // FIXME: If add dataZoom when setOption in merge mode,
            // no axis info to be added. See `test/dataZoom-extreme.html`
            addForAxis('xAxis', dataZoomOpt);
            addForAxis('yAxis', dataZoomOpt);
        }
    }

    function addForAxis(axisName, dataZoomOpt) {
        if (!dataZoomOpt) {
            return;
        }

        // Try not to modify model, because it is not merged yet.
        var axisIndicesName = axisName + 'Index';
        var givenAxisIndices = dataZoomOpt[axisIndicesName];
        if (givenAxisIndices != null
            && givenAxisIndices !== 'all'
            && !isArray(givenAxisIndices)
        ) {
            givenAxisIndices = (givenAxisIndices === false || givenAxisIndices === 'none') ? [] : [givenAxisIndices];
        }

        forEachComponent(axisName, function (axisOpt, axisIndex) {
            if (givenAxisIndices != null
                && givenAxisIndices !== 'all'
                && indexOf(givenAxisIndices, axisIndex) === -1
            ) {
                return;
            }
            var newOpt = {
                type: 'select',
                $fromToolbox: true,
                // Default to be filter
                filterMode: dataZoomOpt.filterMode || 'filter',
                // Id for merge mapping.
                id: DATA_ZOOM_ID_BASE + axisName + axisIndex
            };
            // FIXME
            // Only support one axis now.
            newOpt[axisIndicesName] = axisIndex;
            dataZoomOpts.push(newOpt);
        });
    }

    function forEachComponent(mainType, cb) {
        var opts = option[mainType];
        if (!isArray(opts)) {
            opts = opts ? [opts] : [];
        }
        each$16(opts, cb);
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var restoreLang = lang.toolbox.restore;

function Restore(model) {
    this.model = model;
}

Restore.defaultOption = {
    show: true,
    /* eslint-disable */
    icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5',
    /* eslint-enable */
    title: restoreLang.title
};

var proto$6 = Restore.prototype;

proto$6.onclick = function (ecModel, api, type) {
    clear$1(ecModel);

    api.dispatchAction({
        type: 'restore',
        from: this.uid
    });
};

register$1('restore', Restore);

registerAction(
    {type: 'restore', event: 'restore', update: 'prepareAndUpdate'},
    function (payload, ecModel) {
        ecModel.resetOption('recreate');
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentModel({

    type: 'tooltip',

    dependencies: ['axisPointer'],

    defaultOption: {
        zlevel: 0,

        z: 60,

        show: true,

        // tooltip主体内容
        showContent: true,

        // 'trigger' only works on coordinate system.
        // 'item' | 'axis' | 'none'
        trigger: 'item',

        // 'click' | 'mousemove' | 'none'
        triggerOn: 'mousemove|click',

        alwaysShowContent: false,

        displayMode: 'single', // 'single' | 'multipleByCoordSys'

        renderMode: 'auto', // 'auto' | 'html' | 'richText'
        // 'auto': use html by default, and use non-html if `document` is not defined
        // 'html': use html for tooltip
        // 'richText': use canvas, svg, and etc. for tooltip

        // 位置 {Array} | {Function}
        // position: null
        // Consider triggered from axisPointer handle, verticalAlign should be 'middle'
        // align: null,
        // verticalAlign: null,

        // 是否约束 content 在 viewRect 中。默认 false 是为了兼容以前版本。
        confine: false,

        // 内容格式器：{string}（Template） ¦ {Function}
        // formatter: null

        showDelay: 0,

        // 隐藏延迟，单位ms
        hideDelay: 100,

        // 动画变换时间，单位s
        transitionDuration: 0.4,

        enterable: false,

        // 提示背景颜色，默认为透明度为0.7的黑色
        backgroundColor: 'rgba(50,50,50,0.7)',

        // 提示边框颜色
        borderColor: '#333',

        // 提示边框圆角，单位px，默认为4
        borderRadius: 4,

        // 提示边框线宽，单位px，默认为0（无边框）
        borderWidth: 0,

        // 提示内边距，单位px，默认各方向内边距为5，
        // 接受数组分别设定上右下左边距，同css
        padding: 5,

        // Extra css text
        extraCssText: '',

        // 坐标轴指示器，坐标轴触发有效
        axisPointer: {
            // 默认为直线
            // 可选为：'line' | 'shadow' | 'cross'
            type: 'line',

            // type 为 line 的时候有效，指定 tooltip line 所在的轴，可选
            // 可选 'x' | 'y' | 'angle' | 'radius' | 'auto'
            // 默认 'auto'，会选择类型为 category 的轴，对于双数值轴，笛卡尔坐标系会默认选择 x 轴
            // 极坐标系会默认选择 angle 轴
            axis: 'auto',

            animation: 'auto',
            animationDurationUpdate: 200,
            animationEasingUpdate: 'exponentialOut',

            crossStyle: {
                color: '#999',
                width: 1,
                type: 'dashed',

                // TODO formatter
                textStyle: {}
            }

            // lineStyle and shadowStyle should not be specified here,
            // otherwise it will always override those styles on option.axisPointer.
        },
        textStyle: {
            color: '#fff',
            fontSize: 14
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$22 = each$1;
var toCamelCase$1 = toCamelCase;

var vendors = ['', '-webkit-', '-moz-', '-o-'];

var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';

/**
 * @param {number} duration
 * @return {string}
 * @inner
 */
function assembleTransition(duration) {
    var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)';
    var transitionText = 'left ' + duration + 's ' + transitionCurve + ','
                        + 'top ' + duration + 's ' + transitionCurve;
    return map(vendors, function (vendorPrefix) {
        return vendorPrefix + 'transition:' + transitionText;
    }).join(';');
}

/**
 * @param {Object} textStyle
 * @return {string}
 * @inner
 */
function assembleFont(textStyleModel) {
    var cssText = [];

    var fontSize = textStyleModel.get('fontSize');
    var color = textStyleModel.getTextColor();

    color && cssText.push('color:' + color);

    cssText.push('font:' + textStyleModel.getFont());

    fontSize
        && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');

    each$22(['decoration', 'align'], function (name) {
        var val = textStyleModel.get(name);
        val && cssText.push('text-' + name + ':' + val);
    });

    return cssText.join(';');
}

/**
 * @param {Object} tooltipModel
 * @return {string}
 * @inner
 */
function assembleCssText(tooltipModel) {

    var cssText = [];

    var transitionDuration = tooltipModel.get('transitionDuration');
    var backgroundColor = tooltipModel.get('backgroundColor');
    var textStyleModel = tooltipModel.getModel('textStyle');
    var padding = tooltipModel.get('padding');

    // Animation transition. Do not animate when transitionDuration is 0.
    transitionDuration
        && cssText.push(assembleTransition(transitionDuration));

    if (backgroundColor) {
        if (env$1.canvasSupported) {
            cssText.push('background-Color:' + backgroundColor);
        }
        else {
            // for ie
            cssText.push(
                'background-Color:#' + toHex(backgroundColor)
            );
            cssText.push('filter:alpha(opacity=70)');
        }
    }

    // Border style
    each$22(['width', 'color', 'radius'], function (name) {
        var borderName = 'border-' + name;
        var camelCase = toCamelCase$1(borderName);
        var val = tooltipModel.get(camelCase);
        val != null
            && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px'));
    });

    // Text style
    cssText.push(assembleFont(textStyleModel));

    // Padding
    if (padding != null) {
        cssText.push('padding:' + normalizeCssArray$1(padding).join('px ') + 'px');
    }

    return cssText.join(';') + ';';
}

/**
 * @alias module:echarts/component/tooltip/TooltipContent
 * @constructor
 */
function TooltipContent(container, api) {
    if (env$1.wxa) {
        return null;
    }

    var el = document.createElement('div');
    var zr = this._zr = api.getZr();

    this.el = el;

    this._x = api.getWidth() / 2;
    this._y = api.getHeight() / 2;

    container.appendChild(el);

    this._container = container;

    this._show = false;

    /**
     * @private
     */
    this._hideTimeout;

    // FIXME
    // Is it needed to trigger zr event manually if
    // the browser do not support `pointer-events: none`.

    var self = this;
    el.onmouseenter = function () {
        // clear the timeout in hideLater and keep showing tooltip
        if (self._enterable) {
            clearTimeout(self._hideTimeout);
            self._show = true;
        }
        self._inContent = true;
    };
    el.onmousemove = function (e) {
        e = e || window.event;
        if (!self._enterable) {
            // `pointer-events: none` is set to tooltip content div
            // if `enterable` is set as `false`, and `el.onmousemove`
            // can not be triggered. But in browser that do not
            // support `pointer-events`, we need to do this:
            // Try trigger zrender event to avoid mouse
            // in and out shape too frequently
            var handler = zr.handler;
            normalizeEvent(container, e, true);
            handler.dispatch('mousemove', e);
        }
    };
    el.onmouseleave = function () {
        if (self._enterable) {
            if (self._show) {
                self.hideLater(self._hideDelay);
            }
        }
        self._inContent = false;
    };
}

TooltipContent.prototype = {

    constructor: TooltipContent,

    /**
     * @private
     * @type {boolean}
     */
    _enterable: true,

    /**
     * Update when tooltip is rendered
     */
    update: function () {
        // FIXME
        // Move this logic to ec main?
        var container = this._container;
        var stl = container.currentStyle
            || document.defaultView.getComputedStyle(container);
        var domStyle = container.style;
        if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
            domStyle.position = 'relative';
        }
        // Hide the tooltip
        // PENDING
        // this.hide();
    },

    show: function (tooltipModel) {
        clearTimeout(this._hideTimeout);
        var el = this.el;

        el.style.cssText = gCssText + assembleCssText(tooltipModel)
            // Because of the reason described in:
            // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
            // we should set initial value to `left` and `top`.
            + ';left:' + this._x + 'px;top:' + this._y + 'px;'
            + (tooltipModel.get('extraCssText') || '');

        el.style.display = el.innerHTML ? 'block' : 'none';

        // If mouse occsionally move over the tooltip, a mouseout event will be
        // triggered by canvas, and cuase some unexpectable result like dragging
        // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
        // it. Although it is not suppored by IE8~IE10, fortunately it is a rare
        // scenario.
        el.style.pointerEvents = this._enterable ? 'auto' : 'none';

        this._show = true;
    },

    setContent: function (content) {
        this.el.innerHTML = content == null ? '' : content;
    },

    setEnterable: function (enterable) {
        this._enterable = enterable;
    },

    getSize: function () {
        var el = this.el;
        return [el.clientWidth, el.clientHeight];
    },

    moveTo: function (x, y) {
        // xy should be based on canvas root. But tooltipContent is
        // the sibling of canvas root. So padding of ec container
        // should be considered here.
        var zr = this._zr;
        var viewportRootOffset;
        if (zr && zr.painter && (viewportRootOffset = zr.painter.getViewportRootOffset())) {
            x += viewportRootOffset.offsetLeft;
            y += viewportRootOffset.offsetTop;
        }

        var style = this.el.style;
        style.left = x + 'px';
        style.top = y + 'px';

        this._x = x;
        this._y = y;
    },

    hide: function () {
        this.el.style.display = 'none';
        this._show = false;
    },

    hideLater: function (time) {
        if (this._show && !(this._inContent && this._enterable)) {
            if (time) {
                this._hideDelay = time;
                // Set show false to avoid invoke hideLater mutiple times
                this._show = false;
                this._hideTimeout = setTimeout(bind(this.hide, this), time);
            }
            else {
                this.hide();
            }
        }
    },

    isShow: function () {
        return this._show;
    },

    getOuterSize: function () {
        var width = this.el.clientWidth;
        var height = this.el.clientHeight;

        // Consider browser compatibility.
        // IE8 does not support getComputedStyle.
        if (document.defaultView && document.defaultView.getComputedStyle) {
            var stl = document.defaultView.getComputedStyle(this.el);
            if (stl) {
                width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10);
                height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10);
            }
        }

        return {width: width, height: height};
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// import Group from 'zrender/src/container/Group';
/**
 * @alias module:echarts/component/tooltip/TooltipRichContent
 * @constructor
 */
function TooltipRichContent(api) {

    this._zr = api.getZr();

    this._show = false;

    /**
     * @private
     */
    this._hideTimeout;
}

TooltipRichContent.prototype = {

    constructor: TooltipRichContent,

    /**
     * @private
     * @type {boolean}
     */
    _enterable: true,

    /**
     * Update when tooltip is rendered
     */
    update: function () {
        // noop
    },

    show: function (tooltipModel) {
        if (this._hideTimeout) {
            clearTimeout(this._hideTimeout);
        }

        this.el.attr('show', true);
        this._show = true;
    },

    /**
     * Set tooltip content
     *
     * @param {string} content rich text string of content
     * @param {Object} markerRich rich text style
     * @param {Object} tooltipModel tooltip model
     */
    setContent: function (content, markerRich, tooltipModel) {
        if (this.el) {
            this._zr.remove(this.el);
        }

        var markers = {};
        var text = content;
        var prefix = '{marker';
        var suffix = '|}';
        var startId = text.indexOf(prefix);
        while (startId >= 0) {
            var endId = text.indexOf(suffix);
            var name = text.substr(startId + prefix.length, endId - startId - prefix.length);
            if (name.indexOf('sub') > -1) {
                markers['marker' + name] = {
                    textWidth: 4,
                    textHeight: 4,
                    textBorderRadius: 2,
                    textBackgroundColor: markerRich[name],
                    // TODO: textOffset is not implemented for rich text
                    textOffset: [3, 0]
                };
            }
            else {
                markers['marker' + name] = {
                    textWidth: 10,
                    textHeight: 10,
                    textBorderRadius: 5,
                    textBackgroundColor: markerRich[name]
                };
            }

            text = text.substr(endId + 1);
            startId = text.indexOf('{marker');
        }

        this.el = new Text({
            style: {
                rich: markers,
                text: content,
                textLineHeight: 20,
                textBackgroundColor: tooltipModel.get('backgroundColor'),
                textBorderRadius: tooltipModel.get('borderRadius'),
                textFill: tooltipModel.get('textStyle.color'),
                textPadding: tooltipModel.get('padding')
            },
            z: tooltipModel.get('z')
        });
        this._zr.add(this.el);

        var self = this;
        this.el.on('mouseover', function () {
            // clear the timeout in hideLater and keep showing tooltip
            if (self._enterable) {
                clearTimeout(self._hideTimeout);
                self._show = true;
            }
            self._inContent = true;
        });
        this.el.on('mouseout', function () {
            if (self._enterable) {
                if (self._show) {
                    self.hideLater(self._hideDelay);
                }
            }
            self._inContent = false;
        });
    },

    setEnterable: function (enterable) {
        this._enterable = enterable;
    },

    getSize: function () {
        var bounding = this.el.getBoundingRect();
        return [bounding.width, bounding.height];
    },

    moveTo: function (x, y) {
        if (this.el) {
            this.el.attr('position', [x, y]);
        }
    },

    hide: function () {
        if (this.el) {
            this.el.hide();
        }
        this._show = false;
    },

    hideLater: function (time) {
        if (this._show && !(this._inContent && this._enterable)) {
            if (time) {
                this._hideDelay = time;
                // Set show false to avoid invoke hideLater mutiple times
                this._show = false;
                this._hideTimeout = setTimeout(bind(this.hide, this), time);
            }
            else {
                this.hide();
            }
        }
    },

    isShow: function () {
        return this._show;
    },

    getOuterSize: function () {
        var size = this.getSize();
        return {
            width: size[0],
            height: size[1]
        };
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var bind$3 = bind;
var each$21 = each$1;
var parsePercent$2 = parsePercent$1;

var proxyRect = new Rect({
    shape: {x: -1, y: -1, width: 2, height: 2}
});

extendComponentView({

    type: 'tooltip',

    init: function (ecModel, api) {
        if (env$1.node) {
            return;
        }

        var tooltipModel = ecModel.getComponent('tooltip');
        var renderMode = tooltipModel.get('renderMode');
        this._renderMode = getTooltipRenderMode(renderMode);

        var tooltipContent;
        if (this._renderMode === 'html') {
            tooltipContent = new TooltipContent(api.getDom(), api);
            this._newLine = '<br/>';
        }
        else {
            tooltipContent = new TooltipRichContent(api);
            this._newLine = '\n';
        }

        this._tooltipContent = tooltipContent;
    },

    render: function (tooltipModel, ecModel, api) {
        if (env$1.node) {
            return;
        }

        // Reset
        this.group.removeAll();

        /**
         * @private
         * @type {module:echarts/component/tooltip/TooltipModel}
         */
        this._tooltipModel = tooltipModel;

        /**
         * @private
         * @type {module:echarts/model/Global}
         */
        this._ecModel = ecModel;

        /**
         * @private
         * @type {module:echarts/ExtensionAPI}
         */
        this._api = api;

        /**
         * Should be cleaned when render.
         * @private
         * @type {Array.<Array.<Object>>}
         */
        this._lastDataByCoordSys = null;

        /**
         * @private
         * @type {boolean}
         */
        this._alwaysShowContent = tooltipModel.get('alwaysShowContent');

        var tooltipContent = this._tooltipContent;
        tooltipContent.update();
        tooltipContent.setEnterable(tooltipModel.get('enterable'));

        this._initGlobalListener();

        this._keepShow();
    },

    _initGlobalListener: function () {
        var tooltipModel = this._tooltipModel;
        var triggerOn = tooltipModel.get('triggerOn');

        register(
            'itemTooltip',
            this._api,
            bind$3(function (currTrigger, e, dispatchAction) {
                // If 'none', it is not controlled by mouse totally.
                if (triggerOn !== 'none') {
                    if (triggerOn.indexOf(currTrigger) >= 0) {
                        this._tryShow(e, dispatchAction);
                    }
                    else if (currTrigger === 'leave') {
                        this._hide(dispatchAction);
                    }
                }
            }, this)
        );
    },

    _keepShow: function () {
        var tooltipModel = this._tooltipModel;
        var ecModel = this._ecModel;
        var api = this._api;

        // Try to keep the tooltip show when refreshing
        if (this._lastX != null
            && this._lastY != null
            // When user is willing to control tooltip totally using API,
            // self.manuallyShowTip({x, y}) might cause tooltip hide,
            // which is not expected.
            && tooltipModel.get('triggerOn') !== 'none'
        ) {
            var self = this;
            clearTimeout(this._refreshUpdateTimeout);
            this._refreshUpdateTimeout = setTimeout(function () {
                // Show tip next tick after other charts are rendered
                // In case highlight action has wrong result
                // FIXME
                !api.isDisposed() && self.manuallyShowTip(tooltipModel, ecModel, api, {
                    x: self._lastX,
                    y: self._lastY
                });
            });
        }
    },

    /**
     * Show tip manually by
     * dispatchAction({
     *     type: 'showTip',
     *     x: 10,
     *     y: 10
     * });
     * Or
     * dispatchAction({
     *      type: 'showTip',
     *      seriesIndex: 0,
     *      dataIndex or dataIndexInside or name
     * });
     *
     *  TODO Batch
     */
    manuallyShowTip: function (tooltipModel, ecModel, api, payload) {
        if (payload.from === this.uid || env$1.node) {
            return;
        }

        var dispatchAction = makeDispatchAction$1(payload, api);

        // Reset ticket
        this._ticket = '';

        // When triggered from axisPointer.
        var dataByCoordSys = payload.dataByCoordSys;

        if (payload.tooltip && payload.x != null && payload.y != null) {
            var el = proxyRect;
            el.position = [payload.x, payload.y];
            el.update();
            el.tooltip = payload.tooltip;
            // Manually show tooltip while view is not using zrender elements.
            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                target: el
            }, dispatchAction);
        }
        else if (dataByCoordSys) {
            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                position: payload.position,
                event: {},
                dataByCoordSys: payload.dataByCoordSys,
                tooltipOption: payload.tooltipOption
            }, dispatchAction);
        }
        else if (payload.seriesIndex != null) {

            if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) {
                return;
            }

            var pointInfo = findPointFromSeries(payload, ecModel);
            var cx = pointInfo.point[0];
            var cy = pointInfo.point[1];
            if (cx != null && cy != null) {
                this._tryShow({
                    offsetX: cx,
                    offsetY: cy,
                    position: payload.position,
                    target: pointInfo.el,
                    event: {}
                }, dispatchAction);
            }
        }
        else if (payload.x != null && payload.y != null) {
            // FIXME
            // should wrap dispatchAction like `axisPointer/globalListener` ?
            api.dispatchAction({
                type: 'updateAxisPointer',
                x: payload.x,
                y: payload.y
            });

            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                position: payload.position,
                target: api.getZr().findHover(payload.x, payload.y).target,
                event: {}
            }, dispatchAction);
        }
    },

    manuallyHideTip: function (tooltipModel, ecModel, api, payload) {
        var tooltipContent = this._tooltipContent;

        if (!this._alwaysShowContent && this._tooltipModel) {
            tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));
        }

        this._lastX = this._lastY = null;

        if (payload.from !== this.uid) {
            this._hide(makeDispatchAction$1(payload, api));
        }
    },

    // Be compatible with previous design, that is, when tooltip.type is 'axis' and
    // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer
    // and tooltip.
    _manuallyAxisShowTip: function (tooltipModel, ecModel, api, payload) {
        var seriesIndex = payload.seriesIndex;
        var dataIndex = payload.dataIndex;
        var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

        if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) {
            return;
        }

        var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
        if (!seriesModel) {
            return;
        }

        var data = seriesModel.getData();
        var tooltipModel = buildTooltipModel([
            data.getItemModel(dataIndex),
            seriesModel,
            (seriesModel.coordinateSystem || {}).model,
            tooltipModel
        ]);

        if (tooltipModel.get('trigger') !== 'axis') {
            return;
        }

        api.dispatchAction({
            type: 'updateAxisPointer',
            seriesIndex: seriesIndex,
            dataIndex: dataIndex,
            position: payload.position
        });

        return true;
    },

    _tryShow: function (e, dispatchAction) {
        var el = e.target;
        var tooltipModel = this._tooltipModel;

        if (!tooltipModel) {
            return;
        }

        // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed
        this._lastX = e.offsetX;
        this._lastY = e.offsetY;

        var dataByCoordSys = e.dataByCoordSys;
        if (dataByCoordSys && dataByCoordSys.length) {
            this._showAxisTooltip(dataByCoordSys, e);
        }
        // Always show item tooltip if mouse is on the element with dataIndex
        else if (el && el.dataIndex != null) {
            this._lastDataByCoordSys = null;
            this._showSeriesItemTooltip(e, el, dispatchAction);
        }
        // Tooltip provided directly. Like legend.
        else if (el && el.tooltip) {
            this._lastDataByCoordSys = null;
            this._showComponentItemTooltip(e, el, dispatchAction);
        }
        else {
            this._lastDataByCoordSys = null;
            this._hide(dispatchAction);
        }
    },

    _showOrMove: function (tooltipModel, cb) {
        // showDelay is used in this case: tooltip.enterable is set
        // as true. User intent to move mouse into tooltip and click
        // something. `showDelay` makes it easyer to enter the content
        // but tooltip do not move immediately.
        var delay = tooltipModel.get('showDelay');
        cb = bind(cb, this);
        clearTimeout(this._showTimout);
        delay > 0
            ? (this._showTimout = setTimeout(cb, delay))
            : cb();
    },

    _showAxisTooltip: function (dataByCoordSys, e) {
        var ecModel = this._ecModel;
        var globalTooltipModel = this._tooltipModel;
        var point = [e.offsetX, e.offsetY];
        var singleDefaultHTML = [];
        var singleParamsList = [];
        var singleTooltipModel = buildTooltipModel([
            e.tooltipOption,
            globalTooltipModel
        ]);

        var renderMode = this._renderMode;
        var newLine = this._newLine;

        var markers = {};

        each$21(dataByCoordSys, function (itemCoordSys) {
            // var coordParamList = [];
            // var coordDefaultHTML = [];
            // var coordTooltipModel = buildTooltipModel([
            //     e.tooltipOption,
            //     itemCoordSys.tooltipOption,
            //     ecModel.getComponent(itemCoordSys.coordSysMainType, itemCoordSys.coordSysIndex),
            //     globalTooltipModel
            // ]);
            // var displayMode = coordTooltipModel.get('displayMode');
            // var paramsList = displayMode === 'single' ? singleParamsList : [];

            each$21(itemCoordSys.dataByAxis, function (item) {
                var axisModel = ecModel.getComponent(item.axisDim + 'Axis', item.axisIndex);
                var axisValue = item.value;
                var seriesDefaultHTML = [];

                if (!axisModel || axisValue == null) {
                    return;
                }

                var valueLabel = getValueLabel(
                    axisValue, axisModel.axis, ecModel,
                    item.seriesDataIndices,
                    item.valueLabelOpt
                );

                each$1(item.seriesDataIndices, function (idxItem) {
                    var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
                    var dataIndex = idxItem.dataIndexInside;
                    var dataParams = series && series.getDataParams(dataIndex);
                    dataParams.axisDim = item.axisDim;
                    dataParams.axisIndex = item.axisIndex;
                    dataParams.axisType = item.axisType;
                    dataParams.axisId = item.axisId;
                    dataParams.axisValue = getAxisRawValue(axisModel.axis, axisValue);
                    dataParams.axisValueLabel = valueLabel;

                    if (dataParams) {
                        singleParamsList.push(dataParams);
                        var seriesTooltip = series.formatTooltip(dataIndex, true, null, renderMode);

                        var html;
                        if (isObject$1(seriesTooltip)) {
                            html = seriesTooltip.html;
                            var newMarkers = seriesTooltip.markers;
                            merge(markers, newMarkers);
                        }
                        else {
                            html = seriesTooltip;
                        }
                        seriesDefaultHTML.push(html);
                    }
                });

                // Default tooltip content
                // FIXME
                // (1) shold be the first data which has name?
                // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
                var firstLine = valueLabel;
                if (renderMode !== 'html') {
                    singleDefaultHTML.push(seriesDefaultHTML.join(newLine));
                }
                else {
                    singleDefaultHTML.push(
                        (firstLine ? encodeHTML(firstLine) + newLine : '')
                        + seriesDefaultHTML.join(newLine)
                    );
                }
            });
        }, this);

        // In most case, the second axis is shown upper than the first one.
        singleDefaultHTML.reverse();
        singleDefaultHTML = singleDefaultHTML.join(this._newLine + this._newLine);

        var positionExpr = e.position;
        this._showOrMove(singleTooltipModel, function () {
            if (this._updateContentNotChangedOnAxis(dataByCoordSys)) {
                this._updatePosition(
                    singleTooltipModel,
                    positionExpr,
                    point[0], point[1],
                    this._tooltipContent,
                    singleParamsList
                );
            }
            else {
                this._showTooltipContent(
                    singleTooltipModel, singleDefaultHTML, singleParamsList, Math.random(),
                    point[0], point[1], positionExpr, undefined, markers
                );
            }
        });

        // Do not trigger events here, because this branch only be entered
        // from dispatchAction.
    },

    _showSeriesItemTooltip: function (e, el, dispatchAction) {
        var ecModel = this._ecModel;
        // Use dataModel in element if possible
        // Used when mouseover on a element like markPoint or edge
        // In which case, the data is not main data in series.
        var seriesIndex = el.seriesIndex;
        var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

        // For example, graph link.
        var dataModel = el.dataModel || seriesModel;
        var dataIndex = el.dataIndex;
        var dataType = el.dataType;
        var data = dataModel.getData();

        var tooltipModel = buildTooltipModel([
            data.getItemModel(dataIndex),
            dataModel,
            seriesModel && (seriesModel.coordinateSystem || {}).model,
            this._tooltipModel
        ]);

        var tooltipTrigger = tooltipModel.get('trigger');
        if (tooltipTrigger != null && tooltipTrigger !== 'item') {
            return;
        }

        var params = dataModel.getDataParams(dataIndex, dataType);
        var seriesTooltip = dataModel.formatTooltip(dataIndex, false, dataType, this._renderMode);
        var defaultHtml;
        var markers;
        if (isObject$1(seriesTooltip)) {
            defaultHtml = seriesTooltip.html;
            markers = seriesTooltip.markers;
        }
        else {
            defaultHtml = seriesTooltip;
            markers = null;
        }

        var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;

        this._showOrMove(tooltipModel, function () {
            this._showTooltipContent(
                tooltipModel, defaultHtml, params, asyncTicket,
                e.offsetX, e.offsetY, e.position, e.target, markers
            );
        });

        // FIXME
        // duplicated showtip if manuallyShowTip is called from dispatchAction.
        dispatchAction({
            type: 'showTip',
            dataIndexInside: dataIndex,
            dataIndex: data.getRawIndex(dataIndex),
            seriesIndex: seriesIndex,
            from: this.uid
        });
    },

    _showComponentItemTooltip: function (e, el, dispatchAction) {
        var tooltipOpt = el.tooltip;
        if (typeof tooltipOpt === 'string') {
            var content = tooltipOpt;
            tooltipOpt = {
                content: content,
                // Fixed formatter
                formatter: content
            };
        }
        var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel);
        var defaultHtml = subTooltipModel.get('content');
        var asyncTicket = Math.random();

        // Do not check whether `trigger` is 'none' here, because `trigger`
        // only works on cooridinate system. In fact, we have not found case
        // that requires setting `trigger` nothing on component yet.

        this._showOrMove(subTooltipModel, function () {
            this._showTooltipContent(
                subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {},
                asyncTicket, e.offsetX, e.offsetY, e.position, el
            );
        });

        // If not dispatch showTip, tip may be hide triggered by axis.
        dispatchAction({
            type: 'showTip',
            from: this.uid
        });
    },

    _showTooltipContent: function (
        tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markers
    ) {
        // Reset ticket
        this._ticket = '';

        if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) {
            return;
        }

        var tooltipContent = this._tooltipContent;

        var formatter = tooltipModel.get('formatter');
        positionExpr = positionExpr || tooltipModel.get('position');
        var html = defaultHtml;

        if (formatter && typeof formatter === 'string') {
            html = formatTpl(formatter, params, true);
        }
        else if (typeof formatter === 'function') {
            var callback = bind$3(function (cbTicket, html) {
                if (cbTicket === this._ticket) {
                    tooltipContent.setContent(html, markers, tooltipModel);
                    this._updatePosition(
                        tooltipModel, positionExpr, x, y, tooltipContent, params, el
                    );
                }
            }, this);
            this._ticket = asyncTicket;
            html = formatter(params, asyncTicket, callback);
        }

        tooltipContent.setContent(html, markers, tooltipModel);
        tooltipContent.show(tooltipModel);

        this._updatePosition(
            tooltipModel, positionExpr, x, y, tooltipContent, params, el
        );
    },

    /**
     * @param  {string|Function|Array.<number>|Object} positionExpr
     * @param  {number} x Mouse x
     * @param  {number} y Mouse y
     * @param  {boolean} confine Whether confine tooltip content in view rect.
     * @param  {Object|<Array.<Object>} params
     * @param  {module:zrender/Element} el target element
     * @param  {module:echarts/ExtensionAPI} api
     * @return {Array.<number>}
     */
    _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) {
        var viewWidth = this._api.getWidth();
        var viewHeight = this._api.getHeight();
        positionExpr = positionExpr || tooltipModel.get('position');

        var contentSize = content.getSize();
        var align = tooltipModel.get('align');
        var vAlign = tooltipModel.get('verticalAlign');
        var rect = el && el.getBoundingRect().clone();
        el && rect.applyTransform(el.transform);

        if (typeof positionExpr === 'function') {
            // Callback of position can be an array or a string specify the position
            positionExpr = positionExpr([x, y], params, content.el, rect, {
                viewSize: [viewWidth, viewHeight],
                contentSize: contentSize.slice()
            });
        }

        if (isArray(positionExpr)) {
            x = parsePercent$2(positionExpr[0], viewWidth);
            y = parsePercent$2(positionExpr[1], viewHeight);
        }
        else if (isObject$1(positionExpr)) {
            positionExpr.width = contentSize[0];
            positionExpr.height = contentSize[1];
            var layoutRect = getLayoutRect(
                positionExpr, {width: viewWidth, height: viewHeight}
            );
            x = layoutRect.x;
            y = layoutRect.y;
            align = null;
            // When positionExpr is left/top/right/bottom,
            // align and verticalAlign will not work.
            vAlign = null;
        }
        // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element
        else if (typeof positionExpr === 'string' && el) {
            var pos = calcTooltipPosition(
                positionExpr, rect, contentSize
            );
            x = pos[0];
            y = pos[1];
        }
        else {
            var pos = refixTooltipPosition(
                x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20
            );
            x = pos[0];
            y = pos[1];
        }

        align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0);
        vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0);

        if (tooltipModel.get('confine')) {
            var pos = confineTooltipPosition(
                x, y, content, viewWidth, viewHeight
            );
            x = pos[0];
            y = pos[1];
        }

        content.moveTo(x, y);
    },

    // FIXME
    // Should we remove this but leave this to user?
    _updateContentNotChangedOnAxis: function (dataByCoordSys) {
        var lastCoordSys = this._lastDataByCoordSys;
        var contentNotChanged = !!lastCoordSys
            && lastCoordSys.length === dataByCoordSys.length;

        contentNotChanged && each$21(lastCoordSys, function (lastItemCoordSys, indexCoordSys) {
            var lastDataByAxis = lastItemCoordSys.dataByAxis || {};
            var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {};
            var thisDataByAxis = thisItemCoordSys.dataByAxis || [];
            contentNotChanged &= lastDataByAxis.length === thisDataByAxis.length;

            contentNotChanged && each$21(lastDataByAxis, function (lastItem, indexAxis) {
                var thisItem = thisDataByAxis[indexAxis] || {};
                var lastIndices = lastItem.seriesDataIndices || [];
                var newIndices = thisItem.seriesDataIndices || [];

                contentNotChanged
                    &= lastItem.value === thisItem.value
                    && lastItem.axisType === thisItem.axisType
                    && lastItem.axisId === thisItem.axisId
                    && lastIndices.length === newIndices.length;

                contentNotChanged && each$21(lastIndices, function (lastIdxItem, j) {
                    var newIdxItem = newIndices[j];
                    contentNotChanged
                        &= lastIdxItem.seriesIndex === newIdxItem.seriesIndex
                        && lastIdxItem.dataIndex === newIdxItem.dataIndex;
                });
            });
        });

        this._lastDataByCoordSys = dataByCoordSys;

        return !!contentNotChanged;
    },

    _hide: function (dispatchAction) {
        // Do not directly hideLater here, because this behavior may be prevented
        // in dispatchAction when showTip is dispatched.

        // FIXME
        // duplicated hideTip if manuallyHideTip is called from dispatchAction.
        this._lastDataByCoordSys = null;
        dispatchAction({
            type: 'hideTip',
            from: this.uid
        });
    },

    dispose: function (ecModel, api) {
        if (env$1.node) {
            return;
        }
        this._tooltipContent.hide();
        unregister('itemTooltip', api);
    }
});


/**
 * @param {Array.<Object|module:echarts/model/Model>} modelCascade
 * From top to bottom. (the last one should be globalTooltipModel);
 */
function buildTooltipModel(modelCascade) {
    var resultModel = modelCascade.pop();
    while (modelCascade.length) {
        var tooltipOpt = modelCascade.pop();
        if (tooltipOpt) {
            if (Model.isInstance(tooltipOpt)) {
                tooltipOpt = tooltipOpt.get('tooltip', true);
            }
            // In each data item tooltip can be simply write:
            // {
            //  value: 10,
            //  tooltip: 'Something you need to know'
            // }
            if (typeof tooltipOpt === 'string') {
                tooltipOpt = {formatter: tooltipOpt};
            }
            resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel);
        }
    }
    return resultModel;
}

function makeDispatchAction$1(payload, api) {
    return payload.dispatchAction || bind(api.dispatchAction, api);
}

function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) {
    var size = content.getOuterSize();
    var width = size.width;
    var height = size.height;

    if (gapH != null) {
        if (x + width + gapH > viewWidth) {
            x -= width + gapH;
        }
        else {
            x += gapH;
        }
    }
    if (gapV != null) {
        if (y + height + gapV > viewHeight) {
            y -= height + gapV;
        }
        else {
            y += gapV;
        }
    }
    return [x, y];
}

function confineTooltipPosition(x, y, content, viewWidth, viewHeight) {
    var size = content.getOuterSize();
    var width = size.width;
    var height = size.height;

    x = Math.min(x + width, viewWidth) - width;
    y = Math.min(y + height, viewHeight) - height;
    x = Math.max(x, 0);
    y = Math.max(y, 0);

    return [x, y];
}

function calcTooltipPosition(position, rect, contentSize) {
    var domWidth = contentSize[0];
    var domHeight = contentSize[1];
    var gap = 5;
    var x = 0;
    var y = 0;
    var rectWidth = rect.width;
    var rectHeight = rect.height;
    switch (position) {
        case 'inside':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y + rectHeight / 2 - domHeight / 2;
            break;
        case 'top':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y - domHeight - gap;
            break;
        case 'bottom':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y + rectHeight + gap;
            break;
        case 'left':
            x = rect.x - domWidth - gap;
            y = rect.y + rectHeight / 2 - domHeight / 2;
            break;
        case 'right':
            x = rect.x + rectWidth + gap;
            y = rect.y + rectHeight / 2 - domHeight / 2;
    }
    return [x, y];
}

function isCenterAlign(align) {
    return align === 'center' || align === 'middle';
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// FIXME Better way to pack data in graphic element

/**
 * @action
 * @property {string} type
 * @property {number} seriesIndex
 * @property {number} dataIndex
 * @property {number} [x]
 * @property {number} [y]
 */
registerAction(
    {
        type: 'showTip',
        event: 'showTip',
        update: 'tooltip:manuallyShowTip'
    },
    // noop
    function () {}
);

registerAction(
    {
        type: 'hideTip',
        event: 'hideTip',
        update: 'tooltip:manuallyHideTip'
    },
    // noop
    function () {}
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear'];

var preprocessor$1 = function (option, isNew) {
    var brushComponents = option && option.brush;
    if (!isArray(brushComponents)) {
        brushComponents = brushComponents ? [brushComponents] : [];
    }

    if (!brushComponents.length) {
        return;
    }

    var brushComponentSpecifiedBtns = [];

    each$1(brushComponents, function (brushOpt) {
        var tbs = brushOpt.hasOwnProperty('toolbox')
            ? brushOpt.toolbox : [];

        if (tbs instanceof Array) {
            brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs);
        }
    });

    var toolbox = option && option.toolbox;

    if (isArray(toolbox)) {
        toolbox = toolbox[0];
    }
    if (!toolbox) {
        toolbox = {feature: {}};
        option.toolbox = [toolbox];
    }

    var toolboxFeature = (toolbox.feature || (toolbox.feature = {}));
    var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {});
    var brushTypes = toolboxBrush.type || (toolboxBrush.type = []);

    brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns);

    removeDuplicate(brushTypes);

    if (isNew && !brushTypes.length) {
        brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS);
    }
};

function removeDuplicate(arr) {
    var map$$1 = {};
    each$1(arr, function (val) {
        map$$1[val] = 1;
    });
    arr.length = 0;
    each$1(map$$1, function (flag, val) {
        arr.push(val);
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @file Visual solution, for consistent option specification.
 */

var each$23 = each$1;

function hasKeys(obj) {
    if (obj) {
        for (var name in obj) {
            if (obj.hasOwnProperty(name)) {
                return true;
            }
        }
    }
}

/**
 * @param {Object} option
 * @param {Array.<string>} stateList
 * @param {Function} [supplementVisualOption]
 * @return {Object} visualMappings <state, <visualType, module:echarts/visual/VisualMapping>>
 */
function createVisualMappings(option, stateList, supplementVisualOption) {
    var visualMappings = {};

    each$23(stateList, function (state) {
        var mappings = visualMappings[state] = createMappings();

        each$23(option[state], function (visualData, visualType) {
            if (!VisualMapping.isValidType(visualType)) {
                return;
            }
            var mappingOption = {
                type: visualType,
                visual: visualData
            };
            supplementVisualOption && supplementVisualOption(mappingOption, state);
            mappings[visualType] = new VisualMapping(mappingOption);

            // Prepare a alpha for opacity, for some case that opacity
            // is not supported, such as rendering using gradient color.
            if (visualType === 'opacity') {
                mappingOption = clone(mappingOption);
                mappingOption.type = 'colorAlpha';
                mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption);
            }
        });
    });

    return visualMappings;

    function createMappings() {
        var Creater = function () {};
        // Make sure hidden fields will not be visited by
        // object iteration (with hasOwnProperty checking).
        Creater.prototype.__hidden = Creater.prototype;
        var obj = new Creater();
        return obj;
    }
}

/**
 * @param {Object} thisOption
 * @param {Object} newOption
 * @param {Array.<string>} keys
 */
function replaceVisualOption(thisOption, newOption, keys) {
    // Visual attributes merge is not supported, otherwise it
    // brings overcomplicated merge logic. See #2853. So if
    // newOption has anyone of these keys, all of these keys
    // will be reset. Otherwise, all keys remain.
    var has;
    each$1(keys, function (key) {
        if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
            has = true;
        }
    });
    has && each$1(keys, function (key) {
        if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
            thisOption[key] = clone(newOption[key]);
        }
        else {
            delete thisOption[key];
        }
    });
}

/**
 * @param {Array.<string>} stateList
 * @param {Object} visualMappings <state, Object.<visualType, module:echarts/visual/VisualMapping>>
 * @param {module:echarts/data/List} list
 * @param {Function} getValueState param: valueOrIndex, return: state.
 * @param {object} [scope] Scope for getValueState
 * @param {string} [dimension] Concrete dimension, if used.
 */
// ???! handle brush?
function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) {
    var visualTypesMap = {};
    each$1(stateList, function (state) {
        var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
        visualTypesMap[state] = visualTypes;
    });

    var dataIndex;

    function getVisual(key) {
        return data.getItemVisual(dataIndex, key);
    }

    function setVisual(key, value) {
        data.setItemVisual(dataIndex, key, value);
    }

    if (dimension == null) {
        data.each(eachItem);
    }
    else {
        data.each([dimension], eachItem);
    }

    function eachItem(valueOrIndex, index) {
        dataIndex = dimension == null ? valueOrIndex : index;

        var rawDataItem = data.getRawDataItem(dataIndex);
        // Consider performance
        if (rawDataItem && rawDataItem.visualMap === false) {
            return;
        }

        var valueState = getValueState.call(scope, valueOrIndex);
        var mappings = visualMappings[valueState];
        var visualTypes = visualTypesMap[valueState];

        for (var i = 0, len = visualTypes.length; i < len; i++) {
            var type = visualTypes[i];
            mappings[type] && mappings[type].applyVisual(
                valueOrIndex, getVisual, setVisual
            );
        }
    }
}

/**
 * @param {module:echarts/data/List} data
 * @param {Array.<string>} stateList
 * @param {Object} visualMappings <state, Object.<visualType, module:echarts/visual/VisualMapping>>
 * @param {Function} getValueState param: valueOrIndex, return: state.
 * @param {number} [dim] dimension or dimension index.
 */
function incrementalApplyVisual(stateList, visualMappings, getValueState, dim) {
    var visualTypesMap = {};
    each$1(stateList, function (state) {
        var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
        visualTypesMap[state] = visualTypes;
    });

    function progress(params, data) {
        if (dim != null) {
            dim = data.getDimension(dim);
        }

        function getVisual(key) {
            return data.getItemVisual(dataIndex, key);
        }

        function setVisual(key, value) {
            data.setItemVisual(dataIndex, key, value);
        }

        var dataIndex;
        while ((dataIndex = params.next()) != null) {
            var rawDataItem = data.getRawDataItem(dataIndex);

            // Consider performance
            if (rawDataItem && rawDataItem.visualMap === false) {
                continue;
            }

            var value = dim != null
                ? data.get(dim, dataIndex, true)
                : dataIndex;

            var valueState = getValueState(value);
            var mappings = visualMappings[valueState];
            var visualTypes = visualTypesMap[valueState];

            for (var i = 0, len = visualTypes.length; i < len; i++) {
                var type = visualTypes[i];
                mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual);
            }
        }
    }

    return {progress: progress};
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Key of the first level is brushType: `line`, `rect`, `polygon`.
// Key of the second level is chart element type: `point`, `rect`.
// See moudule:echarts/component/helper/BrushController
// function param:
//      {Object} itemLayout fetch from data.getItemLayout(dataIndex)
//      {Object} selectors {point: selector, rect: selector, ...}
//      {Object} area {range: [[], [], ..], boudingRect}
// function return:
//      {boolean} Whether in the given brush.
var selector = {
    lineX: getLineSelectors(0),
    lineY: getLineSelectors(1),
    rect: {
        point: function (itemLayout, selectors, area) {
            return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]);
        },
        rect: function (itemLayout, selectors, area) {
            return itemLayout && area.boundingRect.intersect(itemLayout);
        }
    },
    polygon: {
        point: function (itemLayout, selectors, area) {
            return itemLayout
                && area.boundingRect.contain(itemLayout[0], itemLayout[1])
                && contain$1(area.range, itemLayout[0], itemLayout[1]);
        },
        rect: function (itemLayout, selectors, area) {
            var points = area.range;

            if (!itemLayout || points.length <= 1) {
                return false;
            }

            var x = itemLayout.x;
            var y = itemLayout.y;
            var width = itemLayout.width;
            var height = itemLayout.height;
            var p = points[0];

            if (contain$1(points, x, y)
                || contain$1(points, x + width, y)
                || contain$1(points, x, y + height)
                || contain$1(points, x + width, y + height)
                || BoundingRect.create(itemLayout).contain(p[0], p[1])
                || linePolygonIntersect(x, y, x + width, y, points)
                || linePolygonIntersect(x, y, x, y + height, points)
                || linePolygonIntersect(x + width, y, x + width, y + height, points)
                || linePolygonIntersect(x, y + height, x + width, y + height, points)
            ) {
                return true;
            }
        }
    }
};

function getLineSelectors(xyIndex) {
    var xy = ['x', 'y'];
    var wh = ['width', 'height'];

    return {
        point: function (itemLayout, selectors, area) {
            if (itemLayout) {
                var range = area.range;
                var p = itemLayout[xyIndex];
                return inLineRange(p, range);
            }
        },
        rect: function (itemLayout, selectors, area) {
            if (itemLayout) {
                var range = area.range;
                var layoutRange = [
                    itemLayout[xy[xyIndex]],
                    itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]]
                ];
                layoutRange[1] < layoutRange[0] && layoutRange.reverse();
                return inLineRange(layoutRange[0], range)
                    || inLineRange(layoutRange[1], range)
                    || inLineRange(range[0], layoutRange)
                    || inLineRange(range[1], layoutRange);
            }
        }
    };
}

function inLineRange(p, range) {
    return range[0] <= p && p <= range[1];
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var STATE_LIST = ['inBrush', 'outOfBrush'];
var DISPATCH_METHOD = '__ecBrushSelect';
var DISPATCH_FLAG = '__ecInBrushSelectEvent';
var PRIORITY_BRUSH = PRIORITY.VISUAL.BRUSH;

/**
 * Layout for visual, the priority higher than other layout, and before brush visual.
 */
registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) {
    ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {

        payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(
            payload.key === 'brush' ? payload.brushOption : {brushType: false}
        );

        var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);

        brushTargetManager.setInputRanges(brushModel.areas, ecModel);
    });
});

/**
 * Register the visual encoding if this modules required.
 */
registerVisual(PRIORITY_BRUSH, function (ecModel, api, payload) {

    var brushSelected = [];
    var throttleType;
    var throttleDelay;

    ecModel.eachComponent({mainType: 'brush'}, function (brushModel, brushIndex) {

        var thisBrushSelected = {
            brushId: brushModel.id,
            brushIndex: brushIndex,
            brushName: brushModel.name,
            areas: clone(brushModel.areas),
            selected: []
        };
        // Every brush component exists in event params, convenient
        // for user to find by index.
        brushSelected.push(thisBrushSelected);

        var brushOption = brushModel.option;
        var brushLink = brushOption.brushLink;
        var linkedSeriesMap = [];
        var selectedDataIndexForLink = [];
        var rangeInfoBySeries = [];
        var hasBrushExists = 0;

        if (!brushIndex) { // Only the first throttle setting works.
            throttleType = brushOption.throttleType;
            throttleDelay = brushOption.throttleDelay;
        }

        // Add boundingRect and selectors to range.
        var areas = map(brushModel.areas, function (area) {
            return bindSelector(
                defaults(
                    {boundingRect: boundingRectBuilders[area.brushType](area)},
                    area
                )
            );
        });

        var visualMappings = createVisualMappings(
            brushModel.option, STATE_LIST, function (mappingOption) {
                mappingOption.mappingMethod = 'fixed';
            }
        );

        isArray(brushLink) && each$1(brushLink, function (seriesIndex) {
            linkedSeriesMap[seriesIndex] = 1;
        });

        function linkOthers(seriesIndex) {
            return brushLink === 'all' || linkedSeriesMap[seriesIndex];
        }

        // If no supported brush or no brush on the series,
        // all visuals should be in original state.
        function brushed(rangeInfoList) {
            return !!rangeInfoList.length;
        }

        /**
         * Logic for each series: (If the logic has to be modified one day, do it carefully!)
         *
         * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers  ) => StepA: ┬record, ┬ StepB: ┬visualByRecord.
         *   !brushed┘    ├hasBrushExist ┤                            └nothing,┘        ├visualByRecord.
         *                └!hasBrushExist┘                                              └nothing.
         * ( !brushed  && ┬hasBrushExist ┬ && linkOthers  ) => StepA:  nothing,  StepB: ┬visualByRecord.
         *                └!hasBrushExist┘                                              └nothing.
         * ( brushed ┬ &&                     !linkOthers ) => StepA:  nothing,  StepB: ┬visualByCheck.
         *   !brushed┘                                                                  └nothing.
         * ( !brushed  &&                     !linkOthers ) => StepA:  nothing,  StepB:  nothing.
         */

        // Step A
        ecModel.eachSeries(function (seriesModel, seriesIndex) {
            var rangeInfoList = rangeInfoBySeries[seriesIndex] = [];

            seriesModel.subType === 'parallel'
                ? stepAParallel(seriesModel, seriesIndex, rangeInfoList)
                : stepAOthers(seriesModel, seriesIndex, rangeInfoList);
        });

        function stepAParallel(seriesModel, seriesIndex) {
            var coordSys = seriesModel.coordinateSystem;
            hasBrushExists |= coordSys.hasAxisBrushed();

            linkOthers(seriesIndex) && coordSys.eachActiveState(
                seriesModel.getData(),
                function (activeState, dataIndex) {
                    activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1);
                }
            );
        }

        function stepAOthers(seriesModel, seriesIndex, rangeInfoList) {
            var selectorsByBrushType = getSelectorsByBrushType(seriesModel);
            if (!selectorsByBrushType || brushModelNotControll(brushModel, seriesIndex)) {
                return;
            }

            each$1(areas, function (area) {
                selectorsByBrushType[area.brushType]
                    && brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)
                    && rangeInfoList.push(area);
                hasBrushExists |= brushed(rangeInfoList);
            });

            if (linkOthers(seriesIndex) && brushed(rangeInfoList)) {
                var data = seriesModel.getData();
                data.each(function (dataIndex) {
                    if (checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)) {
                        selectedDataIndexForLink[dataIndex] = 1;
                    }
                });
            }
        }

        // Step B
        ecModel.eachSeries(function (seriesModel, seriesIndex) {
            var seriesBrushSelected = {
                seriesId: seriesModel.id,
                seriesIndex: seriesIndex,
                seriesName: seriesModel.name,
                dataIndex: []
            };
            // Every series exists in event params, convenient
            // for user to find series by seriesIndex.
            thisBrushSelected.selected.push(seriesBrushSelected);

            var selectorsByBrushType = getSelectorsByBrushType(seriesModel);
            var rangeInfoList = rangeInfoBySeries[seriesIndex];

            var data = seriesModel.getData();
            var getValueState = linkOthers(seriesIndex)
                ? function (dataIndex) {
                    return selectedDataIndexForLink[dataIndex]
                        ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush')
                        : 'outOfBrush';
                }
                : function (dataIndex) {
                    return checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)
                        ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush')
                        : 'outOfBrush';
                };

            // If no supported brush or no brush, all visuals are in original state.
            (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList))
                && applyVisual(
                    STATE_LIST, visualMappings, data, getValueState
                );
        });

    });

    dispatchAction(api, throttleType, throttleDelay, brushSelected, payload);
});

function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) {
    // This event will not be triggered when `setOpion`, otherwise dead lock may
    // triggered when do `setOption` in event listener, which we do not find
    // satisfactory way to solve yet. Some considered resolutions:
    // (a) Diff with prevoius selected data ant only trigger event when changed.
    // But store previous data and diff precisely (i.e., not only by dataIndex, but
    // also detect value changes in selected data) might bring complexity or fragility.
    // (b) Use spectial param like `silent` to suppress event triggering.
    // But such kind of volatile param may be weird in `setOption`.
    if (!payload) {
        return;
    }

    var zr = api.getZr();
    if (zr[DISPATCH_FLAG]) {
        return;
    }

    if (!zr[DISPATCH_METHOD]) {
        zr[DISPATCH_METHOD] = doDispatch;
    }

    var fn = createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType);

    fn(api, brushSelected);
}

function doDispatch(api, brushSelected) {
    if (!api.isDisposed()) {
        var zr = api.getZr();
        zr[DISPATCH_FLAG] = true;
        api.dispatchAction({
            type: 'brushSelect',
            batch: brushSelected
        });
        zr[DISPATCH_FLAG] = false;
    }
}

function checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) {
    for (var i = 0, len = rangeInfoList.length; i < len; i++) {
        var area = rangeInfoList[i];
        if (selectorsByBrushType[area.brushType](
            dataIndex, data, area.selectors, area
        )) {
            return true;
        }
    }
}

function getSelectorsByBrushType(seriesModel) {
    var brushSelector = seriesModel.brushSelector;
    if (isString(brushSelector)) {
        var sels = [];
        each$1(selector, function (selectorsByElementType, brushType) {
            sels[brushType] = function (dataIndex, data, selectors, area) {
                var itemLayout = data.getItemLayout(dataIndex);
                return selectorsByElementType[brushSelector](itemLayout, selectors, area);
            };
        });
        return sels;
    }
    else if (isFunction$1(brushSelector)) {
        var bSelector = {};
        each$1(selector, function (sel, brushType) {
            bSelector[brushType] = brushSelector;
        });
        return bSelector;
    }
    return brushSelector;
}

function brushModelNotControll(brushModel, seriesIndex) {
    var seriesIndices = brushModel.option.seriesIndex;
    return seriesIndices != null
        && seriesIndices !== 'all'
        && (
            isArray(seriesIndices)
            ? indexOf(seriesIndices, seriesIndex) < 0
            : seriesIndex !== seriesIndices
        );
}

function bindSelector(area) {
    var selectors = area.selectors = {};
    each$1(selector[area.brushType], function (selFn, elType) {
        // Do not use function binding or curry for performance.
        selectors[elType] = function (itemLayout) {
            return selFn(itemLayout, selectors, area);
        };
    });
    return area;
}

var boundingRectBuilders = {

    lineX: noop,

    lineY: noop,

    rect: function (area) {
        return getBoundingRectFromMinMax(area.range);
    },

    polygon: function (area) {
        var minMax;
        var range = area.range;

        for (var i = 0, len = range.length; i < len; i++) {
            minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]];
            var rg = range[i];
            rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]);
            rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]);
            rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]);
            rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]);
        }

        return minMax && getBoundingRectFromMinMax(minMax);
    }
};

function getBoundingRectFromMinMax(minMax) {
    return new BoundingRect(
        minMax[0][0],
        minMax[1][0],
        minMax[0][1] - minMax[0][0],
        minMax[1][1] - minMax[1][0]
    );
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var DEFAULT_OUT_OF_BRUSH_COLOR = ['#ddd'];

var BrushModel = extendComponentModel({

    type: 'brush',

    dependencies: ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'],

    /**
     * @protected
     */
    defaultOption: {
        // inBrush: null,
        // outOfBrush: null,
        toolbox: null,          // Default value see preprocessor.
        brushLink: null,        // Series indices array, broadcast using dataIndex.
                                // or 'all', which means all series. 'none' or null means no series.
        seriesIndex: 'all',     // seriesIndex array, specify series controlled by this brush component.
        geoIndex: null,         //
        xAxisIndex: null,
        yAxisIndex: null,

        brushType: 'rect',      // Default brushType, see BrushController.
        brushMode: 'single',    // Default brushMode, 'single' or 'multiple'
        transformable: true,    // Default transformable.
        brushStyle: {           // Default brushStyle
            borderWidth: 1,
            color: 'rgba(120,140,180,0.3)',
            borderColor: 'rgba(120,140,180,0.8)'
        },

        throttleType: 'fixRate', // Throttle in brushSelected event. 'fixRate' or 'debounce'.
                                 // If null, no throttle. Valid only in the first brush component
        throttleDelay: 0,        // Unit: ms, 0 means every event will be triggered.

        // FIXME
        // 试验效果
        removeOnClick: true,

        z: 10000
    },

    /**
     * @readOnly
     * @type {Array.<Object>}
     */
    areas: [],

    /**
     * Current activated brush type.
     * If null, brush is inactived.
     * see module:echarts/component/helper/BrushController
     * @readOnly
     * @type {string}
     */
    brushType: null,

    /**
     * Current brush opt.
     * see module:echarts/component/helper/BrushController
     * @readOnly
     * @type {Object}
     */
    brushOption: {},

    /**
     * @readOnly
     * @type {Array.<Object>}
     */
    coordInfoList: [],

    optionUpdated: function (newOption, isInit) {
        var thisOption = this.option;

        !isInit && replaceVisualOption(
            thisOption, newOption, ['inBrush', 'outOfBrush']
        );

        var inBrush = thisOption.inBrush = thisOption.inBrush || {};
        // Always give default visual, consider setOption at the second time.
        thisOption.outOfBrush = thisOption.outOfBrush || {color: DEFAULT_OUT_OF_BRUSH_COLOR};

        if (!inBrush.hasOwnProperty('liftZ')) {
            // Bigger than the highlight z lift, otherwise it will
            // be effected by the highlight z when brush.
            inBrush.liftZ = 5;
        }
    },

    /**
     * If ranges is null/undefined, range state remain.
     *
     * @param {Array.<Object>} [ranges]
     */
    setAreas: function (areas) {
        if (__DEV__) {
            assert$1(isArray(areas));
            each$1(areas, function (area) {
                assert$1(area.brushType, 'Illegal areas');
            });
        }

        // If ranges is null/undefined, range state remain.
        // This helps user to dispatchAction({type: 'brush'}) with no areas
        // set but just want to get the current brush select info from a `brush` event.
        if (!areas) {
            return;
        }

        this.areas = map(areas, function (area) {
            return generateBrushOption(this.option, area);
        }, this);
    },

    /**
     * see module:echarts/component/helper/BrushController
     * @param {Object} brushOption
     */
    setBrushOption: function (brushOption) {
        this.brushOption = generateBrushOption(this.option, brushOption);
        this.brushType = this.brushOption.brushType;
    }

});

function generateBrushOption(option, brushOption) {
    return merge(
        {
            brushType: option.brushType,
            brushMode: option.brushMode,
            transformable: option.transformable,
            brushStyle: new Model(option.brushStyle).getItemStyle(),
            removeOnClick: option.removeOnClick,
            z: option.z
        },
        brushOption,
        true
    );
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

extendComponentView({

    type: 'brush',

    init: function (ecModel, api) {

        /**
         * @readOnly
         * @type {module:echarts/model/Global}
         */
        this.ecModel = ecModel;

        /**
         * @readOnly
         * @type {module:echarts/ExtensionAPI}
         */
        this.api = api;

        /**
         * @readOnly
         * @type {module:echarts/component/brush/BrushModel}
         */
        this.model;

        /**
         * @private
         * @type {module:echarts/component/helper/BrushController}
         */
        (this._brushController = new BrushController(api.getZr()))
            .on('brush', bind(this._onBrush, this))
            .mount();
    },

    /**
     * @override
     */
    render: function (brushModel) {
        this.model = brushModel;
        return updateController.apply(this, arguments);
    },

    /**
     * @override
     */
    updateTransform: updateController,

    /**
     * @override
     */
    updateView: updateController,

    // /**
    //  * @override
    //  */
    // updateLayout: updateController,

    // /**
    //  * @override
    //  */
    // updateVisual: updateController,

    /**
     * @override
     */
    dispose: function () {
        this._brushController.dispose();
    },

    /**
     * @private
     */
    _onBrush: function (areas, opt) {
        var modelId = this.model.id;

        this.model.brushTargetManager.setOutputRanges(areas, this.ecModel);

        // Action is not dispatched on drag end, because the drag end
        // emits the same params with the last drag move event, and
        // may have some delay when using touch pad, which makes
        // animation not smooth (when using debounce).
        (!opt.isEnd || opt.removeOnClick) && this.api.dispatchAction({
            type: 'brush',
            brushId: modelId,
            areas: clone(areas),
            $from: modelId
        });
        opt.isEnd && this.api.dispatchAction({
            type: 'brushEnd',
            brushId: modelId,
            areas: clone(areas),
            $from: modelId
        });
    }

});

function updateController(brushModel, ecModel, api, payload) {
    // Do not update controller when drawing.
    (!payload || payload.$from !== brushModel.id) && this._brushController
        .setPanels(brushModel.brushTargetManager.makePanelOpts(api))
        .enableBrush(brushModel.brushOption)
        .updateCovers(brushModel.areas.slice());
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * payload: {
 *      brushIndex: number, or,
 *      brushId: string, or,
 *      brushName: string,
 *      globalRanges: Array
 * }
 */
registerAction(
        {type: 'brush', event: 'brush' /*, update: 'updateView' */},
    function (payload, ecModel) {
        ecModel.eachComponent({mainType: 'brush', query: payload}, function (brushModel) {
            brushModel.setAreas(payload.areas);
        });
    }
);

/**
 * payload: {
 *      brushComponents: [
 *          {
 *              brushId,
 *              brushIndex,
 *              brushName,
 *              series: [
 *                  {
 *                      seriesId,
 *                      seriesIndex,
 *                      seriesName,
 *                      rawIndices: [21, 34, ...]
 *                  },
 *                  ...
 *              ]
 *          },
 *          ...
 *      ]
 * }
 */
registerAction(
    {type: 'brushSelect', event: 'brushSelected', update: 'none'},
    function () {}
);

registerAction(
    {type: 'brushEnd', event: 'brushEnd', update: 'none'},
    function () {}
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var brushLang = lang.toolbox.brush;

function Brush(model, ecModel, api) {
    this.model = model;
    this.ecModel = ecModel;
    this.api = api;

    /**
     * @private
     * @type {string}
     */
    this._brushType;

    /**
     * @private
     * @type {string}
     */
    this._brushMode;
}

Brush.defaultOption = {
    show: true,
    type: ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'],
    icon: {
        /* eslint-disable */
        rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line
        polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line
        lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line
        lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line
        keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line
        clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line
        /* eslint-enable */
    },
    // `rect`, `polygon`, `lineX`, `lineY`, `keep`, `clear`
    title: clone(brushLang.title)
};

var proto$7 = Brush.prototype;

// proto.updateLayout = function (featureModel, ecModel, api) {
/* eslint-disable */
proto$7.render =
/* eslint-enable */
proto$7.updateView = function (featureModel, ecModel, api) {
    var brushType;
    var brushMode;
    var isBrushed;

    ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {
        brushType = brushModel.brushType;
        brushMode = brushModel.brushOption.brushMode || 'single';
        isBrushed |= brushModel.areas.length;
    });
    this._brushType = brushType;
    this._brushMode = brushMode;

    each$1(featureModel.get('type', true), function (type) {
        featureModel.setIconStatus(
            type,
            (
                type === 'keep'
                ? brushMode === 'multiple'
                : type === 'clear'
                ? isBrushed
                : type === brushType
            ) ? 'emphasis' : 'normal'
        );
    });
};

proto$7.getIcons = function () {
    var model = this.model;
    var availableIcons = model.get('icon', true);
    var icons = {};
    each$1(model.get('type', true), function (type) {
        if (availableIcons[type]) {
            icons[type] = availableIcons[type];
        }
    });
    return icons;
};

proto$7.onclick = function (ecModel, api, type) {
    var brushType = this._brushType;
    var brushMode = this._brushMode;

    if (type === 'clear') {
        // Trigger parallel action firstly
        api.dispatchAction({
            type: 'axisAreaSelect',
            intervals: []
        });

        api.dispatchAction({
            type: 'brush',
            command: 'clear',
            // Clear all areas of all brush components.
            areas: []
        });
    }
    else {
        api.dispatchAction({
            type: 'takeGlobalCursor',
            key: 'brush',
            brushOption: {
                brushType: type === 'keep'
                    ? brushType
                    : (brushType === type ? false : type),
                brushMode: type === 'keep'
                    ? (brushMode === 'multiple' ? 'single' : 'multiple')
                    : brushMode
            }
        });
    }
};

register$1('brush', Brush);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Brush component entry
 */

registerPreprocessor(preprocessor$1);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Model
extendComponentModel({

    type: 'title',

    layoutMode: {type: 'box', ignoreSize: true},

    defaultOption: {
        // 一级层叠
        zlevel: 0,
        // 二级层叠
        z: 6,
        show: true,

        text: '',
        // 超链接跳转
        // link: null,
        // 仅支持self | blank
        target: 'blank',
        subtext: '',

        // 超链接跳转
        // sublink: null,
        // 仅支持self | blank
        subtarget: 'blank',

        // 'center' ¦ 'left' ¦ 'right'
        // ¦ {number}（x坐标，单位px）
        left: 0,
        // 'top' ¦ 'bottom' ¦ 'center'
        // ¦ {number}（y坐标，单位px）
        top: 0,

        // 水平对齐
        // 'auto' | 'left' | 'right' | 'center'
        // 默认根据 left 的位置判断是左对齐还是右对齐
        // textAlign: null
        //
        // 垂直对齐
        // 'auto' | 'top' | 'bottom' | 'middle'
        // 默认根据 top 位置判断是上对齐还是下对齐
        // textVerticalAlign: null
        // textBaseline: null // The same as textVerticalAlign.

        backgroundColor: 'rgba(0,0,0,0)',

        // 标题边框颜色
        borderColor: '#ccc',

        // 标题边框线宽，单位px，默认为0（无边框）
        borderWidth: 0,

        // 标题内边距，单位px，默认各方向内边距为5，
        // 接受数组分别设定上右下左边距，同css
        padding: 5,

        // 主副标题纵向间隔，单位px，默认为10，
        itemGap: 10,
        textStyle: {
            fontSize: 18,
            fontWeight: 'bolder',
            color: '#333'
        },
        subtextStyle: {
            color: '#aaa'
        }
    }
});

// View
extendComponentView({

    type: 'title',

    render: function (titleModel, ecModel, api) {
        this.group.removeAll();

        if (!titleModel.get('show')) {
            return;
        }

        var group = this.group;

        var textStyleModel = titleModel.getModel('textStyle');
        var subtextStyleModel = titleModel.getModel('subtextStyle');

        var textAlign = titleModel.get('textAlign');
        var textVerticalAlign = retrieve2(
            titleModel.get('textBaseline'), titleModel.get('textVerticalAlign')
        );

        var textEl = new Text({
            style: setTextStyle({}, textStyleModel, {
                text: titleModel.get('text'),
                textFill: textStyleModel.getTextColor()
            }, {disableBox: true}),
            z2: 10
        });

        var textRect = textEl.getBoundingRect();

        var subText = titleModel.get('subtext');
        var subTextEl = new Text({
            style: setTextStyle({}, subtextStyleModel, {
                text: subText,
                textFill: subtextStyleModel.getTextColor(),
                y: textRect.height + titleModel.get('itemGap'),
                textVerticalAlign: 'top'
            }, {disableBox: true}),
            z2: 10
        });

        var link = titleModel.get('link');
        var sublink = titleModel.get('sublink');
        var triggerEvent = titleModel.get('triggerEvent', true);

        textEl.silent = !link && !triggerEvent;
        subTextEl.silent = !sublink && !triggerEvent;

        if (link) {
            textEl.on('click', function () {
                window.open(link, '_' + titleModel.get('target'));
            });
        }
        if (sublink) {
            subTextEl.on('click', function () {
                window.open(sublink, '_' + titleModel.get('subtarget'));
            });
        }

        textEl.eventData = subTextEl.eventData = triggerEvent
            ? {
                componentType: 'title',
                componentIndex: titleModel.componentIndex
            }
            : null;

        group.add(textEl);
        subText && group.add(subTextEl);
        // If no subText, but add subTextEl, there will be an empty line.

        var groupRect = group.getBoundingRect();
        var layoutOption = titleModel.getBoxLayoutParams();
        layoutOption.width = groupRect.width;
        layoutOption.height = groupRect.height;
        var layoutRect = getLayoutRect(
            layoutOption, {
                width: api.getWidth(),
                height: api.getHeight()
            }, titleModel.get('padding')
        );
        // Adjust text align based on position
        if (!textAlign) {
            // Align left if title is on the left. center and right is same
            textAlign = titleModel.get('left') || titleModel.get('right');
            if (textAlign === 'middle') {
                textAlign = 'center';
            }
            // Adjust layout by text align
            if (textAlign === 'right') {
                layoutRect.x += layoutRect.width;
            }
            else if (textAlign === 'center') {
                layoutRect.x += layoutRect.width / 2;
            }
        }
        if (!textVerticalAlign) {
            textVerticalAlign = titleModel.get('top') || titleModel.get('bottom');
            if (textVerticalAlign === 'center') {
                textVerticalAlign = 'middle';
            }
            if (textVerticalAlign === 'bottom') {
                layoutRect.y += layoutRect.height;
            }
            else if (textVerticalAlign === 'middle') {
                layoutRect.y += layoutRect.height / 2;
            }

            textVerticalAlign = textVerticalAlign || 'top';
        }

        group.attr('position', [layoutRect.x, layoutRect.y]);
        var alignStyle = {
            textAlign: textAlign,
            textVerticalAlign: textVerticalAlign
        };
        textEl.setStyle(alignStyle);
        subTextEl.setStyle(alignStyle);

        // Render background
        // Get groupRect again because textAlign has been changed
        groupRect = group.getBoundingRect();
        var padding = layoutRect.margin;
        var style = titleModel.getItemStyle(['color', 'opacity']);
        style.fill = titleModel.get('backgroundColor');
        var rect = new Rect({
            shape: {
                x: groupRect.x - padding[3],
                y: groupRect.y - padding[0],
                width: groupRect.width + padding[1] + padding[3],
                height: groupRect.height + padding[0] + padding[2],
                r: titleModel.get('borderRadius')
            },
            style: style,
            subPixelOptimize: true,
            silent: true
        });

        group.add(rect);
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var preprocessor$2 = function (option) {
    var timelineOpt = option && option.timeline;

    if (!isArray(timelineOpt)) {
        timelineOpt = timelineOpt ? [timelineOpt] : [];
    }

    each$1(timelineOpt, function (opt) {
        if (!opt) {
            return;
        }

        compatibleEC2(opt);
    });
};

function compatibleEC2(opt) {
    var type = opt.type;

    var ec2Types = {'number': 'value', 'time': 'time'};

    // Compatible with ec2
    if (ec2Types[type]) {
        opt.axisType = ec2Types[type];
        delete opt.type;
    }

    transferItem(opt);

    if (has$1(opt, 'controlPosition')) {
        var controlStyle = opt.controlStyle || (opt.controlStyle = {});
        if (!has$1(controlStyle, 'position')) {
            controlStyle.position = opt.controlPosition;
        }
        if (controlStyle.position === 'none' && !has$1(controlStyle, 'show')) {
            controlStyle.show = false;
            delete controlStyle.position;
        }
        delete opt.controlPosition;
    }

    each$1(opt.data || [], function (dataItem) {
        if (isObject$1(dataItem) && !isArray(dataItem)) {
            if (!has$1(dataItem, 'value') && has$1(dataItem, 'name')) {
                // In ec2, using name as value.
                dataItem.value = dataItem.name;
            }
            transferItem(dataItem);
        }
    });
}

function transferItem(opt) {
    var itemStyle = opt.itemStyle || (opt.itemStyle = {});

    var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {});

    // Transfer label out
    var label = opt.label || (opt.label || {});
    var labelNormal = label.normal || (label.normal = {});
    var excludeLabelAttr = {normal: 1, emphasis: 1};

    each$1(label, function (value, name) {
        if (!excludeLabelAttr[name] && !has$1(labelNormal, name)) {
            labelNormal[name] = value;
        }
    });

    if (itemStyleEmphasis.label && !has$1(label, 'emphasis')) {
        label.emphasis = itemStyleEmphasis.label;
        delete itemStyleEmphasis.label;
    }
}

function has$1(obj, attr) {
    return obj.hasOwnProperty(attr);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

ComponentModel.registerSubTypeDefaulter('timeline', function () {
    // Only slider now.
    return 'slider';
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerAction(

    {type: 'timelineChange', event: 'timelineChanged', update: 'prepareAndUpdate'},

    function (payload, ecModel) {

        var timelineModel = ecModel.getComponent('timeline');
        if (timelineModel && payload.currentIndex != null) {
            timelineModel.setCurrentIndex(payload.currentIndex);

            if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) {
                timelineModel.setPlayState(false);
            }
        }

        // Set normalized currentIndex to payload.
        ecModel.resetOption('timeline');

        return defaults({
            currentIndex: timelineModel.option.currentIndex
        }, payload);
    }
);

registerAction(

    {type: 'timelinePlayChange', event: 'timelinePlayChanged', update: 'update'},

    function (payload, ecModel) {
        var timelineModel = ecModel.getComponent('timeline');
        if (timelineModel && payload.playState != null) {
            timelineModel.setPlayState(payload.playState);
        }
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var TimelineModel = ComponentModel.extend({

    type: 'timeline',

    layoutMode: 'box',

    /**
     * @protected
     */
    defaultOption: {

        zlevel: 0,                  // 一级层叠
        z: 4,                       // 二级层叠
        show: true,

        axisType: 'time',  // 模式是时间类型，支持 value, category

        realtime: true,

        left: '20%',
        top: null,
        right: '20%',
        bottom: 0,
        width: null,
        height: 40,
        padding: 5,

        controlPosition: 'left',           // 'left' 'right' 'top' 'bottom' 'none'
        autoPlay: false,
        rewind: false,                     // 反向播放
        loop: true,
        playInterval: 2000,                // 播放时间间隔，单位ms

        currentIndex: 0,

        itemStyle: {},
        label: {
            color: '#000'
        },

        data: []
    },

    /**
     * @override
     */
    init: function (option, parentModel, ecModel) {

        /**
         * @private
         * @type {module:echarts/data/List}
         */
        this._data;

        /**
         * @private
         * @type {Array.<string>}
         */
        this._names;

        this.mergeDefaultAndTheme(option, ecModel);
        this._initData();
    },

    /**
     * @override
     */
    mergeOption: function (option) {
        TimelineModel.superApply(this, 'mergeOption', arguments);
        this._initData();
    },

    /**
     * @param {number} [currentIndex]
     */
    setCurrentIndex: function (currentIndex) {
        if (currentIndex == null) {
            currentIndex = this.option.currentIndex;
        }
        var count = this._data.count();

        if (this.option.loop) {
            currentIndex = (currentIndex % count + count) % count;
        }
        else {
            currentIndex >= count && (currentIndex = count - 1);
            currentIndex < 0 && (currentIndex = 0);
        }

        this.option.currentIndex = currentIndex;
    },

    /**
     * @return {number} currentIndex
     */
    getCurrentIndex: function () {
        return this.option.currentIndex;
    },

    /**
     * @return {boolean}
     */
    isIndexMax: function () {
        return this.getCurrentIndex() >= this._data.count() - 1;
    },

    /**
     * @param {boolean} state true: play, false: stop
     */
    setPlayState: function (state) {
        this.option.autoPlay = !!state;
    },

    /**
     * @return {boolean} true: play, false: stop
     */
    getPlayState: function () {
        return !!this.option.autoPlay;
    },

    /**
     * @private
     */
    _initData: function () {
        var thisOption = this.option;
        var dataArr = thisOption.data || [];
        var axisType = thisOption.axisType;
        var names = this._names = [];

        if (axisType === 'category') {
            var idxArr = [];
            each$1(dataArr, function (item, index) {
                var value = getDataItemValue(item);
                var newItem;

                if (isObject$1(item)) {
                    newItem = clone(item);
                    newItem.value = index;
                }
                else {
                    newItem = index;
                }

                idxArr.push(newItem);

                if (!isString(value) && (value == null || isNaN(value))) {
                    value = '';
                }

                names.push(value + '');
            });
            dataArr = idxArr;
        }

        var dimType = ({category: 'ordinal', time: 'time'})[axisType] || 'number';

        var data = this._data = new List([{name: 'value', type: dimType}], this);

        data.initData(dataArr, names);
    },

    getData: function () {
        return this._data;
    },

    /**
     * @public
     * @return {Array.<string>} categoreis
     */
    getCategories: function () {
        if (this.get('axisType') === 'category') {
            return this._names.slice();
        }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var SliderTimelineModel = TimelineModel.extend({

    type: 'timeline.slider',

    /**
     * @protected
     */
    defaultOption: {

        backgroundColor: 'rgba(0,0,0,0)',   // 时间轴背景颜色
        borderColor: '#ccc',               // 时间轴边框颜色
        borderWidth: 0,                    // 时间轴边框线宽，单位px，默认为0（无边框）

        orient: 'horizontal',              // 'vertical'
        inverse: false,

        tooltip: {                          // boolean or Object
            trigger: 'item'                 // data item may also have tootip attr.
        },

        symbol: 'emptyCircle',
        symbolSize: 10,

        lineStyle: {
            show: true,
            width: 2,
            color: '#304654'
        },
        label: {                            // 文本标签
            position: 'auto',           // auto left right top bottom
                                        // When using number, label position is not
                                        // restricted by viewRect.
                                        // positive: right/bottom, negative: left/top
            show: true,
            interval: 'auto',
            rotate: 0,
            // formatter: null,
            // 其余属性默认使用全局文本样式，详见TEXTSTYLE
            color: '#304654'
        },
        itemStyle: {
            color: '#304654',
            borderWidth: 1
        },

        checkpointStyle: {
            symbol: 'circle',
            symbolSize: 13,
            color: '#c23531',
            borderWidth: 5,
            borderColor: 'rgba(194,53,49, 0.5)',
            animation: true,
            animationDuration: 300,
            animationEasing: 'quinticInOut'
        },

        controlStyle: {
            show: true,
            showPlayBtn: true,
            showPrevBtn: true,
            showNextBtn: true,
            itemSize: 22,
            itemGap: 12,
            position: 'left',  // 'left' 'right' 'top' 'bottom'
            playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', // jshint ignore:line
            stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', // jshint ignore:line
            nextIcon: 'path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z', // jshint ignore:line
            prevIcon: 'path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z', // jshint ignore:line

            color: '#304654',
            borderColor: '#304654',
            borderWidth: 1
        },

        emphasis: {
            label: {
                show: true,
                // 其余属性默认使用全局文本样式，详见TEXTSTYLE
                color: '#c23531'
            },

            itemStyle: {
                color: '#c23531'
            },

            controlStyle: {
                color: '#c23531',
                borderColor: '#c23531',
                borderWidth: 2
            }
        },
        data: []
    }

});

mixin(SliderTimelineModel, dataFormatMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var TimelineView = Component$1.extend({
    type: 'timeline'
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Extend axis 2d
 * @constructor module:echarts/coord/cartesian/Axis2D
 * @extends {module:echarts/coord/cartesian/Axis}
 * @param {string} dim
 * @param {*} scale
 * @param {Array.<number>} coordExtent
 * @param {string} axisType
 * @param {string} position
 */
var TimelineAxis = function (dim, scale, coordExtent, axisType) {

    Axis.call(this, dim, scale, coordExtent);

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     * @type {string}
     */
    this.type = axisType || 'value';

    /**
     * Axis model
     * @param {module:echarts/component/TimelineModel}
     */
    this.model = null;
};

TimelineAxis.prototype = {

    constructor: TimelineAxis,

    /**
     * @override
     */
    getLabelModel: function () {
        return this.model.getModel('label');
    },

    /**
     * @override
     */
    isHorizontal: function () {
        return this.model.get('orient') === 'horizontal';
    }

};

inherits(TimelineAxis, Axis);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var bind$4 = bind;
var each$24 = each$1;

var PI$5 = Math.PI;

TimelineView.extend({

    type: 'timeline.slider',

    init: function (ecModel, api) {

        this.api = api;

        /**
         * @private
         * @type {module:echarts/component/timeline/TimelineAxis}
         */
        this._axis;

        /**
         * @private
         * @type {module:zrender/core/BoundingRect}
         */
        this._viewRect;

        /**
         * @type {number}
         */
        this._timer;

        /**
         * @type {module:zrender/Element}
         */
        this._currentPointer;

        /**
         * @type {module:zrender/container/Group}
         */
        this._mainGroup;

        /**
         * @type {module:zrender/container/Group}
         */
        this._labelGroup;
    },

    /**
     * @override
     */
    render: function (timelineModel, ecModel, api, payload) {
        this.model = timelineModel;
        this.api = api;
        this.ecModel = ecModel;

        this.group.removeAll();

        if (timelineModel.get('show', true)) {

            var layoutInfo = this._layout(timelineModel, api);
            var mainGroup = this._createGroup('mainGroup');
            var labelGroup = this._createGroup('labelGroup');

            /**
             * @private
             * @type {module:echarts/component/timeline/TimelineAxis}
             */
            var axis = this._axis = this._createAxis(layoutInfo, timelineModel);

            timelineModel.formatTooltip = function (dataIndex) {
                return encodeHTML(axis.scale.getLabel(dataIndex));
            };

            each$24(
                ['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'],
                function (name) {
                    this['_render' + name](layoutInfo, mainGroup, axis, timelineModel);
                },
                this
            );

            this._renderAxisLabel(layoutInfo, labelGroup, axis, timelineModel);
            this._position(layoutInfo, timelineModel);
        }

        this._doPlayStop();
    },

    /**
     * @override
     */
    remove: function () {
        this._clearTimer();
        this.group.removeAll();
    },

    /**
     * @override
     */
    dispose: function () {
        this._clearTimer();
    },

    _layout: function (timelineModel, api) {
        var labelPosOpt = timelineModel.get('label.position');
        var orient = timelineModel.get('orient');
        var viewRect = getViewRect$4(timelineModel, api);
        // Auto label offset.
        if (labelPosOpt == null || labelPosOpt === 'auto') {
            labelPosOpt = orient === 'horizontal'
                ? ((viewRect.y + viewRect.height / 2) < api.getHeight() / 2 ? '-' : '+')
                : ((viewRect.x + viewRect.width / 2) < api.getWidth() / 2 ? '+' : '-');
        }
        else if (isNaN(labelPosOpt)) {
            labelPosOpt = ({
                horizontal: {top: '-', bottom: '+'},
                vertical: {left: '-', right: '+'}
            })[orient][labelPosOpt];
        }

        var labelAlignMap = {
            horizontal: 'center',
            vertical: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'left' : 'right'
        };

        var labelBaselineMap = {
            horizontal: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'top' : 'bottom',
            vertical: 'middle'
        };
        var rotationMap = {
            horizontal: 0,
            vertical: PI$5 / 2
        };

        // Position
        var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width;

        var controlModel = timelineModel.getModel('controlStyle');
        var showControl = controlModel.get('show', true);
        var controlSize = showControl ? controlModel.get('itemSize') : 0;
        var controlGap = showControl ? controlModel.get('itemGap') : 0;
        var sizePlusGap = controlSize + controlGap;

        // Special label rotate.
        var labelRotation = timelineModel.get('label.rotate') || 0;
        labelRotation = labelRotation * PI$5 / 180; // To radian.

        var playPosition;
        var prevBtnPosition;
        var nextBtnPosition;
        var axisExtent;
        var controlPosition = controlModel.get('position', true);
        var showPlayBtn = showControl && controlModel.get('showPlayBtn', true);
        var showPrevBtn = showControl && controlModel.get('showPrevBtn', true);
        var showNextBtn = showControl && controlModel.get('showNextBtn', true);
        var xLeft = 0;
        var xRight = mainLength;

        // position[0] means left, position[1] means middle.
        if (controlPosition === 'left' || controlPosition === 'bottom') {
            showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap);
            showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap);
            showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
        }
        else { // 'top' 'right'
            showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
            showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap);
            showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
        }
        axisExtent = [xLeft, xRight];

        if (timelineModel.get('inverse')) {
            axisExtent.reverse();
        }

        return {
            viewRect: viewRect,
            mainLength: mainLength,
            orient: orient,

            rotation: rotationMap[orient],
            labelRotation: labelRotation,
            labelPosOpt: labelPosOpt,
            labelAlign: timelineModel.get('label.align') || labelAlignMap[orient],
            labelBaseline: timelineModel.get('label.verticalAlign')
                || timelineModel.get('label.baseline')
                || labelBaselineMap[orient],

            // Based on mainGroup.
            playPosition: playPosition,
            prevBtnPosition: prevBtnPosition,
            nextBtnPosition: nextBtnPosition,
            axisExtent: axisExtent,

            controlSize: controlSize,
            controlGap: controlGap
        };
    },

    _position: function (layoutInfo, timelineModel) {
        // Position is be called finally, because bounding rect is needed for
        // adapt content to fill viewRect (auto adapt offset).

        // Timeline may be not all in the viewRect when 'offset' is specified
        // as a number, because it is more appropriate that label aligns at
        // 'offset' but not the other edge defined by viewRect.

        var mainGroup = this._mainGroup;
        var labelGroup = this._labelGroup;

        var viewRect = layoutInfo.viewRect;
        if (layoutInfo.orient === 'vertical') {
            // transform to horizontal, inverse rotate by left-top point.
            var m = create$1();
            var rotateOriginX = viewRect.x;
            var rotateOriginY = viewRect.y + viewRect.height;
            translate(m, m, [-rotateOriginX, -rotateOriginY]);
            rotate(m, m, -PI$5 / 2);
            translate(m, m, [rotateOriginX, rotateOriginY]);
            viewRect = viewRect.clone();
            viewRect.applyTransform(m);
        }

        var viewBound = getBound(viewRect);
        var mainBound = getBound(mainGroup.getBoundingRect());
        var labelBound = getBound(labelGroup.getBoundingRect());

        var mainPosition = mainGroup.position;
        var labelsPosition = labelGroup.position;

        labelsPosition[0] = mainPosition[0] = viewBound[0][0];

        var labelPosOpt = layoutInfo.labelPosOpt;

        if (isNaN(labelPosOpt)) { // '+' or '-'
            var mainBoundIdx = labelPosOpt === '+' ? 0 : 1;
            toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
            toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx);
        }
        else {
            var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1;
            toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
            labelsPosition[1] = mainPosition[1] + labelPosOpt;
        }

        mainGroup.attr('position', mainPosition);
        labelGroup.attr('position', labelsPosition);
        mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation;

        setOrigin(mainGroup);
        setOrigin(labelGroup);

        function setOrigin(targetGroup) {
            var pos = targetGroup.position;
            targetGroup.origin = [
                viewBound[0][0] - pos[0],
                viewBound[1][0] - pos[1]
            ];
        }

        function getBound(rect) {
            // [[xmin, xmax], [ymin, ymax]]
            return [
                [rect.x, rect.x + rect.width],
                [rect.y, rect.y + rect.height]
            ];
        }

        function toBound(fromPos, from, to, dimIdx, boundIdx) {
            fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx];
        }
    },

    _createAxis: function (layoutInfo, timelineModel) {
        var data = timelineModel.getData();
        var axisType = timelineModel.get('axisType');

        var scale = createScaleByModel(timelineModel, axisType);

        // Customize scale. The `tickValue` is `dataIndex`.
        scale.getTicks = function () {
            return data.mapArray(['value'], function (value) {
                return value;
            });
        };

        var dataExtent = data.getDataExtent('value');
        scale.setExtent(dataExtent[0], dataExtent[1]);
        scale.niceTicks();

        var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType);
        axis.model = timelineModel;

        return axis;
    },

    _createGroup: function (name) {
        var newGroup = this['_' + name] = new Group();
        this.group.add(newGroup);
        return newGroup;
    },

    _renderAxisLine: function (layoutInfo, group, axis, timelineModel) {
        var axisExtent = axis.getExtent();

        if (!timelineModel.get('lineStyle.show')) {
            return;
        }

        group.add(new Line({
            shape: {
                x1: axisExtent[0], y1: 0,
                x2: axisExtent[1], y2: 0
            },
            style: extend(
                {lineCap: 'round'},
                timelineModel.getModel('lineStyle').getLineStyle()
            ),
            silent: true,
            z2: 1
        }));
    },

    /**
     * @private
     */
    _renderAxisTick: function (layoutInfo, group, axis, timelineModel) {
        var data = timelineModel.getData();
        // Show all ticks, despite ignoring strategy.
        var ticks = axis.scale.getTicks();

        // The value is dataIndex, see the costomized scale.
        each$24(ticks, function (value) {
            var tickCoord = axis.dataToCoord(value);
            var itemModel = data.getItemModel(value);
            var itemStyleModel = itemModel.getModel('itemStyle');
            var hoverStyleModel = itemModel.getModel('emphasis.itemStyle');
            var symbolOpt = {
                position: [tickCoord, 0],
                onclick: bind$4(this._changeTimeline, this, value)
            };
            var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
            setHoverStyle(el, hoverStyleModel.getItemStyle());

            if (itemModel.get('tooltip')) {
                el.dataIndex = value;
                el.dataModel = timelineModel;
            }
            else {
                el.dataIndex = el.dataModel = null;
            }

        }, this);
    },

    /**
     * @private
     */
    _renderAxisLabel: function (layoutInfo, group, axis, timelineModel) {
        var labelModel = axis.getLabelModel();

        if (!labelModel.get('show')) {
            return;
        }

        var data = timelineModel.getData();
        var labels = axis.getViewLabels();

        each$24(labels, function (labelItem) {
            // The tickValue is dataIndex, see the costomized scale.
            var dataIndex = labelItem.tickValue;

            var itemModel = data.getItemModel(dataIndex);
            var normalLabelModel = itemModel.getModel('label');
            var hoverLabelModel = itemModel.getModel('emphasis.label');
            var tickCoord = axis.dataToCoord(labelItem.tickValue);
            var textEl = new Text({
                position: [tickCoord, 0],
                rotation: layoutInfo.labelRotation - layoutInfo.rotation,
                onclick: bind$4(this._changeTimeline, this, dataIndex),
                silent: false
            });
            setTextStyle(textEl.style, normalLabelModel, {
                text: labelItem.formattedLabel,
                textAlign: layoutInfo.labelAlign,
                textVerticalAlign: layoutInfo.labelBaseline
            });

            group.add(textEl);
            setHoverStyle(
                textEl, setTextStyle({}, hoverLabelModel)
            );

        }, this);
    },

    /**
     * @private
     */
    _renderControl: function (layoutInfo, group, axis, timelineModel) {
        var controlSize = layoutInfo.controlSize;
        var rotation = layoutInfo.rotation;

        var itemStyle = timelineModel.getModel('controlStyle').getItemStyle();
        var hoverStyle = timelineModel.getModel('emphasis.controlStyle').getItemStyle();
        var rect = [0, -controlSize / 2, controlSize, controlSize];
        var playState = timelineModel.getPlayState();
        var inverse = timelineModel.get('inverse', true);

        makeBtn(
            layoutInfo.nextBtnPosition,
            'controlStyle.nextIcon',
            bind$4(this._changeTimeline, this, inverse ? '-' : '+')
        );
        makeBtn(
            layoutInfo.prevBtnPosition,
            'controlStyle.prevIcon',
            bind$4(this._changeTimeline, this, inverse ? '+' : '-')
        );
        makeBtn(
            layoutInfo.playPosition,
            'controlStyle.' + (playState ? 'stopIcon' : 'playIcon'),
            bind$4(this._handlePlayClick, this, !playState),
            true
        );

        function makeBtn(position, iconPath, onclick, willRotate) {
            if (!position) {
                return;
            }
            var opt = {
                position: position,
                origin: [controlSize / 2, 0],
                rotation: willRotate ? -rotation : 0,
                rectHover: true,
                style: itemStyle,
                onclick: onclick
            };
            var btn = makeIcon(timelineModel, iconPath, rect, opt);
            group.add(btn);
            setHoverStyle(btn, hoverStyle);
        }
    },

    _renderCurrentPointer: function (layoutInfo, group, axis, timelineModel) {
        var data = timelineModel.getData();
        var currentIndex = timelineModel.getCurrentIndex();
        var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle');
        var me = this;

        var callback = {
            onCreate: function (pointer) {
                pointer.draggable = true;
                pointer.drift = bind$4(me._handlePointerDrag, me);
                pointer.ondragend = bind$4(me._handlePointerDragend, me);
                pointerMoveTo(pointer, currentIndex, axis, timelineModel, true);
            },
            onUpdate: function (pointer) {
                pointerMoveTo(pointer, currentIndex, axis, timelineModel);
            }
        };

        // Reuse when exists, for animation and drag.
        this._currentPointer = giveSymbol(
            pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback
        );
    },

    _handlePlayClick: function (nextState) {
        this._clearTimer();
        this.api.dispatchAction({
            type: 'timelinePlayChange',
            playState: nextState,
            from: this.uid
        });
    },

    _handlePointerDrag: function (dx, dy, e) {
        this._clearTimer();
        this._pointerChangeTimeline([e.offsetX, e.offsetY]);
    },

    _handlePointerDragend: function (e) {
        this._pointerChangeTimeline([e.offsetX, e.offsetY], true);
    },

    _pointerChangeTimeline: function (mousePos, trigger) {
        var toCoord = this._toAxisCoord(mousePos)[0];

        var axis = this._axis;
        var axisExtent = asc(axis.getExtent().slice());

        toCoord > axisExtent[1] && (toCoord = axisExtent[1]);
        toCoord < axisExtent[0] && (toCoord = axisExtent[0]);

        this._currentPointer.position[0] = toCoord;
        this._currentPointer.dirty();

        var targetDataIndex = this._findNearestTick(toCoord);
        var timelineModel = this.model;

        if (trigger || (
            targetDataIndex !== timelineModel.getCurrentIndex()
            && timelineModel.get('realtime')
        )) {
            this._changeTimeline(targetDataIndex);
        }
    },

    _doPlayStop: function () {
        this._clearTimer();

        if (this.model.getPlayState()) {
            this._timer = setTimeout(
                bind$4(handleFrame, this),
                this.model.get('playInterval')
            );
        }

        function handleFrame() {
            // Do not cache
            var timelineModel = this.model;
            this._changeTimeline(
                timelineModel.getCurrentIndex()
                + (timelineModel.get('rewind', true) ? -1 : 1)
            );
        }
    },

    _toAxisCoord: function (vertex) {
        var trans = this._mainGroup.getLocalTransform();
        return applyTransform$1(vertex, trans, true);
    },

    _findNearestTick: function (axisCoord) {
        var data = this.model.getData();
        var dist = Infinity;
        var targetDataIndex;
        var axis = this._axis;

        data.each(['value'], function (value, dataIndex) {
            var coord = axis.dataToCoord(value);
            var d = Math.abs(coord - axisCoord);
            if (d < dist) {
                dist = d;
                targetDataIndex = dataIndex;
            }
        });

        return targetDataIndex;
    },

    _clearTimer: function () {
        if (this._timer) {
            clearTimeout(this._timer);
            this._timer = null;
        }
    },

    _changeTimeline: function (nextIndex) {
        var currentIndex = this.model.getCurrentIndex();

        if (nextIndex === '+') {
            nextIndex = currentIndex + 1;
        }
        else if (nextIndex === '-') {
            nextIndex = currentIndex - 1;
        }

        this.api.dispatchAction({
            type: 'timelineChange',
            currentIndex: nextIndex,
            from: this.uid
        });
    }

});

function getViewRect$4(model, api) {
    return getLayoutRect(
        model.getBoxLayoutParams(),
        {
            width: api.getWidth(),
            height: api.getHeight()
        },
        model.get('padding')
    );
}

function makeIcon(timelineModel, objPath, rect, opts) {
    var icon = makePath(
        timelineModel.get(objPath).replace(/^path:\/\//, ''),
        clone(opts || {}),
        new BoundingRect(rect[0], rect[1], rect[2], rect[3]),
        'center'
    );

    return icon;
}

/**
 * Create symbol or update symbol
 * opt: basic position and event handlers
 */
function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) {
    var color = itemStyleModel.get('color');

    if (!symbol) {
        var symbolType = hostModel.get('symbol');
        symbol = createSymbol(symbolType, -1, -1, 2, 2, color);
        symbol.setStyle('strokeNoScale', true);
        group.add(symbol);
        callback && callback.onCreate(symbol);
    }
    else {
        symbol.setColor(color);
        group.add(symbol); // Group may be new, also need to add.
        callback && callback.onUpdate(symbol);
    }

    // Style
    var itemStyle = itemStyleModel.getItemStyle(['color', 'symbol', 'symbolSize']);
    symbol.setStyle(itemStyle);

    // Transform and events.
    opt = merge({
        rectHover: true,
        z2: 100
    }, opt, true);

    var symbolSize = hostModel.get('symbolSize');
    symbolSize = symbolSize instanceof Array
        ? symbolSize.slice()
        : [+symbolSize, +symbolSize];
    symbolSize[0] /= 2;
    symbolSize[1] /= 2;
    opt.scale = symbolSize;

    var symbolOffset = hostModel.get('symbolOffset');
    if (symbolOffset) {
        var pos = opt.position = opt.position || [0, 0];
        pos[0] += parsePercent$1(symbolOffset[0], symbolSize[0]);
        pos[1] += parsePercent$1(symbolOffset[1], symbolSize[1]);
    }

    var symbolRotate = hostModel.get('symbolRotate');
    opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;

    symbol.attr(opt);

    // FIXME
    // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed,
    // getBoundingRect will return wrong result.
    // (This is supposed to be resolved in zrender, but it is a little difficult to
    // leverage performance and auto updateTransform)
    // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol.
    symbol.updateTransform();

    return symbol;
}

function pointerMoveTo(pointer, dataIndex, axis, timelineModel, noAnimation) {
    if (pointer.dragging) {
        return;
    }

    var pointerModel = timelineModel.getModel('checkpointStyle');
    var toCoord = axis.dataToCoord(timelineModel.getData().get(['value'], dataIndex));

    if (noAnimation || !pointerModel.get('animation', true)) {
        pointer.attr({position: [toCoord, 0]});
    }
    else {
        pointer.stopAnimation(true);
        pointer.animateTo(
            {position: [toCoord, 0]},
            pointerModel.get('animationDuration', true),
            pointerModel.get('animationEasing', true)
        );
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * DataZoom component entry
 */

registerPreprocessor(preprocessor$2);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var addCommas$1 = addCommas;
var encodeHTML$1 = encodeHTML;

function fillLabel(opt) {
    defaultEmphasis(opt, 'label', ['show']);
}
var MarkerModel = extendComponentModel({

    type: 'marker',

    dependencies: ['series', 'grid', 'polar', 'geo'],

    /**
     * @overrite
     */
    init: function (option, parentModel, ecModel) {

        if (__DEV__) {
            if (this.type === 'marker') {
                throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.');
            }
        }
        this.mergeDefaultAndTheme(option, ecModel);
        this._mergeOption(option, ecModel, false, true);
    },

    /**
     * @return {boolean}
     */
    isAnimationEnabled: function () {
        if (env$1.node) {
            return false;
        }

        var hostSeries = this.__hostSeries;
        return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled();
    },

    /**
     * @overrite
     */
    mergeOption: function (newOpt, ecModel) {
        this._mergeOption(newOpt, ecModel, false, false);
    },

    _mergeOption: function (newOpt, ecModel, createdBySelf, isInit) {
        var MarkerModel = this.constructor;
        var modelPropName = this.mainType + 'Model';
        if (!createdBySelf) {
            ecModel.eachSeries(function (seriesModel) {

                var markerOpt = seriesModel.get(this.mainType, true);

                var markerModel = seriesModel[modelPropName];
                if (!markerOpt || !markerOpt.data) {
                    seriesModel[modelPropName] = null;
                    return;
                }
                if (!markerModel) {
                    if (isInit) {
                        // Default label emphasis `position` and `show`
                        fillLabel(markerOpt);
                    }
                    each$1(markerOpt.data, function (item) {
                        // FIXME Overwrite fillLabel method ?
                        if (item instanceof Array) {
                            fillLabel(item[0]);
                            fillLabel(item[1]);
                        }
                        else {
                            fillLabel(item);
                        }
                    });

                    markerModel = new MarkerModel(
                        markerOpt, this, ecModel
                    );

                    extend(markerModel, {
                        mainType: this.mainType,
                        // Use the same series index and name
                        seriesIndex: seriesModel.seriesIndex,
                        name: seriesModel.name,
                        createdBySelf: true
                    });

                    markerModel.__hostSeries = seriesModel;
                }
                else {
                    markerModel._mergeOption(markerOpt, ecModel, true);
                }
                seriesModel[modelPropName] = markerModel;
            }, this);
        }
    },

    formatTooltip: function (dataIndex) {
        var data = this.getData();
        var value = this.getRawValue(dataIndex);
        var formattedValue = isArray(value)
            ? map(value, addCommas$1).join(', ') : addCommas$1(value);
        var name = data.getName(dataIndex);
        var html = encodeHTML$1(this.name);
        if (value != null || name) {
            html += '<br />';
        }
        if (name) {
            html += encodeHTML$1(name);
            if (value != null) {
                html += ' : ';
            }
        }
        if (value != null) {
            html += encodeHTML$1(formattedValue);
        }
        return html;
    },

    getData: function () {
        return this._data;
    },

    setData: function (data) {
        this._data = data;
    }
});

mixin(MarkerModel, dataFormatMixin);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

MarkerModel.extend({

    type: 'markPoint',

    defaultOption: {
        zlevel: 0,
        z: 5,
        symbol: 'pin',
        symbolSize: 50,
        //symbolRotate: 0,
        //symbolOffset: [0, 0]
        tooltip: {
            trigger: 'item'
        },
        label: {
            show: true,
            position: 'inside'
        },
        itemStyle: {
            borderWidth: 2
        },
        emphasis: {
            label: {
                show: true
            }
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var indexOf$2 = indexOf;

function hasXOrY(item) {
    return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
}

function hasXAndY(item) {
    return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
}

// Make it simple, do not visit all stacked value to count precision.
// function getPrecision(data, valueAxisDim, dataIndex) {
//     var precision = -1;
//     var stackedDim = data.mapDimension(valueAxisDim);
//     do {
//         precision = Math.max(
//             numberUtil.getPrecision(data.get(stackedDim, dataIndex)),
//             precision
//         );
//         var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
//         if (stackedOnSeries) {
//             var byValue = data.get(data.getCalculationInfo('stackedByDimension'), dataIndex);
//             data = stackedOnSeries.getData();
//             dataIndex = data.indexOf(data.getCalculationInfo('stackedByDimension'), byValue);
//             stackedDim = data.getCalculationInfo('stackedDimension');
//         }
//         else {
//             data = null;
//         }
//     } while (data);

//     return precision;
// }

function markerTypeCalculatorWithExtent(
    mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex
) {
    var coordArr = [];

    var stacked = isDimensionStacked(data, targetDataDim /*, otherDataDim*/);
    var calcDataDim = stacked
        ? data.getCalculationInfo('stackResultDimension')
        : targetDataDim;

    var value = numCalculate(data, calcDataDim, mlType);

    var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
    coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
    coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex);

    // Make it simple, do not visit all stacked value to count precision.
    var precision = getPrecision(data.get(targetDataDim, dataIndex));
    precision = Math.min(precision, 20);
    if (precision >= 0) {
        coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
    }

    return coordArr;
}

var curry$5 = curry;
// TODO Specified percent
var markerTypeCalculator = {
    /**
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
     */
    min: curry$5(markerTypeCalculatorWithExtent, 'min'),
    /**
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
     */
    max: curry$5(markerTypeCalculatorWithExtent, 'max'),

    /**
     * @method
     * @param {module:echarts/data/List} data
     * @param {string} baseAxisDim
     * @param {string} valueAxisDim
     */
    average: curry$5(markerTypeCalculatorWithExtent, 'average')
};

/**
 * Transform markPoint data item to format used in List by do the following
 * 1. Calculate statistic like `max`, `min`, `average`
 * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array
 * @param  {module:echarts/model/Series} seriesModel
 * @param  {module:echarts/coord/*} [coordSys]
 * @param  {Object} item
 * @return {Object}
 */
function dataTransform(seriesModel, item) {
    var data = seriesModel.getData();
    var coordSys = seriesModel.coordinateSystem;

    // 1. If not specify the position with pixel directly
    // 2. If `coord` is not a data array. Which uses `xAxis`,
    // `yAxis` to specify the coord on each dimension

    // parseFloat first because item.x and item.y can be percent string like '20%'
    if (item && !hasXAndY(item) && !isArray(item.coord) && coordSys) {
        var dims = coordSys.dimensions;
        var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel);

        // Clone the option
        // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value
        item = clone(item);

        if (item.type
            && markerTypeCalculator[item.type]
            && axisInfo.baseAxis && axisInfo.valueAxis
        ) {
            var otherCoordIndex = indexOf$2(dims, axisInfo.baseAxis.dim);
            var targetCoordIndex = indexOf$2(dims, axisInfo.valueAxis.dim);

            item.coord = markerTypeCalculator[item.type](
                data, axisInfo.baseDataDim, axisInfo.valueDataDim,
                otherCoordIndex, targetCoordIndex
            );
            // Force to use the value of calculated value.
            item.value = item.coord[targetCoordIndex];
        }
        else {
            // FIXME Only has one of xAxis and yAxis.
            var coord = [
                item.xAxis != null ? item.xAxis : item.radiusAxis,
                item.yAxis != null ? item.yAxis : item.angleAxis
            ];
            // Each coord support max, min, average
            for (var i = 0; i < 2; i++) {
                if (markerTypeCalculator[coord[i]]) {
                    coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]);
                }
            }
            item.coord = coord;
        }
    }
    return item;
}

function getAxisInfo$1(item, data, coordSys, seriesModel) {
    var ret = {};

    if (item.valueIndex != null || item.valueDim != null) {
        ret.valueDataDim = item.valueIndex != null
            ? data.getDimension(item.valueIndex) : item.valueDim;
        ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim));
        ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
        ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
    }
    else {
        ret.baseAxis = seriesModel.getBaseAxis();
        ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
        ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
        ret.valueDataDim = data.mapDimension(ret.valueAxis.dim);
    }

    return ret;
}

function dataDimToCoordDim(seriesModel, dataDim) {
    var data = seriesModel.getData();
    var dimensions = data.dimensions;
    dataDim = data.getDimension(dataDim);
    for (var i = 0; i < dimensions.length; i++) {
        var dimItem = data.getDimensionInfo(dimensions[i]);
        if (dimItem.name === dataDim) {
            return dimItem.coordDim;
        }
    }
}

/**
 * Filter data which is out of coordinateSystem range
 * [dataFilter description]
 * @param  {module:echarts/coord/*} [coordSys]
 * @param  {Object} item
 * @return {boolean}
 */
function dataFilter$1(coordSys, item) {
    // Alwalys return true if there is no coordSys
    return (coordSys && coordSys.containData && item.coord && !hasXOrY(item))
        ? coordSys.containData(item.coord) : true;
}

function dimValueGetter(item, dimName, dataIndex, dimIndex) {
    // x, y, radius, angle
    if (dimIndex < 2) {
        return item.coord && item.coord[dimIndex];
    }
    return item.value;
}

function numCalculate(data, valueDataDim, type) {
    if (type === 'average') {
        var sum = 0;
        var count = 0;
        data.each(valueDataDim, function (val, idx) {
            if (!isNaN(val)) {
                sum += val;
                count++;
            }
        });
        return sum / count;
    }
    else if (type === 'median') {
        return data.getMedian(valueDataDim);
    }
    else {
        // max & min
        return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0];
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var MarkerView = extendComponentView({

    type: 'marker',

    init: function () {
        /**
         * Markline grouped by series
         * @private
         * @type {module:zrender/core/util.HashMap}
         */
        this.markerGroupMap = createHashMap();
    },

    render: function (markerModel, ecModel, api) {
        var markerGroupMap = this.markerGroupMap;
        markerGroupMap.each(function (item) {
            item.__keep = false;
        });

        var markerModelKey = this.type + 'Model';
        ecModel.eachSeries(function (seriesModel) {
            var markerModel = seriesModel[markerModelKey];
            markerModel && this.renderSeries(seriesModel, markerModel, ecModel, api);
        }, this);

        markerGroupMap.each(function (item) {
            !item.__keep && this.group.remove(item.group);
        }, this);
    },

    renderSeries: function () {}
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function updateMarkerLayout(mpData, seriesModel, api) {
    var coordSys = seriesModel.coordinateSystem;
    mpData.each(function (idx) {
        var itemModel = mpData.getItemModel(idx);
        var point;
        var xPx = parsePercent$1(itemModel.get('x'), api.getWidth());
        var yPx = parsePercent$1(itemModel.get('y'), api.getHeight());
        if (!isNaN(xPx) && !isNaN(yPx)) {
            point = [xPx, yPx];
        }
        // Chart like bar may have there own marker positioning logic
        else if (seriesModel.getMarkerPosition) {
            // Use the getMarkerPoisition
            point = seriesModel.getMarkerPosition(
                mpData.getValues(mpData.dimensions, idx)
            );
        }
        else if (coordSys) {
            var x = mpData.get(coordSys.dimensions[0], idx);
            var y = mpData.get(coordSys.dimensions[1], idx);
            point = coordSys.dataToPoint([x, y]);

        }

        // Use x, y if has any
        if (!isNaN(xPx)) {
            point[0] = xPx;
        }
        if (!isNaN(yPx)) {
            point[1] = yPx;
        }

        mpData.setItemLayout(idx, point);
    });
}

MarkerView.extend({

    type: 'markPoint',

    // updateLayout: function (markPointModel, ecModel, api) {
    //     ecModel.eachSeries(function (seriesModel) {
    //         var mpModel = seriesModel.markPointModel;
    //         if (mpModel) {
    //             updateMarkerLayout(mpModel.getData(), seriesModel, api);
    //             this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel);
    //         }
    //     }, this);
    // },

    updateTransform: function (markPointModel, ecModel, api) {
        ecModel.eachSeries(function (seriesModel) {
            var mpModel = seriesModel.markPointModel;
            if (mpModel) {
                updateMarkerLayout(mpModel.getData(), seriesModel, api);
                this.markerGroupMap.get(seriesModel.id).updateLayout(mpModel);
            }
        }, this);
    },

    renderSeries: function (seriesModel, mpModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;
        var seriesId = seriesModel.id;
        var seriesData = seriesModel.getData();

        var symbolDrawMap = this.markerGroupMap;
        var symbolDraw = symbolDrawMap.get(seriesId)
            || symbolDrawMap.set(seriesId, new SymbolDraw());

        var mpData = createList$1(coordSys, seriesModel, mpModel);

        // FIXME
        mpModel.setData(mpData);

        updateMarkerLayout(mpModel.getData(), seriesModel, api);

        mpData.each(function (idx) {
            var itemModel = mpData.getItemModel(idx);
            var symbol = itemModel.getShallow('symbol');
            var symbolSize = itemModel.getShallow('symbolSize');
            var isFnSymbol = isFunction$1(symbol);
            var isFnSymbolSize = isFunction$1(symbolSize);

            if (isFnSymbol || isFnSymbolSize) {
                var rawIdx = mpModel.getRawValue(idx);
                var dataParams = mpModel.getDataParams(idx);
                if (isFnSymbol) {
                    symbol = symbol(rawIdx, dataParams);
                }
                if (isFnSymbolSize) {
                    // FIXME 这里不兼容 ECharts 2.x，2.x 貌似参数是整个数据？
                    symbolSize = symbolSize(rawIdx, dataParams);
                }
            }

            mpData.setItemVisual(idx, {
                symbol: symbol,
                symbolSize: symbolSize,
                color: itemModel.get('itemStyle.color')
                    || seriesData.getVisual('color')
            });
        });

        // TODO Text are wrong
        symbolDraw.updateData(mpData);
        this.group.add(symbolDraw.group);

        // Set host model for tooltip
        // FIXME
        mpData.eachItemGraphicEl(function (el) {
            el.traverse(function (child) {
                child.dataModel = mpModel;
            });
        });

        symbolDraw.__keep = true;

        symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent');
    }
});

/**
 * @inner
 * @param {module:echarts/coord/*} [coordSys]
 * @param {module:echarts/model/Series} seriesModel
 * @param {module:echarts/model/Model} mpModel
 */
function createList$1(coordSys, seriesModel, mpModel) {
    var coordDimsInfos;
    if (coordSys) {
        coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
            var info = seriesModel.getData().getDimensionInfo(
                seriesModel.getData().mapDimension(coordDim)
            ) || {};
            // In map series data don't have lng and lat dimension. Fallback to same with coordSys
            return defaults({name: coordDim}, info);
        });
    }
    else {
        coordDimsInfos = [{
            name: 'value',
            type: 'float'
        }];
    }

    var mpData = new List(coordDimsInfos, mpModel);
    var dataOpt = map(mpModel.get('data'), curry(
            dataTransform, seriesModel
        ));
    if (coordSys) {
        dataOpt = filter(
            dataOpt, curry(dataFilter$1, coordSys)
        );
    }

    mpData.initData(dataOpt, null,
        coordSys ? dimValueGetter : function (item) {
            return item.value;
        }
    );

    return mpData;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// HINT Markpoint can't be used too much
registerPreprocessor(function (opt) {
    // Make sure markPoint component is enabled
    opt.markPoint = opt.markPoint || {};
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

MarkerModel.extend({

    type: 'markLine',

    defaultOption: {
        zlevel: 0,
        z: 5,

        symbol: ['circle', 'arrow'],
        symbolSize: [8, 16],

        //symbolRotate: 0,

        precision: 2,
        tooltip: {
            trigger: 'item'
        },
        label: {
            show: true,
            position: 'end'
        },
        lineStyle: {
            type: 'dashed'
        },
        emphasis: {
            label: {
                show: true
            },
            lineStyle: {
                width: 3
            }
        },
        animationEasing: 'linear'
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
    var data = seriesModel.getData();
    // Special type markLine like 'min', 'max', 'average', 'median'
    var mlType = item.type;

    if (!isArray(item)
        && (
            mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median'
            // In case
            // data: [{
            //   yAxis: 10
            // }]
            || (item.xAxis != null || item.yAxis != null)
        )
    ) {
        var valueAxis;
        var value;

        if (item.yAxis != null || item.xAxis != null) {
            valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x');
            value = retrieve(item.yAxis, item.xAxis);
        }
        else {
            var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel);
            valueAxis = axisInfo.valueAxis;
            var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim);
            value = numCalculate(data, valueDataDim, mlType);
        }
        var valueIndex = valueAxis.dim === 'x' ? 0 : 1;
        var baseIndex = 1 - valueIndex;

        var mlFrom = clone(item);
        var mlTo = {};

        mlFrom.type = null;

        mlFrom.coord = [];
        mlTo.coord = [];
        mlFrom.coord[baseIndex] = -Infinity;
        mlTo.coord[baseIndex] = Infinity;

        var precision = mlModel.get('precision');
        if (precision >= 0 && typeof value === 'number') {
            value = +value.toFixed(Math.min(precision, 20));
        }

        mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value;

        item = [mlFrom, mlTo, { // Extra option for tooltip and label
            type: mlType,
            valueIndex: item.valueIndex,
            // Force to use the value of calculated value.
            value: value
        }];
    }

    item = [
        dataTransform(seriesModel, item[0]),
        dataTransform(seriesModel, item[1]),
        extend({}, item[2])
    ];

    // Avoid line data type is extended by from(to) data type
    item[2].type = item[2].type || '';

    // Merge from option and to option into line option
    merge(item[2], item[0]);
    merge(item[2], item[1]);

    return item;
};

function isInifinity(val) {
    return !isNaN(val) && !isFinite(val);
}

// If a markLine has one dim
function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
    var otherDimIndex = 1 - dimIndex;
    var dimName = coordSys.dimensions[dimIndex];
    return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex])
        && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]);
}

function markLineFilter(coordSys, item) {
    if (coordSys.type === 'cartesian2d') {
        var fromCoord = item[0].coord;
        var toCoord = item[1].coord;
        // In case
        // {
        //  markLine: {
        //    data: [{ yAxis: 2 }]
        //  }
        // }
        if (
            fromCoord && toCoord
            && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys)
            || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))
        ) {
            return true;
        }
    }
    return dataFilter$1(coordSys, item[0])
        && dataFilter$1(coordSys, item[1]);
}

function updateSingleMarkerEndLayout(
    data, idx, isFrom, seriesModel, api
) {
    var coordSys = seriesModel.coordinateSystem;
    var itemModel = data.getItemModel(idx);

    var point;
    var xPx = parsePercent$1(itemModel.get('x'), api.getWidth());
    var yPx = parsePercent$1(itemModel.get('y'), api.getHeight());
    if (!isNaN(xPx) && !isNaN(yPx)) {
        point = [xPx, yPx];
    }
    else {
        // Chart like bar may have there own marker positioning logic
        if (seriesModel.getMarkerPosition) {
            // Use the getMarkerPoisition
            point = seriesModel.getMarkerPosition(
                data.getValues(data.dimensions, idx)
            );
        }
        else {
            var dims = coordSys.dimensions;
            var x = data.get(dims[0], idx);
            var y = data.get(dims[1], idx);
            point = coordSys.dataToPoint([x, y]);
        }
        // Expand line to the edge of grid if value on one axis is Inifnity
        // In case
        //  markLine: {
        //    data: [{
        //      yAxis: 2
        //      // or
        //      type: 'average'
        //    }]
        //  }
        if (coordSys.type === 'cartesian2d') {
            var xAxis = coordSys.getAxis('x');
            var yAxis = coordSys.getAxis('y');
            var dims = coordSys.dimensions;
            if (isInifinity(data.get(dims[0], idx))) {
                point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]);
            }
            else if (isInifinity(data.get(dims[1], idx))) {
                point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]);
            }
        }

        // Use x, y if has any
        if (!isNaN(xPx)) {
            point[0] = xPx;
        }
        if (!isNaN(yPx)) {
            point[1] = yPx;
        }
    }

    data.setItemLayout(idx, point);
}

MarkerView.extend({

    type: 'markLine',

    // updateLayout: function (markLineModel, ecModel, api) {
    //     ecModel.eachSeries(function (seriesModel) {
    //         var mlModel = seriesModel.markLineModel;
    //         if (mlModel) {
    //             var mlData = mlModel.getData();
    //             var fromData = mlModel.__from;
    //             var toData = mlModel.__to;
    //             // Update visual and layout of from symbol and to symbol
    //             fromData.each(function (idx) {
    //                 updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api);
    //                 updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api);
    //             });
    //             // Update layout of line
    //             mlData.each(function (idx) {
    //                 mlData.setItemLayout(idx, [
    //                     fromData.getItemLayout(idx),
    //                     toData.getItemLayout(idx)
    //                 ]);
    //             });

    //             this.markerGroupMap.get(seriesModel.id).updateLayout();

    //         }
    //     }, this);
    // },

    updateTransform: function (markLineModel, ecModel, api) {
        ecModel.eachSeries(function (seriesModel) {
            var mlModel = seriesModel.markLineModel;
            if (mlModel) {
                var mlData = mlModel.getData();
                var fromData = mlModel.__from;
                var toData = mlModel.__to;
                // Update visual and layout of from symbol and to symbol
                fromData.each(function (idx) {
                    updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api);
                    updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api);
                });
                // Update layout of line
                mlData.each(function (idx) {
                    mlData.setItemLayout(idx, [
                        fromData.getItemLayout(idx),
                        toData.getItemLayout(idx)
                    ]);
                });

                this.markerGroupMap.get(seriesModel.id).updateLayout();

            }
        }, this);
    },

    renderSeries: function (seriesModel, mlModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;
        var seriesId = seriesModel.id;
        var seriesData = seriesModel.getData();

        var lineDrawMap = this.markerGroupMap;
        var lineDraw = lineDrawMap.get(seriesId)
            || lineDrawMap.set(seriesId, new LineDraw());
        this.group.add(lineDraw.group);

        var mlData = createList$2(coordSys, seriesModel, mlModel);

        var fromData = mlData.from;
        var toData = mlData.to;
        var lineData = mlData.line;

        mlModel.__from = fromData;
        mlModel.__to = toData;
        // Line data for tooltip and formatter
        mlModel.setData(lineData);

        var symbolType = mlModel.get('symbol');
        var symbolSize = mlModel.get('symbolSize');
        if (!isArray(symbolType)) {
            symbolType = [symbolType, symbolType];
        }
        if (typeof symbolSize === 'number') {
            symbolSize = [symbolSize, symbolSize];
        }

        // Update visual and layout of from symbol and to symbol
        mlData.from.each(function (idx) {
            updateDataVisualAndLayout(fromData, idx, true);
            updateDataVisualAndLayout(toData, idx, false);
        });

        // Update visual and layout of line
        lineData.each(function (idx) {
            var lineColor = lineData.getItemModel(idx).get('lineStyle.color');
            lineData.setItemVisual(idx, {
                color: lineColor || fromData.getItemVisual(idx, 'color')
            });
            lineData.setItemLayout(idx, [
                fromData.getItemLayout(idx),
                toData.getItemLayout(idx)
            ]);

            lineData.setItemVisual(idx, {
                'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
                'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
                'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
                'toSymbol': toData.getItemVisual(idx, 'symbol')
            });
        });

        lineDraw.updateData(lineData);

        // Set host model for tooltip
        // FIXME
        mlData.line.eachItemGraphicEl(function (el, idx) {
            el.traverse(function (child) {
                child.dataModel = mlModel;
            });
        });

        function updateDataVisualAndLayout(data, idx, isFrom) {
            var itemModel = data.getItemModel(idx);

            updateSingleMarkerEndLayout(
                data, idx, isFrom, seriesModel, api
            );

            data.setItemVisual(idx, {
                symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
                symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
                color: itemModel.get('itemStyle.color') || seriesData.getVisual('color')
            });
        }

        lineDraw.__keep = true;

        lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent');
    }
});

/**
 * @inner
 * @param {module:echarts/coord/*} coordSys
 * @param {module:echarts/model/Series} seriesModel
 * @param {module:echarts/model/Model} mpModel
 */
function createList$2(coordSys, seriesModel, mlModel) {

    var coordDimsInfos;
    if (coordSys) {
        coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
            var info = seriesModel.getData().getDimensionInfo(
                seriesModel.getData().mapDimension(coordDim)
            ) || {};
            // In map series data don't have lng and lat dimension. Fallback to same with coordSys
            return defaults({name: coordDim}, info);
        });
    }
    else {
        coordDimsInfos = [{
            name: 'value',
            type: 'float'
        }];
    }

    var fromData = new List(coordDimsInfos, mlModel);
    var toData = new List(coordDimsInfos, mlModel);
    // No dimensions
    var lineData = new List([], mlModel);

    var optData = map(mlModel.get('data'), curry(
        markLineTransform, seriesModel, coordSys, mlModel
    ));
    if (coordSys) {
        optData = filter(
            optData, curry(markLineFilter, coordSys)
        );
    }
    var dimValueGetter$$1 = coordSys ? dimValueGetter : function (item) {
        return item.value;
    };
    fromData.initData(
        map(optData, function (item) {
            return item[0];
        }),
        null,
        dimValueGetter$$1
    );
    toData.initData(
        map(optData, function (item) {
            return item[1];
        }),
        null,
        dimValueGetter$$1
    );
    lineData.initData(
        map(optData, function (item) {
            return item[2];
        })
    );
    lineData.hasItemOption = true;

    return {
        from: fromData,
        to: toData,
        line: lineData
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerPreprocessor(function (opt) {
    // Make sure markLine component is enabled
    opt.markLine = opt.markLine || {};
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

MarkerModel.extend({

    type: 'markArea',

    defaultOption: {
        zlevel: 0,
        // PENDING
        z: 1,
        tooltip: {
            trigger: 'item'
        },
        // markArea should fixed on the coordinate system
        animation: false,
        label: {
            show: true,
            position: 'top'
        },
        itemStyle: {
            // color and borderColor default to use color from series
            // color: 'auto'
            // borderColor: 'auto'
            borderWidth: 0
        },

        emphasis: {
            label: {
                show: true,
                position: 'top'
            }
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// TODO Better on polar

var markAreaTransform = function (seriesModel, coordSys, maModel, item) {
    var lt = dataTransform(seriesModel, item[0]);
    var rb = dataTransform(seriesModel, item[1]);
    var retrieve$$1 = retrieve;

    // FIXME make sure lt is less than rb
    var ltCoord = lt.coord;
    var rbCoord = rb.coord;
    ltCoord[0] = retrieve$$1(ltCoord[0], -Infinity);
    ltCoord[1] = retrieve$$1(ltCoord[1], -Infinity);

    rbCoord[0] = retrieve$$1(rbCoord[0], Infinity);
    rbCoord[1] = retrieve$$1(rbCoord[1], Infinity);

    // Merge option into one
    var result = mergeAll([{}, lt, rb]);

    result.coord = [
        lt.coord, rb.coord
    ];
    result.x0 = lt.x;
    result.y0 = lt.y;
    result.x1 = rb.x;
    result.y1 = rb.y;
    return result;
};

function isInifinity$1(val) {
    return !isNaN(val) && !isFinite(val);
}

// If a markArea has one dim
function ifMarkLineHasOnlyDim$1(dimIndex, fromCoord, toCoord, coordSys) {
    var otherDimIndex = 1 - dimIndex;
    return isInifinity$1(fromCoord[otherDimIndex]) && isInifinity$1(toCoord[otherDimIndex]);
}

function markAreaFilter(coordSys, item) {
    var fromCoord = item.coord[0];
    var toCoord = item.coord[1];
    if (coordSys.type === 'cartesian2d') {
        // In case
        // {
        //  markArea: {
        //    data: [{ yAxis: 2 }]
        //  }
        // }
        if (
            fromCoord && toCoord
            && (ifMarkLineHasOnlyDim$1(1, fromCoord, toCoord, coordSys)
            || ifMarkLineHasOnlyDim$1(0, fromCoord, toCoord, coordSys))
        ) {
            return true;
        }
    }
    return dataFilter$1(coordSys, {
            coord: fromCoord,
            x: item.x0,
            y: item.y0
        })
        || dataFilter$1(coordSys, {
            coord: toCoord,
            x: item.x1,
            y: item.y1
        });
}

// dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0']
function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) {
    var coordSys = seriesModel.coordinateSystem;
    var itemModel = data.getItemModel(idx);

    var point;
    var xPx = parsePercent$1(itemModel.get(dims[0]), api.getWidth());
    var yPx = parsePercent$1(itemModel.get(dims[1]), api.getHeight());
    if (!isNaN(xPx) && !isNaN(yPx)) {
        point = [xPx, yPx];
    }
    else {
        // Chart like bar may have there own marker positioning logic
        if (seriesModel.getMarkerPosition) {
            // Use the getMarkerPoisition
            point = seriesModel.getMarkerPosition(
                data.getValues(dims, idx)
            );
        }
        else {
            var x = data.get(dims[0], idx);
            var y = data.get(dims[1], idx);
            var pt = [x, y];
            coordSys.clampData && coordSys.clampData(pt, pt);
            point = coordSys.dataToPoint(pt, true);
        }
        if (coordSys.type === 'cartesian2d') {
            var xAxis = coordSys.getAxis('x');
            var yAxis = coordSys.getAxis('y');
            var x = data.get(dims[0], idx);
            var y = data.get(dims[1], idx);
            if (isInifinity$1(x)) {
                point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]);
            }
            else if (isInifinity$1(y)) {
                point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]);
            }
        }

        // Use x, y if has any
        if (!isNaN(xPx)) {
            point[0] = xPx;
        }
        if (!isNaN(yPx)) {
            point[1] = yPx;
        }
    }

    return point;
}

var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']];

MarkerView.extend({

    type: 'markArea',

    // updateLayout: function (markAreaModel, ecModel, api) {
    //     ecModel.eachSeries(function (seriesModel) {
    //         var maModel = seriesModel.markAreaModel;
    //         if (maModel) {
    //             var areaData = maModel.getData();
    //             areaData.each(function (idx) {
    //                 var points = zrUtil.map(dimPermutations, function (dim) {
    //                     return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
    //                 });
    //                 // Layout
    //                 areaData.setItemLayout(idx, points);
    //                 var el = areaData.getItemGraphicEl(idx);
    //                 el.setShape('points', points);
    //             });
    //         }
    //     }, this);
    // },

    updateTransform: function (markAreaModel, ecModel, api) {
        ecModel.eachSeries(function (seriesModel) {
            var maModel = seriesModel.markAreaModel;
            if (maModel) {
                var areaData = maModel.getData();
                areaData.each(function (idx) {
                    var points = map(dimPermutations, function (dim) {
                        return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
                    });
                    // Layout
                    areaData.setItemLayout(idx, points);
                    var el = areaData.getItemGraphicEl(idx);
                    el.setShape('points', points);
                });
            }
        }, this);
    },

    renderSeries: function (seriesModel, maModel, ecModel, api) {
        var coordSys = seriesModel.coordinateSystem;
        var seriesId = seriesModel.id;
        var seriesData = seriesModel.getData();

        var areaGroupMap = this.markerGroupMap;
        var polygonGroup = areaGroupMap.get(seriesId)
            || areaGroupMap.set(seriesId, {group: new Group()});

        this.group.add(polygonGroup.group);
        polygonGroup.__keep = true;

        var areaData = createList$3(coordSys, seriesModel, maModel);

        // Line data for tooltip and formatter
        maModel.setData(areaData);

        // Update visual and layout of line
        areaData.each(function (idx) {
            // Layout
            areaData.setItemLayout(idx, map(dimPermutations, function (dim) {
                return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
            }));

            // Visual
            areaData.setItemVisual(idx, {
                color: seriesData.getVisual('color')
            });
        });


        areaData.diff(polygonGroup.__data)
            .add(function (idx) {
                var polygon = new Polygon({
                    shape: {
                        points: areaData.getItemLayout(idx)
                    }
                });
                areaData.setItemGraphicEl(idx, polygon);
                polygonGroup.group.add(polygon);
            })
            .update(function (newIdx, oldIdx) {
                var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
                updateProps(polygon, {
                    shape: {
                        points: areaData.getItemLayout(newIdx)
                    }
                }, maModel, newIdx);
                polygonGroup.group.add(polygon);
                areaData.setItemGraphicEl(newIdx, polygon);
            })
            .remove(function (idx) {
                var polygon = polygonGroup.__data.getItemGraphicEl(idx);
                polygonGroup.group.remove(polygon);
            })
            .execute();

        areaData.eachItemGraphicEl(function (polygon, idx) {
            var itemModel = areaData.getItemModel(idx);
            var labelModel = itemModel.getModel('label');
            var labelHoverModel = itemModel.getModel('emphasis.label');
            var color = areaData.getItemVisual(idx, 'color');
            polygon.useStyle(
                defaults(
                    itemModel.getModel('itemStyle').getItemStyle(),
                    {
                        fill: modifyAlpha(color, 0.4),
                        stroke: color
                    }
                )
            );

            polygon.hoverStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();

            setLabelStyle(
                polygon.style, polygon.hoverStyle, labelModel, labelHoverModel,
                {
                    labelFetcher: maModel,
                    labelDataIndex: idx,
                    defaultText: areaData.getName(idx) || '',
                    isRectText: true,
                    autoColor: color
                }
            );

            setHoverStyle(polygon, {});

            polygon.dataModel = maModel;
        });

        polygonGroup.__data = areaData;

        polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent');
    }
});

/**
 * @inner
 * @param {module:echarts/coord/*} coordSys
 * @param {module:echarts/model/Series} seriesModel
 * @param {module:echarts/model/Model} mpModel
 */
function createList$3(coordSys, seriesModel, maModel) {

    var coordDimsInfos;
    var areaData;
    var dims = ['x0', 'y0', 'x1', 'y1'];
    if (coordSys) {
        coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
            var data = seriesModel.getData();
            var info = data.getDimensionInfo(
                data.mapDimension(coordDim)
            ) || {};
            // In map series data don't have lng and lat dimension. Fallback to same with coordSys
            return defaults({name: coordDim}, info);
        });
        areaData = new List(map(dims, function (dim, idx) {
            return {
                name: dim,
                type: coordDimsInfos[idx % 2].type
            };
        }), maModel);
    }
    else {
        coordDimsInfos = [{
            name: 'value',
            type: 'float'
        }];
        areaData = new List(coordDimsInfos, maModel);
    }

    var optData = map(maModel.get('data'), curry(
        markAreaTransform, seriesModel, coordSys, maModel
    ));
    if (coordSys) {
        optData = filter(
            optData, curry(markAreaFilter, coordSys)
        );
    }

    var dimValueGetter$$1 = coordSys ? function (item, dimName, dataIndex, dimIndex) {
        return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
    } : function (item) {
        return item.value;
    };
    areaData.initData(optData, null, dimValueGetter$$1);
    areaData.hasItemOption = true;
    return areaData;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

registerPreprocessor(function (opt) {
    // Make sure markArea component is enabled
    opt.markArea = opt.markArea || {};
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var langSelector = lang.legend.selector;

var defaultSelectorOption = {
    all: {
        type: 'all',
        title: clone(langSelector.all)
    },
    inverse: {
        type: 'inverse',
        title: clone(langSelector.inverse)
    }
};

var LegendModel = extendComponentModel({

    type: 'legend.plain',

    dependencies: ['series'],

    layoutMode: {
        type: 'box',
        // legend.width/height are maxWidth/maxHeight actually,
        // whereas realy width/height is calculated by its content.
        // (Setting {left: 10, right: 10} does not make sense).
        // So consider the case:
        // `setOption({legend: {left: 10});`
        // then `setOption({legend: {right: 10});`
        // The previous `left` should be cleared by setting `ignoreSize`.
        ignoreSize: true
    },

    init: function (option, parentModel, ecModel) {
        this.mergeDefaultAndTheme(option, ecModel);

        option.selected = option.selected || {};
        this._updateSelector(option);
    },

    mergeOption: function (option) {
        LegendModel.superCall(this, 'mergeOption', option);
        this._updateSelector(option);
    },

    _updateSelector: function (option) {
        var selector = option.selector;
        if (selector === true) {
            selector = option.selector = ['all', 'inverse'];
        }
        if (isArray(selector)) {
            each$1(selector, function (item, index) {
                isString(item) && (item = {type: item});
                selector[index] = merge(item, defaultSelectorOption[item.type]);
            });
        }
    },

    optionUpdated: function () {
        this._updateData(this.ecModel);

        var legendData = this._data;

        // If selectedMode is single, try to select one
        if (legendData[0] && this.get('selectedMode') === 'single') {
            var hasSelected = false;
            // If has any selected in option.selected
            for (var i = 0; i < legendData.length; i++) {
                var name = legendData[i].get('name');
                if (this.isSelected(name)) {
                    // Force to unselect others
                    this.select(name);
                    hasSelected = true;
                    break;
                }
            }
            // Try select the first if selectedMode is single
            !hasSelected && this.select(legendData[0].get('name'));
        }
    },

    _updateData: function (ecModel) {
        var potentialData = [];
        var availableNames = [];

        ecModel.eachRawSeries(function (seriesModel) {
            var seriesName = seriesModel.name;
            availableNames.push(seriesName);
            var isPotential;

            if (seriesModel.legendDataProvider) {
                var data = seriesModel.legendDataProvider();
                var names = data.mapArray(data.getName);

                if (!ecModel.isSeriesFiltered(seriesModel)) {
                    availableNames = availableNames.concat(names);
                }

                if (names.length) {
                    potentialData = potentialData.concat(names);
                }
                else {
                    isPotential = true;
                }
            }
            else {
                isPotential = true;
            }

            if (isPotential && isNameSpecified(seriesModel)) {
                potentialData.push(seriesModel.name);
            }
        });

        /**
         * @type {Array.<string>}
         * @private
         */
        this._availableNames = availableNames;

        // If legend.data not specified in option, use availableNames as data,
        // which is convinient for user preparing option.
        var rawData = this.get('data') || potentialData;

        var legendData = map(rawData, function (dataItem) {
            // Can be string or number
            if (typeof dataItem === 'string' || typeof dataItem === 'number') {
                dataItem = {
                    name: dataItem
                };
            }
            return new Model(dataItem, this, this.ecModel);
        }, this);

        /**
         * @type {Array.<module:echarts/model/Model>}
         * @private
         */
        this._data = legendData;
    },

    /**
     * @return {Array.<module:echarts/model/Model>}
     */
    getData: function () {
        return this._data;
    },

    /**
     * @param {string} name
     */
    select: function (name) {
        var selected = this.option.selected;
        var selectedMode = this.get('selectedMode');
        if (selectedMode === 'single') {
            var data = this._data;
            each$1(data, function (dataItem) {
                selected[dataItem.get('name')] = false;
            });
        }
        selected[name] = true;
    },

    /**
     * @param {string} name
     */
    unSelect: function (name) {
        if (this.get('selectedMode') !== 'single') {
            this.option.selected[name] = false;
        }
    },

    /**
     * @param {string} name
     */
    toggleSelected: function (name) {
        var selected = this.option.selected;
        // Default is true
        if (!selected.hasOwnProperty(name)) {
            selected[name] = true;
        }
        this[selected[name] ? 'unSelect' : 'select'](name);
    },

    allSelect: function () {
        var data = this._data;
        var selected = this.option.selected;
        each$1(data, function (dataItem) {
            selected[dataItem.get('name', true)] = true;
        });
    },

    inverseSelect: function () {
        var data = this._data;
        var selected = this.option.selected;
        each$1(data, function (dataItem) {
            var name = dataItem.get('name', true);
            // Initially, default value is true
            if (!selected.hasOwnProperty(name)) {
                selected[name] = true;
            }
            selected[name] = !selected[name];
        });
    },

    /**
     * @param {string} name
     */
    isSelected: function (name) {
        var selected = this.option.selected;
        return !(selected.hasOwnProperty(name) && !selected[name])
            && indexOf(this._availableNames, name) >= 0;
    },

    getOrient: function () {
        return this.get('orient') === 'vertical'
            ? {index: 1, name: 'vertical'}
            : {index: 0, name: 'horizontal'};
    },

    defaultOption: {
        // 一级层叠
        zlevel: 0,
        // 二级层叠
        z: 4,
        show: true,

        // 布局方式，默认为水平布局，可选为：
        // 'horizontal' | 'vertical'
        orient: 'horizontal',

        left: 'center',
        // right: 'center',

        top: 0,
        // bottom: null,

        // 水平对齐
        // 'auto' | 'left' | 'right'
        // 默认为 'auto', 根据 x 的位置判断是左对齐还是右对齐
        align: 'auto',

        backgroundColor: 'rgba(0,0,0,0)',
        // 图例边框颜色
        borderColor: '#ccc',
        borderRadius: 0,
        // 图例边框线宽，单位px，默认为0（无边框）
        borderWidth: 0,
        // 图例内边距，单位px，默认各方向内边距为5，
        // 接受数组分别设定上右下左边距，同css
        padding: 5,
        // 各个item之间的间隔，单位px，默认为10，
        // 横向布局时为水平间隔，纵向布局时为纵向间隔
        itemGap: 10,
        // the width of legend symbol
        itemWidth: 25,
        // the height of legend symbol
        itemHeight: 14,

        // the color of unselected legend symbol
        inactiveColor: '#ccc',

        // the borderColor of unselected legend symbol
        inactiveBorderColor: '#ccc',

        itemStyle: {
            // the default borderWidth of legend symbol
            borderWidth: 0
        },

        textStyle: {
            // 图例文字颜色
            color: '#333'
        },
        // formatter: '',
        // 选择模式，默认开启图例开关
        selectedMode: true,
        // 配置默认选中状态，可配合LEGEND.SELECTED事件做动态数据载入
        // selected: null,
        // 图例内容（详见legend.data，数组中每一项代表一个item
        // data: [],

        // Usage:
        // selector: [{type: 'all or inverse', title: xxx}]
        // or
        // selector: true
        // or
        // selector: ['all', 'inverse']
        selector: false,

        selectorLabel: {
            show: true,
            borderRadius: 10,
            padding: [3, 5, 3, 5],
            fontSize: 12,
            fontFamily: ' sans-serif',
            color: '#666',
            borderWidth: 1,
            borderColor: '#666'
        },

        emphasis: {
            selectorLabel: {
                show: true,
                color: '#eee',
                backgroundColor: '#666'
            }
        },

        // Value can be 'start' or 'end'
        selectorPosition: 'auto',

        selectorItemGap: 7,

        selectorButtonGap: 10,

        // Tooltip 相关配置
        tooltip: {
            show: false
        }
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

function legendSelectActionHandler(methodName, payload, ecModel) {
    var selectedMap = {};
    var isToggleSelect = methodName === 'toggleSelected';
    var isSelected;
    // Update all legend components
    ecModel.eachComponent('legend', function (legendModel) {
        if (isToggleSelect && isSelected != null) {
            // Force other legend has same selected status
            // Or the first is toggled to true and other are toggled to false
            // In the case one legend has some item unSelected in option. And if other legend
            // doesn't has the item, they will assume it is selected.
            legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
        }
        else if (methodName === 'allSelect' || methodName === 'inverseSelect') {
            legendModel[methodName]();
        }
        else {
            legendModel[methodName](payload.name);
            isSelected = legendModel.isSelected(payload.name);
        }
        var legendData = legendModel.getData();
        each$1(legendData, function (model) {
            var name = model.get('name');
            // Wrap element
            if (name === '\n' || name === '') {
                return;
            }
            var isItemSelected = legendModel.isSelected(name);
            if (selectedMap.hasOwnProperty(name)) {
                // Unselected if any legend is unselected
                selectedMap[name] = selectedMap[name] && isItemSelected;
            }
            else {
                selectedMap[name] = isItemSelected;
            }
        });
    });
    // Return the event explicitly
    return (methodName === 'allSelect' || methodName === 'inverseSelect')
        ? {
            selected: selectedMap
        }
        : {
            name: payload.name,
            selected: selectedMap
        };
}
/**
 * @event legendToggleSelect
 * @type {Object}
 * @property {string} type 'legendToggleSelect'
 * @property {string} [from]
 * @property {string} name Series name or data item name
 */
registerAction(
    'legendToggleSelect', 'legendselectchanged',
    curry(legendSelectActionHandler, 'toggleSelected')
);

registerAction(
    'legendAllSelect', 'legendselectall',
    curry(legendSelectActionHandler, 'allSelect')
);

registerAction(
    'legendInverseSelect', 'legendinverseselect',
    curry(legendSelectActionHandler, 'inverseSelect')
);

/**
 * @event legendSelect
 * @type {Object}
 * @property {string} type 'legendSelect'
 * @property {string} name Series name or data item name
 */
registerAction(
    'legendSelect', 'legendselected',
    curry(legendSelectActionHandler, 'select')
);

/**
 * @event legendUnSelect
 * @type {Object}
 * @property {string} type 'legendUnSelect'
 * @property {string} name Series name or data item name
 */
registerAction(
    'legendUnSelect', 'legendunselected',
    curry(legendSelectActionHandler, 'unSelect')
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var curry$6 = curry;
var each$25 = each$1;
var Group$3 = Group;

var LegendView = extendComponentView({

    type: 'legend.plain',

    newlineDisabled: false,

    /**
     * @override
     */
    init: function () {

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this.group.add(this._contentGroup = new Group$3());

        /**
         * @private
         * @type {module:zrender/Element}
         */
        this._backgroundEl;

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this.group.add(this._selectorGroup = new Group$3());

        /**
         * If first rendering, `contentGroup.position` is [0, 0], which
         * does not make sense and may cause unexepcted animation if adopted.
         * @private
         * @type {boolean}
         */
        this._isFirstRender = true;
    },

    /**
     * @protected
     */
    getContentGroup: function () {
        return this._contentGroup;
    },

    /**
     * @protected
     */
    getSelectorGroup: function () {
        return this._selectorGroup;
    },

    /**
     * @override
     */
    render: function (legendModel, ecModel, api) {
        var isFirstRender = this._isFirstRender;
        this._isFirstRender = false;

        this.resetInner();

        if (!legendModel.get('show', true)) {
            return;
        }

        var itemAlign = legendModel.get('align');
        var orient = legendModel.get('orient');
        if (!itemAlign || itemAlign === 'auto') {
            itemAlign = (
                legendModel.get('left') === 'right'
                && orient === 'vertical'
            ) ? 'right' : 'left';
        }

        var selector = legendModel.get('selector', true);
        var selectorPosition = legendModel.get('selectorPosition', true);
        if (selector && (!selectorPosition || selectorPosition === 'auto')) {
            selectorPosition = orient === 'horizontal' ? 'end' : 'start';
        }

        this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);

        // Perform layout.
        var positionInfo = legendModel.getBoxLayoutParams();
        var viewportSize = {width: api.getWidth(), height: api.getHeight()};
        var padding = legendModel.get('padding');

        var maxSize = getLayoutRect(positionInfo, viewportSize, padding);

        var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition);

        // Place mainGroup, based on the calculated `mainRect`.
        var layoutRect = getLayoutRect(
            defaults({width: mainRect.width, height: mainRect.height}, positionInfo),
            viewportSize,
            padding
        );
        this.group.attr('position', [layoutRect.x - mainRect.x, layoutRect.y - mainRect.y]);

        // Render background after group is layout.
        this.group.add(
            this._backgroundEl = makeBackground(mainRect, legendModel)
        );
    },

    /**
     * @protected
     */
    resetInner: function () {
        this.getContentGroup().removeAll();
        this._backgroundEl && this.group.remove(this._backgroundEl);
        this.getSelectorGroup().removeAll();
    },

    /**
     * @protected
     */
    renderInner: function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
        var contentGroup = this.getContentGroup();
        var legendDrawnMap = createHashMap();
        var selectMode = legendModel.get('selectedMode');

        var excludeSeriesId = [];
        ecModel.eachRawSeries(function (seriesModel) {
            !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id);
        });

        each$25(legendModel.getData(), function (itemModel, dataIndex) {
            var name = itemModel.get('name');

            // Use empty string or \n as a newline string
            if (!this.newlineDisabled && (name === '' || name === '\n')) {
                contentGroup.add(new Group$3({
                    newline: true
                }));
                return;
            }

            // Representitive series.
            var seriesModel = ecModel.getSeriesByName(name)[0];

            if (legendDrawnMap.get(name)) {
                // Have been drawed
                return;
            }

            // Series legend
            if (seriesModel) {
                var data = seriesModel.getData();
                var color = data.getVisual('color');
                var borderColor = data.getVisual('borderColor');

                // If color is a callback function
                if (typeof color === 'function') {
                    // Use the first data
                    color = color(seriesModel.getDataParams(0));
                }

                 // If borderColor is a callback function
                if (typeof borderColor === 'function') {
                    // Use the first data
                    borderColor = borderColor(seriesModel.getDataParams(0));
                }

                // Using rect symbol defaultly
                var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
                var symbolType = data.getVisual('symbol');

                var itemGroup = this._createItem(
                    name, dataIndex, itemModel, legendModel,
                    legendSymbolType, symbolType,
                    itemAlign, color, borderColor,
                    selectMode
                );

                itemGroup.on('click', curry$6(dispatchSelectAction, name, api))
                    .on('mouseover', curry$6(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId))
                    .on('mouseout', curry$6(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));

                legendDrawnMap.set(name, true);
            }
            else {
                // Data legend of pie, funnel
                ecModel.eachRawSeries(function (seriesModel) {
                    // In case multiple series has same data name
                    if (legendDrawnMap.get(name)) {
                        return;
                    }

                    if (seriesModel.legendDataProvider) {
                        var data = seriesModel.legendDataProvider();
                        var idx = data.indexOfName(name);
                        if (idx < 0) {
                            return;
                        }

                        var color = data.getItemVisual(idx, 'color');
                        var borderColor = data.getItemVisual(idx, 'borderColor');

                        var legendSymbolType = 'roundRect';

                        var itemGroup = this._createItem(
                            name, dataIndex, itemModel, legendModel,
                            legendSymbolType, null,
                            itemAlign, color, borderColor,
                            selectMode
                        );

                        // FIXME: consider different series has items with the same name.
                        itemGroup.on('click', curry$6(dispatchSelectAction, name, api))
                            // Should not specify the series name, consider legend controls
                            // more than one pie series.
                            .on('mouseover', curry$6(dispatchHighlightAction, null, name, api, excludeSeriesId))
                            .on('mouseout', curry$6(dispatchDownplayAction, null, name, api, excludeSeriesId));

                        legendDrawnMap.set(name, true);
                    }

                }, this);
            }

            if (__DEV__) {
                if (!legendDrawnMap.get(name)) {
                    console.warn(
                        name + ' series not exists. Legend data should be same with series name or data name.'
                    );
                }
            }
        }, this);

        if (selector) {
            this._createSelector(selector, legendModel, api, orient, selectorPosition);
        }
    },

    _createSelector: function (selector, legendModel, api, orient, selectorPosition) {
        var selectorGroup = this.getSelectorGroup();

        each$25(selector, function (selectorItem) {
            createSelectorButton(selectorItem);
        });

        function createSelectorButton(selectorItem) {
            var type = selectorItem.type;

            var labelText = new Text({
                style: {
                    x: 0,
                    y: 0,
                    align: 'center',
                    verticalAlign: 'middle'
                },
                onclick: function () {
                    api.dispatchAction({
                        type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect'
                    });
                }
            });

            selectorGroup.add(labelText);

            var labelModel = legendModel.getModel('selectorLabel');
            var emphasisLabelModel = legendModel.getModel('emphasis.selectorLabel');

            setLabelStyle(
                labelText.style, labelText.hoverStyle = {}, labelModel, emphasisLabelModel,
                {
                    defaultText: selectorItem.title,
                    isRectText: false
                }
            );
            setHoverStyle(labelText);
        }
    },

    _createItem: function (
        name, dataIndex, itemModel, legendModel,
        legendSymbolType, symbolType,
        itemAlign, color, borderColor, selectMode
    ) {
        var itemWidth = legendModel.get('itemWidth');
        var itemHeight = legendModel.get('itemHeight');
        var inactiveColor = legendModel.get('inactiveColor');
        var inactiveBorderColor = legendModel.get('inactiveBorderColor');
        var symbolKeepAspect = legendModel.get('symbolKeepAspect');
        var legendModelItemStyle = legendModel.getModel('itemStyle');

        var isSelected = legendModel.isSelected(name);
        var itemGroup = new Group$3();

        var textStyleModel = itemModel.getModel('textStyle');

        var itemIcon = itemModel.get('icon');

        var tooltipModel = itemModel.getModel('tooltip');
        var legendGlobalTooltipModel = tooltipModel.parentModel;

        // Use user given icon first
        legendSymbolType = itemIcon || legendSymbolType;
        var legendSymbol = createSymbol(
            legendSymbolType,
            0,
            0,
            itemWidth,
            itemHeight,
            isSelected ? color : inactiveColor,
            // symbolKeepAspect default true for legend
            symbolKeepAspect == null ? true : symbolKeepAspect
        );
        itemGroup.add(
            setSymbolStyle(
                legendSymbol, legendSymbolType, legendModelItemStyle,
                borderColor, inactiveBorderColor, isSelected
            )
        );

        // Compose symbols
        // PENDING
        if (!itemIcon && symbolType
            // At least show one symbol, can't be all none
            && ((symbolType !== legendSymbolType) || symbolType === 'none')
        ) {
            var size = itemHeight * 0.8;
            if (symbolType === 'none') {
                symbolType = 'circle';
            }
            var legendSymbolCenter = createSymbol(
                symbolType,
                (itemWidth - size) / 2,
                (itemHeight - size) / 2,
                size,
                size,
                isSelected ? color : inactiveColor,
                // symbolKeepAspect default true for legend
                symbolKeepAspect == null ? true : symbolKeepAspect
            );
            // Put symbol in the center
            itemGroup.add(
                setSymbolStyle(
                    legendSymbolCenter, symbolType, legendModelItemStyle,
                    borderColor, inactiveBorderColor, isSelected
                )
            );
        }

        var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
        var textAlign = itemAlign;

        var formatter = legendModel.get('formatter');
        var content = name;
        if (typeof formatter === 'string' && formatter) {
            content = formatter.replace('{name}', name != null ? name : '');
        }
        else if (typeof formatter === 'function') {
            content = formatter(name);
        }

        itemGroup.add(new Text({
            style: setTextStyle({}, textStyleModel, {
                text: content,
                x: textX,
                y: itemHeight / 2,
                textFill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
                textAlign: textAlign,
                textVerticalAlign: 'middle'
            })
        }));

        // Add a invisible rect to increase the area of mouse hover
        var hitRect = new Rect({
            shape: itemGroup.getBoundingRect(),
            invisible: true,
            tooltip: tooltipModel.get('show') ? extend({
                content: name,
                // Defaul formatter
                formatter: legendGlobalTooltipModel.get('formatter', true) || function () {
                    return name;
                },
                formatterParams: {
                    componentType: 'legend',
                    legendIndex: legendModel.componentIndex,
                    name: name,
                    $vars: ['name']
                }
            }, tooltipModel.option) : null
        });
        itemGroup.add(hitRect);

        itemGroup.eachChild(function (child) {
            child.silent = true;
        });

        hitRect.silent = !selectMode;

        this.getContentGroup().add(itemGroup);

        setHoverStyle(itemGroup);

        itemGroup.__legendDataIndex = dataIndex;

        return itemGroup;
    },

    /**
     * @protected
     */
    layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
        var contentGroup = this.getContentGroup();
        var selectorGroup = this.getSelectorGroup();

        // Place items in contentGroup.
        box(
            legendModel.get('orient'),
            contentGroup,
            legendModel.get('itemGap'),
            maxSize.width,
            maxSize.height
        );

        var contentRect = contentGroup.getBoundingRect();
        var contentPos = [-contentRect.x, -contentRect.y];

        if (selector) {
            // Place buttons in selectorGroup
            box(
                // Buttons in selectorGroup always layout horizontally
                'horizontal',
                selectorGroup,
                legendModel.get('selectorItemGap', true)
            );

            var selectorRect = selectorGroup.getBoundingRect();
            var selectorPos = [-selectorRect.x, -selectorRect.y];
            var selectorButtonGap = legendModel.get('selectorButtonGap', true);

            var orientIdx = legendModel.getOrient().index;
            var wh = orientIdx === 0 ? 'width' : 'height';
            var hw = orientIdx === 0 ? 'height' : 'width';
            var yx = orientIdx === 0 ? 'y' : 'x';

            if (selectorPosition === 'end') {
                selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap;
            }
            else {
                contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap;
            }

            //Always align selector to content as 'middle'
            selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2;
            selectorGroup.attr('position', selectorPos);
            contentGroup.attr('position', contentPos);

            var mainRect = {x: 0, y: 0};
            mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh];
            mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]);
            mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]);
            return mainRect;
        }
        else {
            contentGroup.attr('position', contentPos);
            return this.group.getBoundingRect();
        }
    },

    /**
     * @protected
     */
    remove: function () {
        this.getContentGroup().removeAll();
        this._isFirstRender = true;
    }

});

function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, isSelected) {
    var itemStyle;
    if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) {
        itemStyle = legendModelItemStyle.getItemStyle();
        symbol.style.stroke = borderColor;
        if (!isSelected) {
            itemStyle.stroke = inactiveBorderColor;
        }
    }
    else {
        itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']);
    }
    return symbol.setStyle(itemStyle);
}

function dispatchSelectAction(name, api) {
    api.dispatchAction({
        type: 'legendToggleSelect',
        name: name
    });
}

function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
    // If element hover will move to a hoverLayer.
    var el = api.getZr().storage.getDisplayList()[0];
    if (!(el && el.useHoverLayer)) {
        api.dispatchAction({
            type: 'highlight',
            seriesName: seriesName,
            name: dataName,
            excludeSeriesId: excludeSeriesId
        });
    }
}

function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) {
    // If element hover will move to a hoverLayer.
    var el = api.getZr().storage.getDisplayList()[0];
    if (!(el && el.useHoverLayer)) {
        api.dispatchAction({
            type: 'downplay',
            seriesName: seriesName,
            name: dataName,
            excludeSeriesId: excludeSeriesId
        });
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var legendFilter = function (ecModel) {

    var legendModels = ecModel.findComponents({
        mainType: 'legend'
    });
    if (legendModels && legendModels.length) {
        ecModel.filterSeries(function (series) {
            // If in any legend component the status is not selected.
            // Because in legend series is assumed selected when it is not in the legend data.
            for (var i = 0; i < legendModels.length; i++) {
                if (!legendModels[i].isSelected(series.name)) {
                    return false;
                }
            }
            return true;
        });
    }

};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


// Do not contain scrollable legend, for sake of file size.

// Series Filter
registerProcessor(PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter);

ComponentModel.registerSubTypeDefaulter('legend', function () {
    // Default 'plain' when no type specified.
    return 'plain';
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var ScrollableLegendModel = LegendModel.extend({

    type: 'legend.scroll',

    /**
     * @param {number} scrollDataIndex
     */
    setScrollDataIndex: function (scrollDataIndex) {
        this.option.scrollDataIndex = scrollDataIndex;
    },

    defaultOption: {
        scrollDataIndex: 0,
        pageButtonItemGap: 5,
        pageButtonGap: null,
        pageButtonPosition: 'end', // 'start' or 'end'
        pageFormatter: '{current}/{total}', // If null/undefined, do not show page.
        pageIcons: {
            horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'],
            vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z']
        },
        pageIconColor: '#2f4554',
        pageIconInactiveColor: '#aaa',
        pageIconSize: 15, // Can be [10, 3], which represents [width, height]
        pageTextStyle: {
            color: '#333'
        },

        animationDurationUpdate: 800
    },

    /**
     * @override
     */
    init: function (option, parentModel, ecModel, extraOpt) {
        var inputPositionParams = getLayoutParams(option);

        ScrollableLegendModel.superCall(this, 'init', option, parentModel, ecModel, extraOpt);

        mergeAndNormalizeLayoutParams$1(this, option, inputPositionParams);
    },

    /**
     * @override
     */
    mergeOption: function (option, extraOpt) {
        ScrollableLegendModel.superCall(this, 'mergeOption', option, extraOpt);

        mergeAndNormalizeLayoutParams$1(this, this.option, option);
    }

});

// Do not `ignoreSize` to enable setting {left: 10, right: 10}.
function mergeAndNormalizeLayoutParams$1(legendModel, target, raw) {
    var orient = legendModel.getOrient();
    var ignoreSize = [1, 1];
    ignoreSize[orient.index] = 0;
    mergeLayoutParam(target, raw, {
        type: 'box', ignoreSize: ignoreSize
    });
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Separate legend and scrollable legend to reduce package size.
 */

var Group$4 = Group;

var WH$1 = ['width', 'height'];
var XY$1 = ['x', 'y'];

var ScrollableLegendView = LegendView.extend({

    type: 'legend.scroll',

    newlineDisabled: true,

    init: function () {

        ScrollableLegendView.superCall(this, 'init');

        /**
         * @private
         * @type {number} For `scroll`.
         */
        this._currentIndex = 0;

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this.group.add(this._containerGroup = new Group$4());
        this._containerGroup.add(this.getContentGroup());

        /**
         * @private
         * @type {module:zrender/container/Group}
         */
        this.group.add(this._controllerGroup = new Group$4());

        /**
         *
         * @private
         */
        this._showController;
    },

    /**
     * @override
     */
    resetInner: function () {
        ScrollableLegendView.superCall(this, 'resetInner');

        this._controllerGroup.removeAll();
        this._containerGroup.removeClipPath();
        this._containerGroup.__rectSize = null;
    },

    /**
     * @override
     */
    renderInner: function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
        var me = this;

        // Render content items.
        ScrollableLegendView.superCall(this, 'renderInner', itemAlign,
            legendModel, ecModel, api, selector, orient, selectorPosition);

        var controllerGroup = this._controllerGroup;

        // FIXME: support be 'auto' adapt to size number text length,
        // e.g., '3/12345' should not overlap with the control arrow button.
        var pageIconSize = legendModel.get('pageIconSize', true);
        if (!isArray(pageIconSize)) {
            pageIconSize = [pageIconSize, pageIconSize];
        }

        createPageButton('pagePrev', 0);

        var pageTextStyleModel = legendModel.getModel('pageTextStyle');
        controllerGroup.add(new Text({
            name: 'pageText',
            style: {
                textFill: pageTextStyleModel.getTextColor(),
                font: pageTextStyleModel.getFont(),
                textVerticalAlign: 'middle',
                textAlign: 'center'
            },
            silent: true
        }));

        createPageButton('pageNext', 1);

        function createPageButton(name, iconIdx) {
            var pageDataIndexName = name + 'DataIndex';
            var icon = createIcon(
                legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx],
                {
                    // Buttons will be created in each render, so we do not need
                    // to worry about avoiding using legendModel kept in scope.
                    onclick: bind(
                        me._pageGo, me, pageDataIndexName, legendModel, api
                    )
                },
                {
                    x: -pageIconSize[0] / 2,
                    y: -pageIconSize[1] / 2,
                    width: pageIconSize[0],
                    height: pageIconSize[1]
                }
            );
            icon.name = name;
            controllerGroup.add(icon);
        }
    },

    /**
     * @override
     */
    layoutInner: function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
        var selectorGroup = this.getSelectorGroup();

        var orientIdx = legendModel.getOrient().index;
        var wh = WH$1[orientIdx];
        var xy = XY$1[orientIdx];
        var hw = WH$1[1 - orientIdx];
        var yx = XY$1[1 - orientIdx];

        selector && box(
            // Buttons in selectorGroup always layout horizontally
            'horizontal',
            selectorGroup,
            legendModel.get('selectorItemGap', true)
        );

        var selectorButtonGap = legendModel.get('selectorButtonGap', true);
        var selectorRect = selectorGroup.getBoundingRect();
        var selectorPos = [-selectorRect.x, -selectorRect.y];

        var processMaxSize = clone(maxSize);
        selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap);

        var mainRect = this._layoutContentAndController(legendModel, isFirstRender,
            processMaxSize, orientIdx, wh, hw, yx
        );

        if (selector) {
            if (selectorPosition === 'end') {
                selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap;
            }
            else {
                var offset = selectorRect[wh] + selectorButtonGap;
                selectorPos[orientIdx] -= offset;
                mainRect[xy] -= offset;
            }
            mainRect[wh] += selectorRect[wh] + selectorButtonGap;

            selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2;
            mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]);
            mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]);

            selectorGroup.attr('position', selectorPos);
        }

        return mainRect;
    },

    _layoutContentAndController: function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx) {
        var contentGroup = this.getContentGroup();
        var containerGroup = this._containerGroup;
        var controllerGroup = this._controllerGroup;

        // Place items in contentGroup.
        box(
            legendModel.get('orient'),
            contentGroup,
            legendModel.get('itemGap'),
            !orientIdx ? null : maxSize.width,
            orientIdx ? null : maxSize.height
        );

        box(
            // Buttons in controller are layout always horizontally.
            'horizontal',
            controllerGroup,
            legendModel.get('pageButtonItemGap', true)
        );

        var contentRect = contentGroup.getBoundingRect();
        var controllerRect = controllerGroup.getBoundingRect();
        var showController = this._showController = contentRect[wh] > maxSize[wh];

        var contentPos = [-contentRect.x, -contentRect.y];
        // Remain contentPos when scroll animation perfroming.
        // If first rendering, `contentGroup.position` is [0, 0], which
        // does not make sense and may cause unexepcted animation if adopted.
        if (!isFirstRender) {
            contentPos[orientIdx] = contentGroup.position[orientIdx];
        }

        // Layout container group based on 0.
        var containerPos = [0, 0];
        var controllerPos = [-controllerRect.x, -controllerRect.y];
        var pageButtonGap = retrieve2(
            legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true)
        );

        // Place containerGroup and controllerGroup and contentGroup.
        if (showController) {
            var pageButtonPosition = legendModel.get('pageButtonPosition', true);
            // controller is on the right / bottom.
            if (pageButtonPosition === 'end') {
                controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh];
            }
            // controller is on the left / top.
            else {
                containerPos[orientIdx] += controllerRect[wh] + pageButtonGap;
            }
        }

        // Always align controller to content as 'middle'.
        controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2;

        contentGroup.attr('position', contentPos);
        containerGroup.attr('position', containerPos);
        controllerGroup.attr('position', controllerPos);

        // Calculate `mainRect` and set `clipPath`.
        // mainRect should not be calculated by `this.group.getBoundingRect()`
        // for sake of the overflow.
        var mainRect = {x: 0, y: 0};

        // Consider content may be overflow (should be clipped).
        mainRect[wh] = showController ? maxSize[wh] : contentRect[wh];
        mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]);

        // `containerRect[yx] + containerPos[1 - orientIdx]` is 0.
        mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]);

        containerGroup.__rectSize = maxSize[wh];
        if (showController) {
            var clipShape = {x: 0, y: 0};
            clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0);
            clipShape[hw] = mainRect[hw];
            containerGroup.setClipPath(new Rect({shape: clipShape}));
            // Consider content may be larger than container, container rect
            // can not be obtained from `containerGroup.getBoundingRect()`.
            containerGroup.__rectSize = clipShape[wh];
        }
        else {
            // Do not remove or ignore controller. Keep them set as placeholders.
            controllerGroup.eachChild(function (child) {
                child.attr({invisible: true, silent: true});
            });
        }

        // Content translate animation.
        var pageInfo = this._getPageInfo(legendModel);
        pageInfo.pageIndex != null && updateProps(
            contentGroup,
            {position: pageInfo.contentPosition},
            // When switch from "show controller" to "not show controller", view should be
            // updated immediately without animation, otherwise causes weird effect.
            showController ? legendModel : false
        );

        this._updatePageInfoView(legendModel, pageInfo);

        return mainRect;
    },

    _pageGo: function (to, legendModel, api) {
        var scrollDataIndex = this._getPageInfo(legendModel)[to];

        scrollDataIndex != null && api.dispatchAction({
            type: 'legendScroll',
            scrollDataIndex: scrollDataIndex,
            legendId: legendModel.id
        });
    },

    _updatePageInfoView: function (legendModel, pageInfo) {
        var controllerGroup = this._controllerGroup;

        each$1(['pagePrev', 'pageNext'], function (name) {
            var canJump = pageInfo[name + 'DataIndex'] != null;
            var icon = controllerGroup.childOfName(name);
            if (icon) {
                icon.setStyle(
                    'fill',
                    canJump
                        ? legendModel.get('pageIconColor', true)
                        : legendModel.get('pageIconInactiveColor', true)
                );
                icon.cursor = canJump ? 'pointer' : 'default';
            }
        });

        var pageText = controllerGroup.childOfName('pageText');
        var pageFormatter = legendModel.get('pageFormatter');
        var pageIndex = pageInfo.pageIndex;
        var current = pageIndex != null ? pageIndex + 1 : 0;
        var total = pageInfo.pageCount;

        pageText && pageFormatter && pageText.setStyle(
            'text',
            isString(pageFormatter)
                ? pageFormatter.replace('{current}', current).replace('{total}', total)
                : pageFormatter({current: current, total: total})
        );
    },

    /**
     * @param {module:echarts/model/Model} legendModel
     * @return {Object} {
     *  contentPosition: Array.<number>, null when data item not found.
     *  pageIndex: number, null when data item not found.
     *  pageCount: number, always be a number, can be 0.
     *  pagePrevDataIndex: number, null when no previous page.
     *  pageNextDataIndex: number, null when no next page.
     * }
     */
    _getPageInfo: function (legendModel) {
        var scrollDataIndex = legendModel.get('scrollDataIndex', true);
        var contentGroup = this.getContentGroup();
        var containerRectSize = this._containerGroup.__rectSize;
        var orientIdx = legendModel.getOrient().index;
        var wh = WH$1[orientIdx];
        var xy = XY$1[orientIdx];

        var targetItemIndex = this._findTargetItemIndex(scrollDataIndex);
        var children = contentGroup.children();
        var targetItem = children[targetItemIndex];
        var itemCount = children.length;
        var pCount = !itemCount ? 0 : 1;

        var result = {
            contentPosition: contentGroup.position.slice(),
            pageCount: pCount,
            pageIndex: pCount - 1,
            pagePrevDataIndex: null,
            pageNextDataIndex: null
        };

        if (!targetItem) {
            return result;
        }

        var targetItemInfo = getItemInfo(targetItem);
        result.contentPosition[orientIdx] = -targetItemInfo.s;

        // Strategy:
        // (1) Always align based on the left/top most item.
        // (2) It is user-friendly that the last item shown in the
        // current window is shown at the begining of next window.
        // Otherwise if half of the last item is cut by the window,
        // it will have no chance to display entirely.
        // (3) Consider that item size probably be different, we
        // have calculate pageIndex by size rather than item index,
        // and we can not get page index directly by division.
        // (4) The window is to narrow to contain more than
        // one item, we should make sure that the page can be fliped.

        for (var i = targetItemIndex + 1,
            winStartItemInfo = targetItemInfo,
            winEndItemInfo = targetItemInfo,
            currItemInfo = null;
            i <= itemCount;
            ++i
        ) {
            currItemInfo = getItemInfo(children[i]);
            if (
                // Half of the last item is out of the window.
                (!currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize)
                // If the current item does not intersect with the window, the new page
                // can be started at the current item or the last item.
                || (currItemInfo && !intersect(currItemInfo, winStartItemInfo.s))
            ) {
                if (winEndItemInfo.i > winStartItemInfo.i) {
                    winStartItemInfo = winEndItemInfo;
                }
                else { // e.g., when page size is smaller than item size.
                    winStartItemInfo = currItemInfo;
                }
                if (winStartItemInfo) {
                    if (result.pageNextDataIndex == null) {
                        result.pageNextDataIndex = winStartItemInfo.i;
                    }
                    ++result.pageCount;
                }
            }
            winEndItemInfo = currItemInfo;
        }

        for (var i = targetItemIndex - 1,
            winStartItemInfo = targetItemInfo,
            winEndItemInfo = targetItemInfo,
            currItemInfo = null;
            i >= -1;
            --i
        ) {
            currItemInfo = getItemInfo(children[i]);
            if (
                // If the the end item does not intersect with the window started
                // from the current item, a page can be settled.
                (!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s))
                // e.g., when page size is smaller than item size.
                && winStartItemInfo.i < winEndItemInfo.i
            ) {
                winEndItemInfo = winStartItemInfo;
                if (result.pagePrevDataIndex == null) {
                    result.pagePrevDataIndex = winStartItemInfo.i;
                }
                ++result.pageCount;
                ++result.pageIndex;
            }
            winStartItemInfo = currItemInfo;
        }

        return result;

        function getItemInfo(el) {
            if (el) {
                var itemRect = el.getBoundingRect();
                var start = itemRect[xy] + el.position[orientIdx];
                return {
                    s: start,
                    e: start + itemRect[wh],
                    i: el.__legendDataIndex
                };
            }
        }

        function intersect(itemInfo, winStart) {
            return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize;
        }
    },

    _findTargetItemIndex: function (targetDataIndex) {
        var index;
        var contentGroup = this.getContentGroup();
        var defaultIndex;

        if (this._showController) {
            contentGroup.eachChild(function (child, idx) {
                var legendDataIdx = child.__legendDataIndex;
                // FIXME
                // If the given targetDataIndex (from model) is illegal,
                // we use defualtIndex. But the index on the legend model and
                // action payload is still illegal. That case will not be
                // changed until some scenario requires.
                if (defaultIndex == null && legendDataIdx != null) {
                    defaultIndex = idx;
                }
                if (legendDataIdx === targetDataIndex) {
                    index = idx;
                }
            });
        }

        return index != null ? index : defaultIndex;
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @event legendScroll
 * @type {Object}
 * @property {string} type 'legendScroll'
 * @property {string} scrollDataIndex
 */
registerAction(
    'legendScroll', 'legendscroll',
    function (payload, ecModel) {
        var scrollDataIndex = payload.scrollDataIndex;

        scrollDataIndex != null && ecModel.eachComponent(
            {mainType: 'legend', subType: 'scroll', query: payload},
            function (legendModel) {
                legendModel.setScrollDataIndex(scrollDataIndex);
            }
        );
    }
);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Legend component entry file8
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var SliderZoomModel = DataZoomModel.extend({

    type: 'dataZoom.slider',

    layoutMode: 'box',

    /**
     * @protected
     */
    defaultOption: {
        show: true,

        // ph => placeholder. Using placehoder here because
        // deault value can only be drived in view stage.
        right: 'ph',  // Default align to grid rect.
        top: 'ph',    // Default align to grid rect.
        width: 'ph',  // Default align to grid rect.
        height: 'ph', // Default align to grid rect.
        left: null,   // Default align to grid rect.
        bottom: null, // Default align to grid rect.

        backgroundColor: 'rgba(47,69,84,0)',    // Background of slider zoom component.
        // dataBackgroundColor: '#ddd',         // Background coor of data shadow and border of box,
                                                // highest priority, remain for compatibility of
                                                // previous version, but not recommended any more.
        dataBackground: {
            lineStyle: {
                color: '#2f4554',
                width: 0.5,
                opacity: 0.3
            },
            areaStyle: {
                color: 'rgba(47,69,84,0.3)',
                opacity: 0.3
            }
        },
        borderColor: '#ddd',                    // border color of the box. For compatibility,
                                                // if dataBackgroundColor is set, borderColor
                                                // is ignored.

        fillerColor: 'rgba(167,183,204,0.4)',     // Color of selected area.
        // handleColor: 'rgba(89,170,216,0.95)',     // Color of handle.
        // handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z',
        /* eslint-disable */
        handleIcon: 'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z',
        /* eslint-enable */
        // Percent of the slider height
        handleSize: '100%',

        handleStyle: {
            color: '#a7b7cc'
        },

        labelPrecision: null,
        labelFormatter: null,
        showDetail: true,
        showDataShadow: 'auto',                 // Default auto decision.
        realtime: true,
        zoomLock: false,                        // Whether disable zoom.
        textStyle: {
            color: '#333'
        }
    }

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var Rect$2 = Rect;
var linearMap$1 = linearMap;
var asc$2 = asc;
var bind$5 = bind;
var each$26 = each$1;

// Constants
var DEFAULT_LOCATION_EDGE_GAP = 7;
var DEFAULT_FRAME_BORDER_WIDTH = 1;
var DEFAULT_FILLER_SIZE = 30;
var HORIZONTAL = 'horizontal';
var VERTICAL = 'vertical';
var LABEL_GAP = 5;
var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter'];

var SliderZoomView = DataZoomView.extend({

    type: 'dataZoom.slider',

    init: function (ecModel, api) {

        /**
         * @private
         * @type {Object}
         */
        this._displayables = {};

        /**
         * @private
         * @type {string}
         */
        this._orient;

        /**
         * [0, 100]
         * @private
         */
        this._range;

        /**
         * [coord of the first handle, coord of the second handle]
         * @private
         */
        this._handleEnds;

        /**
         * [length, thick]
         * @private
         * @type {Array.<number>}
         */
        this._size;

        /**
         * @private
         * @type {number}
         */
        this._handleWidth;

        /**
         * @private
         * @type {number}
         */
        this._handleHeight;

        /**
         * @private
         */
        this._location;

        /**
         * @private
         */
        this._dragging;

        /**
         * @private
         */
        this._dataShadowInfo;

        this.api = api;
    },

    /**
     * @override
     */
    render: function (dataZoomModel, ecModel, api, payload) {
        SliderZoomView.superApply(this, 'render', arguments);

        createOrUpdate(
            this,
            '_dispatchZoomAction',
            this.dataZoomModel.get('throttle'),
            'fixRate'
        );

        this._orient = dataZoomModel.get('orient');

        if (this.dataZoomModel.get('show') === false) {
            this.group.removeAll();
            return;
        }

        // Notice: this._resetInterval() should not be executed when payload.type
        // is 'dataZoom', origin this._range should be maintained, otherwise 'pan'
        // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction,
        if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
            this._buildView();
        }

        this._updateView();
    },

    /**
     * @override
     */
    remove: function () {
        SliderZoomView.superApply(this, 'remove', arguments);
        clear(this, '_dispatchZoomAction');
    },

    /**
     * @override
     */
    dispose: function () {
        SliderZoomView.superApply(this, 'dispose', arguments);
        clear(this, '_dispatchZoomAction');
    },

    _buildView: function () {
        var thisGroup = this.group;

        thisGroup.removeAll();

        this._resetLocation();
        this._resetInterval();

        var barGroup = this._displayables.barGroup = new Group();

        this._renderBackground();

        this._renderHandle();

        this._renderDataShadow();

        thisGroup.add(barGroup);

        this._positionGroup();
    },

    /**
     * @private
     */
    _resetLocation: function () {
        var dataZoomModel = this.dataZoomModel;
        var api = this.api;

        // If some of x/y/width/height are not specified,
        // auto-adapt according to target grid.
        var coordRect = this._findCoordRect();
        var ecSize = {width: api.getWidth(), height: api.getHeight()};
        // Default align by coordinate system rect.
        var positionInfo = this._orient === HORIZONTAL
            ? {
                // Why using 'right', because right should be used in vertical,
                // and it is better to be consistent for dealing with position param merge.
                right: ecSize.width - coordRect.x - coordRect.width,
                top: (ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP),
                width: coordRect.width,
                height: DEFAULT_FILLER_SIZE
            }
            : { // vertical
                right: DEFAULT_LOCATION_EDGE_GAP,
                top: coordRect.y,
                width: DEFAULT_FILLER_SIZE,
                height: coordRect.height
            };

        // Do not write back to option and replace value 'ph', because
        // the 'ph' value should be recalculated when resize.
        var layoutParams = getLayoutParams(dataZoomModel.option);

        // Replace the placeholder value.
        each$1(['right', 'top', 'width', 'height'], function (name) {
            if (layoutParams[name] === 'ph') {
                layoutParams[name] = positionInfo[name];
            }
        });

        var layoutRect = getLayoutRect(
            layoutParams,
            ecSize,
            dataZoomModel.padding
        );

        this._location = {x: layoutRect.x, y: layoutRect.y};
        this._size = [layoutRect.width, layoutRect.height];
        this._orient === VERTICAL && this._size.reverse();
    },

    /**
     * @private
     */
    _positionGroup: function () {
        var thisGroup = this.group;
        var location = this._location;
        var orient = this._orient;

        // Just use the first axis to determine mapping.
        var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel();
        var inverse = targetAxisModel && targetAxisModel.get('inverse');

        var barGroup = this._displayables.barGroup;
        var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse;

        // Transform barGroup.
        barGroup.attr(
            (orient === HORIZONTAL && !inverse)
            ? {scale: otherAxisInverse ? [1, 1] : [1, -1]}
            : (orient === HORIZONTAL && inverse)
            ? {scale: otherAxisInverse ? [-1, 1] : [-1, -1]}
            : (orient === VERTICAL && !inverse)
            ? {scale: otherAxisInverse ? [1, -1] : [1, 1], rotation: Math.PI / 2}
            // Dont use Math.PI, considering shadow direction.
            : {scale: otherAxisInverse ? [-1, -1] : [-1, 1], rotation: Math.PI / 2}
        );

        // Position barGroup
        var rect = thisGroup.getBoundingRect([barGroup]);
        thisGroup.attr('position', [location.x - rect.x, location.y - rect.y]);
    },

    /**
     * @private
     */
    _getViewExtent: function () {
        return [0, this._size[0]];
    },

    _renderBackground: function () {
        var dataZoomModel = this.dataZoomModel;
        var size = this._size;
        var barGroup = this._displayables.barGroup;

        barGroup.add(new Rect$2({
            silent: true,
            shape: {
                x: 0, y: 0, width: size[0], height: size[1]
            },
            style: {
                fill: dataZoomModel.get('backgroundColor')
            },
            z2: -40
        }));

        // Click panel, over shadow, below handles.
        barGroup.add(new Rect$2({
            shape: {
                x: 0, y: 0, width: size[0], height: size[1]
            },
            style: {
                fill: 'transparent'
            },
            z2: 0,
            onclick: bind(this._onClickPanelClick, this)
        }));
    },

    _renderDataShadow: function () {
        var info = this._dataShadowInfo = this._prepareDataShadowInfo();

        if (!info) {
            return;
        }

        var size = this._size;
        var seriesModel = info.series;
        var data = seriesModel.getRawData();

        var otherDim = seriesModel.getShadowDim
            ? seriesModel.getShadowDim() // @see candlestick
            : info.otherDim;

        if (otherDim == null) {
            return;
        }

        var otherDataExtent = data.getDataExtent(otherDim);
        // Nice extent.
        var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
        otherDataExtent = [
            otherDataExtent[0] - otherOffset,
            otherDataExtent[1] + otherOffset
        ];
        var otherShadowExtent = [0, size[1]];

        var thisShadowExtent = [0, size[0]];

        var areaPoints = [[size[0], 0], [0, 0]];
        var linePoints = [];
        var step = thisShadowExtent[1] / (data.count() - 1);
        var thisCoord = 0;

        // Optimize for large data shadow
        var stride = Math.round(data.count() / size[0]);
        var lastIsEmpty;
        data.each([otherDim], function (value, index) {
            if (stride > 0 && (index % stride)) {
                thisCoord += step;
                return;
            }

            // FIXME
            // Should consider axis.min/axis.max when drawing dataShadow.

            // FIXME
            // 应该使用统一的空判断？还是在list里进行空判断？
            var isEmpty = value == null || isNaN(value) || value === '';
            // See #4235.
            var otherCoord = isEmpty
                ? 0 : linearMap$1(value, otherDataExtent, otherShadowExtent, true);

            // Attempt to draw data shadow precisely when there are empty value.
            if (isEmpty && !lastIsEmpty && index) {
                areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
                linePoints.push([linePoints[linePoints.length - 1][0], 0]);
            }
            else if (!isEmpty && lastIsEmpty) {
                areaPoints.push([thisCoord, 0]);
                linePoints.push([thisCoord, 0]);
            }

            areaPoints.push([thisCoord, otherCoord]);
            linePoints.push([thisCoord, otherCoord]);

            thisCoord += step;
            lastIsEmpty = isEmpty;
        });

        var dataZoomModel = this.dataZoomModel;
        // var dataBackgroundModel = dataZoomModel.getModel('dataBackground');
        this._displayables.barGroup.add(new Polygon({
            shape: {points: areaPoints},
            style: defaults(
                {fill: dataZoomModel.get('dataBackgroundColor')},
                dataZoomModel.getModel('dataBackground.areaStyle').getAreaStyle()
            ),
            silent: true,
            z2: -20
        }));
        this._displayables.barGroup.add(new Polyline({
            shape: {points: linePoints},
            style: dataZoomModel.getModel('dataBackground.lineStyle').getLineStyle(),
            silent: true,
            z2: -19
        }));
    },

    _prepareDataShadowInfo: function () {
        var dataZoomModel = this.dataZoomModel;
        var showDataShadow = dataZoomModel.get('showDataShadow');

        if (showDataShadow === false) {
            return;
        }

        // Find a representative series.
        var result;
        var ecModel = this.ecModel;

        dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) {
            var seriesModels = dataZoomModel
                .getAxisProxy(dimNames.name, axisIndex)
                .getTargetSeriesModels();

            each$1(seriesModels, function (seriesModel) {
                if (result) {
                    return;
                }

                if (showDataShadow !== true && indexOf(
                        SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')
                    ) < 0
                ) {
                    return;
                }

                var thisAxis = ecModel.getComponent(dimNames.axis, axisIndex).axis;
                var otherDim = getOtherDim(dimNames.name);
                var otherAxisInverse;
                var coordSys = seriesModel.coordinateSystem;

                if (otherDim != null && coordSys.getOtherAxis) {
                    otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse;
                }

                otherDim = seriesModel.getData().mapDimension(otherDim);

                result = {
                    thisAxis: thisAxis,
                    series: seriesModel,
                    thisDim: dimNames.name,
                    otherDim: otherDim,
                    otherAxisInverse: otherAxisInverse
                };

            }, this);

        }, this);

        return result;
    },

    _renderHandle: function () {
        var displaybles = this._displayables;
        var handles = displaybles.handles = [];
        var handleLabels = displaybles.handleLabels = [];
        var barGroup = this._displayables.barGroup;
        var size = this._size;
        var dataZoomModel = this.dataZoomModel;

        barGroup.add(displaybles.filler = new Rect$2({
            draggable: true,
            cursor: getCursor(this._orient),
            drift: bind$5(this._onDragMove, this, 'all'),
            onmousemove: function (e) {
                // Fot mobile devicem, prevent screen slider on the button.
                stop(e.event);
            },
            ondragstart: bind$5(this._showDataInfo, this, true),
            ondragend: bind$5(this._onDragEnd, this),
            onmouseover: bind$5(this._showDataInfo, this, true),
            onmouseout: bind$5(this._showDataInfo, this, false),
            style: {
                fill: dataZoomModel.get('fillerColor'),
                textPosition: 'inside'
            }
        }));

        // Frame border.
        barGroup.add(new Rect$2({
            silent: true,
            subPixelOptimize: true,
            shape: {
                x: 0,
                y: 0,
                width: size[0],
                height: size[1]
            },
            style: {
                stroke: dataZoomModel.get('dataBackgroundColor')
                    || dataZoomModel.get('borderColor'),
                lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
                fill: 'rgba(0,0,0,0)'
            }
        }));

        each$26([0, 1], function (handleIndex) {
            var path = createIcon(
                dataZoomModel.get('handleIcon'),
                {
                    cursor: getCursor(this._orient),
                    draggable: true,
                    drift: bind$5(this._onDragMove, this, handleIndex),
                    onmousemove: function (e) {
                        // Fot mobile devicem, prevent screen slider on the button.
                        stop(e.event);
                    },
                    ondragend: bind$5(this._onDragEnd, this),
                    onmouseover: bind$5(this._showDataInfo, this, true),
                    onmouseout: bind$5(this._showDataInfo, this, false)
                },
                {x: -1, y: 0, width: 2, height: 2}
            );

            var bRect = path.getBoundingRect();
            this._handleHeight = parsePercent$1(dataZoomModel.get('handleSize'), this._size[1]);
            this._handleWidth = bRect.width / bRect.height * this._handleHeight;

            path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle());
            var handleColor = dataZoomModel.get('handleColor');
            // Compatitable with previous version
            if (handleColor != null) {
                path.style.fill = handleColor;
            }

            barGroup.add(handles[handleIndex] = path);

            var textStyleModel = dataZoomModel.textStyleModel;

            this.group.add(
                handleLabels[handleIndex] = new Text({
                silent: true,
                invisible: true,
                style: {
                    x: 0, y: 0, text: '',
                    textVerticalAlign: 'middle',
                    textAlign: 'center',
                    textFill: textStyleModel.getTextColor(),
                    textFont: textStyleModel.getFont()
                },
                z2: 10
            }));

        }, this);
    },

    /**
     * @private
     */
    _resetInterval: function () {
        var range = this._range = this.dataZoomModel.getPercentRange();
        var viewExtent = this._getViewExtent();

        this._handleEnds = [
            linearMap$1(range[0], [0, 100], viewExtent, true),
            linearMap$1(range[1], [0, 100], viewExtent, true)
        ];
    },

    /**
     * @private
     * @param {(number|string)} handleIndex 0 or 1 or 'all'
     * @param {number} delta
     * @return {boolean} changed
     */
    _updateInterval: function (handleIndex, delta) {
        var dataZoomModel = this.dataZoomModel;
        var handleEnds = this._handleEnds;
        var viewExtend = this._getViewExtent();
        var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
        var percentExtent = [0, 100];

        sliderMove(
            delta,
            handleEnds,
            viewExtend,
            dataZoomModel.get('zoomLock') ? 'all' : handleIndex,
            minMaxSpan.minSpan != null
                ? linearMap$1(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null,
            minMaxSpan.maxSpan != null
                ? linearMap$1(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null
        );

        var lastRange = this._range;
        var range = this._range = asc$2([
            linearMap$1(handleEnds[0], viewExtend, percentExtent, true),
            linearMap$1(handleEnds[1], viewExtend, percentExtent, true)
        ]);

        return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1];
    },

    /**
     * @private
     */
    _updateView: function (nonRealtime) {
        var displaybles = this._displayables;
        var handleEnds = this._handleEnds;
        var handleInterval = asc$2(handleEnds.slice());
        var size = this._size;

        each$26([0, 1], function (handleIndex) {
            // Handles
            var handle = displaybles.handles[handleIndex];
            var handleHeight = this._handleHeight;
            handle.attr({
                scale: [handleHeight / 2, handleHeight / 2],
                position: [handleEnds[handleIndex], size[1] / 2 - handleHeight / 2]
            });
        }, this);

        // Filler
        displaybles.filler.setShape({
            x: handleInterval[0],
            y: 0,
            width: handleInterval[1] - handleInterval[0],
            height: size[1]
        });

        this._updateDataInfo(nonRealtime);
    },

    /**
     * @private
     */
    _updateDataInfo: function (nonRealtime) {
        var dataZoomModel = this.dataZoomModel;
        var displaybles = this._displayables;
        var handleLabels = displaybles.handleLabels;
        var orient = this._orient;
        var labelTexts = ['', ''];

        // FIXME
        // date型，支持formatter，autoformatter（ec2 date.getAutoFormatter）
        if (dataZoomModel.get('showDetail')) {
            var axisProxy = dataZoomModel.findRepresentativeAxisProxy();

            if (axisProxy) {
                var axis = axisProxy.getAxisModel().axis;
                var range = this._range;

                var dataInterval = nonRealtime
                    // See #4434, data and axis are not processed and reset yet in non-realtime mode.
                    ? axisProxy.calculateDataWindow({
                        start: range[0], end: range[1]
                    }).valueWindow
                    : axisProxy.getDataValueWindow();

                labelTexts = [
                    this._formatLabel(dataInterval[0], axis),
                    this._formatLabel(dataInterval[1], axis)
                ];
            }
        }

        var orderedHandleEnds = asc$2(this._handleEnds.slice());

        setLabel.call(this, 0);
        setLabel.call(this, 1);

        function setLabel(handleIndex) {
            // Label
            // Text should not transform by barGroup.
            // Ignore handlers transform
            var barTransform = getTransform(
                displaybles.handles[handleIndex].parent, this.group
            );
            var direction = transformDirection(
                handleIndex === 0 ? 'right' : 'left', barTransform
            );
            var offset = this._handleWidth / 2 + LABEL_GAP;
            var textPoint = applyTransform$1(
                [
                    orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset),
                    this._size[1] / 2
                ],
                barTransform
            );
            handleLabels[handleIndex].setStyle({
                x: textPoint[0],
                y: textPoint[1],
                textVerticalAlign: orient === HORIZONTAL ? 'middle' : direction,
                textAlign: orient === HORIZONTAL ? direction : 'center',
                text: labelTexts[handleIndex]
            });
        }
    },

    /**
     * @private
     */
    _formatLabel: function (value, axis) {
        var dataZoomModel = this.dataZoomModel;
        var labelFormatter = dataZoomModel.get('labelFormatter');

        var labelPrecision = dataZoomModel.get('labelPrecision');
        if (labelPrecision == null || labelPrecision === 'auto') {
            labelPrecision = axis.getPixelPrecision();
        }

        var valueStr = (value == null || isNaN(value))
            ? ''
            // FIXME Glue code
            : (axis.type === 'category' || axis.type === 'time')
                ? axis.scale.getLabel(Math.round(value))
                // param of toFixed should less then 20.
                : value.toFixed(Math.min(labelPrecision, 20));

        return isFunction$1(labelFormatter)
            ? labelFormatter(value, valueStr)
            : isString(labelFormatter)
            ? labelFormatter.replace('{value}', valueStr)
            : valueStr;
    },

    /**
     * @private
     * @param {boolean} showOrHide true: show, false: hide
     */
    _showDataInfo: function (showOrHide) {
        // Always show when drgging.
        showOrHide = this._dragging || showOrHide;

        var handleLabels = this._displayables.handleLabels;
        handleLabels[0].attr('invisible', !showOrHide);
        handleLabels[1].attr('invisible', !showOrHide);
    },

    _onDragMove: function (handleIndex, dx, dy) {
        this._dragging = true;

        // Transform dx, dy to bar coordination.
        var barTransform = this._displayables.barGroup.getLocalTransform();
        var vertex = applyTransform$1([dx, dy], barTransform, true);

        var changed = this._updateInterval(handleIndex, vertex[0]);

        var realtime = this.dataZoomModel.get('realtime');

        this._updateView(!realtime);

        // Avoid dispatch dataZoom repeatly but range not changed,
        // which cause bad visual effect when progressive enabled.
        changed && realtime && this._dispatchZoomAction();
    },

    _onDragEnd: function () {
        this._dragging = false;
        this._showDataInfo(false);

        // While in realtime mode and stream mode, dispatch action when
        // drag end will cause the whole view rerender, which is unnecessary.
        var realtime = this.dataZoomModel.get('realtime');
        !realtime && this._dispatchZoomAction();
    },

    _onClickPanelClick: function (e) {
        var size = this._size;
        var localPoint = this._displayables.barGroup.transformCoordToLocal(e.offsetX, e.offsetY);

        if (localPoint[0] < 0 || localPoint[0] > size[0]
            || localPoint[1] < 0 || localPoint[1] > size[1]
        ) {
            return;
        }

        var handleEnds = this._handleEnds;
        var center = (handleEnds[0] + handleEnds[1]) / 2;

        var changed = this._updateInterval('all', localPoint[0] - center);
        this._updateView();
        changed && this._dispatchZoomAction();
    },

    /**
     * This action will be throttled.
     * @private
     */
    _dispatchZoomAction: function () {
        var range = this._range;

        this.api.dispatchAction({
            type: 'dataZoom',
            from: this.uid,
            dataZoomId: this.dataZoomModel.id,
            start: range[0],
            end: range[1]
        });
    },

    /**
     * @private
     */
    _findCoordRect: function () {
        // Find the grid coresponding to the first axis referred by dataZoom.
        var rect;
        each$26(this.getTargetCoordInfo(), function (coordInfoList) {
            if (!rect && coordInfoList.length) {
                var coordSys = coordInfoList[0].model.coordinateSystem;
                rect = coordSys.getRect && coordSys.getRect();
            }
        });
        if (!rect) {
            var width = this.api.getWidth();
            var height = this.api.getHeight();
            rect = {
                x: width * 0.2,
                y: height * 0.2,
                width: width * 0.6,
                height: height * 0.6
            };
        }

        return rect;
    }

});

function getOtherDim(thisDim) {
    // FIXME
    // 这个逻辑和getOtherAxis里一致，但是写在这里是否不好
    var map$$1 = {x: 'y', y: 'x', radius: 'angle', angle: 'radius'};
    return map$$1[thisDim];
}

function getCursor(orient) {
    return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

DataZoomModel.extend({

    type: 'dataZoom.inside',

    /**
     * @protected
     */
    defaultOption: {
        disabled: false,   // Whether disable this inside zoom.
        zoomLock: false,   // Whether disable zoom but only pan.
        zoomOnMouseWheel: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
        moveOnMouseMove: true,   // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
        moveOnMouseWheel: false, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
        preventDefaultMouseMove: true
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Only create one roam controller for each coordinate system.
// one roam controller might be refered by two inside data zoom
// components (for example, one for x and one for y). When user
// pan or zoom, only dispatch one action for those data zoom
// components.

var ATTR$2 = '\0_ec_dataZoom_roams';


/**
 * @public
 * @param {module:echarts/ExtensionAPI} api
 * @param {Object} dataZoomInfo
 * @param {string} dataZoomInfo.coordId
 * @param {Function} dataZoomInfo.containsPoint
 * @param {Array.<string>} dataZoomInfo.allCoordIds
 * @param {string} dataZoomInfo.dataZoomId
 * @param {Object} dataZoomInfo.getRange
 * @param {Function} dataZoomInfo.getRange.pan
 * @param {Function} dataZoomInfo.getRange.zoom
 * @param {Function} dataZoomInfo.getRange.scrollMove
 * @param {boolean} dataZoomInfo.dataZoomModel
 */
function register$2(api, dataZoomInfo) {
    var store = giveStore$1(api);
    var theDataZoomId = dataZoomInfo.dataZoomId;
    var theCoordId = dataZoomInfo.coordId;

    // Do clean when a dataZoom changes its target coordnate system.
    // Avoid memory leak, dispose all not-used-registered.
    each$1(store, function (record, coordId) {
        var dataZoomInfos = record.dataZoomInfos;
        if (dataZoomInfos[theDataZoomId]
            && indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0
        ) {
            delete dataZoomInfos[theDataZoomId];
            record.count--;
        }
    });

    cleanStore(store);

    var record = store[theCoordId];
    // Create if needed.
    if (!record) {
        record = store[theCoordId] = {
            coordId: theCoordId,
            dataZoomInfos: {},
            count: 0
        };
        record.controller = createController(api, record);
        record.dispatchAction = curry(dispatchAction$1, api);
    }

    // Update reference of dataZoom.
    !(record.dataZoomInfos[theDataZoomId]) && record.count++;
    record.dataZoomInfos[theDataZoomId] = dataZoomInfo;

    var controllerParams = mergeControllerParams(record.dataZoomInfos);
    record.controller.enable(controllerParams.controlType, controllerParams.opt);

    // Consider resize, area should be always updated.
    record.controller.setPointerChecker(dataZoomInfo.containsPoint);

    // Update throttle.
    createOrUpdate(
        record,
        'dispatchAction',
        dataZoomInfo.dataZoomModel.get('throttle', true),
        'fixRate'
    );
}

/**
 * @public
 * @param {module:echarts/ExtensionAPI} api
 * @param {string} dataZoomId
 */
function unregister$1(api, dataZoomId) {
    var store = giveStore$1(api);

    each$1(store, function (record) {
        record.controller.dispose();
        var dataZoomInfos = record.dataZoomInfos;
        if (dataZoomInfos[dataZoomId]) {
            delete dataZoomInfos[dataZoomId];
            record.count--;
        }
    });

    cleanStore(store);
}

/**
 * @public
 */
function generateCoordId(coordModel) {
    return coordModel.type + '\0_' + coordModel.id;
}

/**
 * Key: coordId, value: {dataZoomInfos: [], count, controller}
 * @type {Array.<Object>}
 */
function giveStore$1(api) {
    // Mount store on zrender instance, so that we do not
    // need to worry about dispose.
    var zr = api.getZr();
    return zr[ATTR$2] || (zr[ATTR$2] = {});
}

function createController(api, newRecord) {
    var controller = new RoamController(api.getZr());

    each$1(['pan', 'zoom', 'scrollMove'], function (eventName) {
        controller.on(eventName, function (event) {
            var batch = [];

            each$1(newRecord.dataZoomInfos, function (info) {
                // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove,
                // moveOnMouseWheel, ...) enabled.
                if (!event.isAvailableBehavior(info.dataZoomModel.option)) {
                    return;
                }

                var method = (info.getRange || {})[eventName];
                var range = method && method(newRecord.controller, event);

                !info.dataZoomModel.get('disabled', true) && range && batch.push({
                    dataZoomId: info.dataZoomId,
                    start: range[0],
                    end: range[1]
                });
            });

            batch.length && newRecord.dispatchAction(batch);
        });
    });

    return controller;
}

function cleanStore(store) {
    each$1(store, function (record, coordId) {
        if (!record.count) {
            record.controller.dispose();
            delete store[coordId];
        }
    });
}

/**
 * This action will be throttled.
 */
function dispatchAction$1(api, batch) {
    api.dispatchAction({
        type: 'dataZoom',
        batch: batch
    });
}

/**
 * Merge roamController settings when multiple dataZooms share one roamController.
 */
function mergeControllerParams(dataZoomInfos) {
    var controlType;
    // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated
    // as string, it is probably revert to reserved word by compress tool. See #7411.
    var prefix = 'type_';
    var typePriority = {
        'type_true': 2,
        'type_move': 1,
        'type_false': 0,
        'type_undefined': -1
    };
    var preventDefaultMouseMove = true;

    each$1(dataZoomInfos, function (dataZoomInfo) {
        var dataZoomModel = dataZoomInfo.dataZoomModel;
        var oneType = dataZoomModel.get('disabled', true)
            ? false
            : dataZoomModel.get('zoomLock', true)
            ? 'move'
            : true;
        if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) {
            controlType = oneType;
        }

        // Prevent default move event by default. If one false, do not prevent. Otherwise
        // users may be confused why it does not work when multiple insideZooms exist.
        preventDefaultMouseMove &= dataZoomModel.get('preventDefaultMouseMove', true);
    });

    return {
        controlType: controlType,
        opt: {
            // RoamController will enable all of these functionalities,
            // and the final behavior is determined by its event listener
            // provided by each inside zoom.
            zoomOnMouseWheel: true,
            moveOnMouseMove: true,
            moveOnMouseWheel: true,
            preventDefaultMouseMove: !!preventDefaultMouseMove
        }
    };
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var bind$6 = bind;

var InsideZoomView = DataZoomView.extend({

    type: 'dataZoom.inside',

    /**
     * @override
     */
    init: function (ecModel, api) {
        /**
         * 'throttle' is used in this.dispatchAction, so we save range
         * to avoid missing some 'pan' info.
         * @private
         * @type {Array.<number>}
         */
        this._range;
    },

    /**
     * @override
     */
    render: function (dataZoomModel, ecModel, api, payload) {
        InsideZoomView.superApply(this, 'render', arguments);

        // Hence the `throttle` util ensures to preserve command order,
        // here simply updating range all the time will not cause missing
        // any of the the roam change.
        this._range = dataZoomModel.getPercentRange();

        // Reset controllers.
        each$1(this.getTargetCoordInfo(), function (coordInfoList, coordSysName) {

            var allCoordIds = map(coordInfoList, function (coordInfo) {
                return generateCoordId(coordInfo.model);
            });

            each$1(coordInfoList, function (coordInfo) {
                var coordModel = coordInfo.model;

                var getRange = {};
                each$1(['pan', 'zoom', 'scrollMove'], function (eventName) {
                    getRange[eventName] = bind$6(roamHandlers[eventName], this, coordInfo, coordSysName);
                }, this);

                register$2(
                    api,
                    {
                        coordId: generateCoordId(coordModel),
                        allCoordIds: allCoordIds,
                        containsPoint: function (e, x, y) {
                            return coordModel.coordinateSystem.containPoint([x, y]);
                        },
                        dataZoomId: dataZoomModel.id,
                        dataZoomModel: dataZoomModel,
                        getRange: getRange
                    }
                );
            }, this);

        }, this);
    },

    /**
     * @override
     */
    dispose: function () {
        unregister$1(this.api, this.dataZoomModel.id);
        InsideZoomView.superApply(this, 'dispose', arguments);
        this._range = null;
    }

});

var roamHandlers = {

    /**
     * @this {module:echarts/component/dataZoom/InsideZoomView}
     */
    zoom: function (coordInfo, coordSysName, controller, e) {
        var lastRange = this._range;
        var range = lastRange.slice();

        // Calculate transform by the first axis.
        var axisModel = coordInfo.axisModels[0];
        if (!axisModel) {
            return;
        }

        var directionInfo = getDirectionInfo[coordSysName](
            null, [e.originX, e.originY], axisModel, controller, coordInfo
        );
        var percentPoint = (
            directionInfo.signal > 0
                ? (directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel)
                : (directionInfo.pixel - directionInfo.pixelStart)
            ) / directionInfo.pixelLength * (range[1] - range[0]) + range[0];

        var scale = Math.max(1 / e.scale, 0);
        range[0] = (range[0] - percentPoint) * scale + percentPoint;
        range[1] = (range[1] - percentPoint) * scale + percentPoint;

        // Restrict range.
        var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();

        sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan);

        this._range = range;

        if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
            return range;
        }
    },

    /**
     * @this {module:echarts/component/dataZoom/InsideZoomView}
     */
    pan: makeMover(function (range, axisModel, coordInfo, coordSysName, controller, e) {
        var directionInfo = getDirectionInfo[coordSysName](
            [e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordInfo
        );

        return directionInfo.signal
            * (range[1] - range[0])
            * directionInfo.pixel / directionInfo.pixelLength;
    }),

    /**
     * @this {module:echarts/component/dataZoom/InsideZoomView}
     */
    scrollMove: makeMover(function (range, axisModel, coordInfo, coordSysName, controller, e) {
        var directionInfo = getDirectionInfo[coordSysName](
            [0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordInfo
        );
        return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta;
    })
};

function makeMover(getPercentDelta) {
    return function (coordInfo, coordSysName, controller, e) {
        var lastRange = this._range;
        var range = lastRange.slice();

        // Calculate transform by the first axis.
        var axisModel = coordInfo.axisModels[0];
        if (!axisModel) {
            return;
        }

        var percentDelta = getPercentDelta(
            range, axisModel, coordInfo, coordSysName, controller, e
        );

        sliderMove(percentDelta, range, [0, 100], 'all');

        this._range = range;

        if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
            return range;
        }
    };
}

var getDirectionInfo = {

    grid: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
        var axis = axisModel.axis;
        var ret = {};
        var rect = coordInfo.model.coordinateSystem.getRect();
        oldPoint = oldPoint || [0, 0];

        if (axis.dim === 'x') {
            ret.pixel = newPoint[0] - oldPoint[0];
            ret.pixelLength = rect.width;
            ret.pixelStart = rect.x;
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // axis.dim === 'y'
            ret.pixel = newPoint[1] - oldPoint[1];
            ret.pixelLength = rect.height;
            ret.pixelStart = rect.y;
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    },

    polar: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
        var axis = axisModel.axis;
        var ret = {};
        var polar = coordInfo.model.coordinateSystem;
        var radiusExtent = polar.getRadiusAxis().getExtent();
        var angleExtent = polar.getAngleAxis().getExtent();

        oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0];
        newPoint = polar.pointToCoord(newPoint);

        if (axisModel.mainType === 'radiusAxis') {
            ret.pixel = newPoint[0] - oldPoint[0];
            // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]);
            // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]);
            ret.pixelLength = radiusExtent[1] - radiusExtent[0];
            ret.pixelStart = radiusExtent[0];
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // 'angleAxis'
            ret.pixel = newPoint[1] - oldPoint[1];
            // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]);
            // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]);
            ret.pixelLength = angleExtent[1] - angleExtent[0];
            ret.pixelStart = angleExtent[0];
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    },

    singleAxis: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
        var axis = axisModel.axis;
        var rect = coordInfo.model.coordinateSystem.getRect();
        var ret = {};

        oldPoint = oldPoint || [0, 0];

        if (axis.orient === 'horizontal') {
            ret.pixel = newPoint[0] - oldPoint[0];
            ret.pixelLength = rect.width;
            ret.pixelStart = rect.x;
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // 'vertical'
            ret.pixel = newPoint[1] - oldPoint[1];
            ret.pixelLength = rect.height;
            ret.pixelStart = rect.y;
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/



// Do not include './dataZoomSelect',
// since it only work for toolbox dataZoom.

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var each$27 = each$1;

var preprocessor$3 = function (option) {
    var visualMap = option && option.visualMap;

    if (!isArray(visualMap)) {
        visualMap = visualMap ? [visualMap] : [];
    }

    each$27(visualMap, function (opt) {
        if (!opt) {
            return;
        }

        // rename splitList to pieces
        if (has$2(opt, 'splitList') && !has$2(opt, 'pieces')) {
            opt.pieces = opt.splitList;
            delete opt.splitList;
        }

        var pieces = opt.pieces;
        if (pieces && isArray(pieces)) {
            each$27(pieces, function (piece) {
                if (isObject$1(piece)) {
                    if (has$2(piece, 'start') && !has$2(piece, 'min')) {
                        piece.min = piece.start;
                    }
                    if (has$2(piece, 'end') && !has$2(piece, 'max')) {
                        piece.max = piece.end;
                    }
                }
            });
        }
    });
};

function has$2(obj, name) {
    return obj && obj.hasOwnProperty && obj.hasOwnProperty(name);
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

ComponentModel.registerSubTypeDefaulter('visualMap', function (option) {
    // Compatible with ec2, when splitNumber === 0, continuous visualMap will be used.
    return (
            !option.categories
            && (
                !(
                    option.pieces
                        ? option.pieces.length > 0
                        : option.splitNumber > 0
                )
                || option.calculable
            )
        )
        ? 'continuous' : 'piecewise';
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var VISUAL_PRIORITY = PRIORITY.VISUAL.COMPONENT;

registerVisual(VISUAL_PRIORITY, {
    createOnAllSeries: true,
    reset: function (seriesModel, ecModel) {
        var resetDefines = [];
        ecModel.eachComponent('visualMap', function (visualMapModel) {
            var pipelineContext = seriesModel.pipelineContext;
            if (!visualMapModel.isTargetSeries(seriesModel)
                || (pipelineContext && pipelineContext.large)
            ) {
                return;
            }

            resetDefines.push(incrementalApplyVisual(
                visualMapModel.stateList,
                visualMapModel.targetVisuals,
                bind(visualMapModel.getValueState, visualMapModel),
                visualMapModel.getDataDimension(seriesModel.getData())
            ));
        });

        return resetDefines;
    }
});

// Only support color.
registerVisual(VISUAL_PRIORITY, {
    createOnAllSeries: true,
    reset: function (seriesModel, ecModel) {
        var data = seriesModel.getData();
        var visualMetaList = [];

        ecModel.eachComponent('visualMap', function (visualMapModel) {
            if (visualMapModel.isTargetSeries(seriesModel)) {
                var visualMeta = visualMapModel.getVisualMeta(
                    bind(getColorVisual, null, seriesModel, visualMapModel)
                ) || {stops: [], outerColors: []};

                var concreteDim = visualMapModel.getDataDimension(data);
                var dimInfo = data.getDimensionInfo(concreteDim);
                if (dimInfo != null) {
                    // visualMeta.dimension should be dimension index, but not concrete dimension.
                    visualMeta.dimension = dimInfo.index;
                    visualMetaList.push(visualMeta);
                }
            }
        });

        // console.log(JSON.stringify(visualMetaList.map(a => a.stops)));
        seriesModel.getData().setVisual('visualMeta', visualMetaList);
    }
});

// FIXME
// performance and export for heatmap?
// value can be Infinity or -Infinity
function getColorVisual(seriesModel, visualMapModel, value, valueState) {
    var mappings = visualMapModel.targetVisuals[valueState];
    var visualTypes = VisualMapping.prepareVisualTypes(mappings);
    var resultVisual = {
        color: seriesModel.getData().getVisual('color') // default color.
    };

    for (var i = 0, len = visualTypes.length; i < len; i++) {
        var type = visualTypes[i];
        var mapping = mappings[
            type === 'opacity' ? '__alphaForOpacity' : type
        ];
        mapping && mapping.applyVisual(value, getVisual, setVisual);
    }

    return resultVisual.color;

    function getVisual(key) {
        return resultVisual[key];
    }

    function setVisual(key, value) {
        resultVisual[key] = value;
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @file Visual mapping.
 */

var visualDefault = {

    /**
     * @public
     */
    get: function (visualType, key, isCategory) {
        var value = clone(
            (defaultOption$3[visualType] || {})[key]
        );

        return isCategory
            ? (isArray(value) ? value[value.length - 1] : value)
            : value;
    }

};

var defaultOption$3 = {

    color: {
        active: ['#006edd', '#e0ffff'],
        inactive: ['rgba(0,0,0,0)']
    },

    colorHue: {
        active: [0, 360],
        inactive: [0, 0]
    },

    colorSaturation: {
        active: [0.3, 1],
        inactive: [0, 0]
    },

    colorLightness: {
        active: [0.9, 0.5],
        inactive: [0, 0]
    },

    colorAlpha: {
        active: [0.3, 1],
        inactive: [0, 0]
    },

    opacity: {
        active: [0.3, 1],
        inactive: [0, 0]
    },

    symbol: {
        active: ['circle', 'roundRect', 'diamond'],
        inactive: ['none']
    },

    symbolSize: {
        active: [10, 50],
        inactive: [0, 0]
    }
};

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var mapVisual$2 = VisualMapping.mapVisual;
var eachVisual = VisualMapping.eachVisual;
var isArray$3 = isArray;
var each$28 = each$1;
var asc$3 = asc;
var linearMap$2 = linearMap;
var noop$2 = noop;

var VisualMapModel = extendComponentModel({

    type: 'visualMap',

    dependencies: ['series'],

    /**
     * @readOnly
     * @type {Array.<string>}
     */
    stateList: ['inRange', 'outOfRange'],

    /**
     * @readOnly
     * @type {Array.<string>}
     */
    replacableOptionKeys: [
        'inRange', 'outOfRange', 'target', 'controller', 'color'
    ],

    /**
     * [lowerBound, upperBound]
     *
     * @readOnly
     * @type {Array.<number>}
     */
    dataBound: [-Infinity, Infinity],

    /**
     * @readOnly
     * @type {string|Object}
     */
    layoutMode: {type: 'box', ignoreSize: true},

    /**
     * @protected
     */
    defaultOption: {
        show: true,

        zlevel: 0,
        z: 4,

        seriesIndex: 'all',     // 'all' or null/undefined: all series.
                                // A number or an array of number: the specified series.

                                // set min: 0, max: 200, only for campatible with ec2.
                                // In fact min max should not have default value.
        min: 0,                 // min value, must specified if pieces is not specified.
        max: 200,               // max value, must specified if pieces is not specified.

        dimension: null,
        inRange: null,          // 'color', 'colorHue', 'colorSaturation', 'colorLightness', 'colorAlpha',
                                // 'symbol', 'symbolSize'
        outOfRange: null,       // 'color', 'colorHue', 'colorSaturation',
                                // 'colorLightness', 'colorAlpha',
                                // 'symbol', 'symbolSize'

        left: 0,                // 'center' ¦ 'left' ¦ 'right' ¦ {number} (px)
        right: null,            // The same as left.
        top: null,              // 'top' ¦ 'bottom' ¦ 'center' ¦ {number} (px)
        bottom: 0,              // The same as top.

        itemWidth: null,
        itemHeight: null,
        inverse: false,
        orient: 'vertical',        // 'horizontal' ¦ 'vertical'

        backgroundColor: 'rgba(0,0,0,0)',
        borderColor: '#ccc',       // 值域边框颜色
        contentColor: '#5793f3',
        inactiveColor: '#aaa',
        borderWidth: 0,            // 值域边框线宽，单位px，默认为0（无边框）
        padding: 5,                // 值域内边距，单位px，默认各方向内边距为5，
                                    // 接受数组分别设定上右下左边距，同css
        textGap: 10,               //
        precision: 0,              // 小数精度，默认为0，无小数点
        color: null,               //颜色（deprecated，兼容ec2，顺序同pieces，不同于inRange/outOfRange）

        formatter: null,
        text: null,                // 文本，如['高', '低']，兼容ec2，text[0]对应高值，text[1]对应低值
        textStyle: {
            color: '#333'          // 值域文字颜色
        }
    },

    /**
     * @protected
     */
    init: function (option, parentModel, ecModel) {

        /**
         * @private
         * @type {Array.<number>}
         */
        this._dataExtent;

        /**
         * @readOnly
         */
        this.targetVisuals = {};

        /**
         * @readOnly
         */
        this.controllerVisuals = {};

        /**
         * @readOnly
         */
        this.textStyleModel;

        /**
         * [width, height]
         * @readOnly
         * @type {Array.<number>}
         */
        this.itemSize;

        this.mergeDefaultAndTheme(option, ecModel);
    },

    /**
     * @protected
     */
    optionUpdated: function (newOption, isInit) {
        var thisOption = this.option;

        // FIXME
        // necessary?
        // Disable realtime view update if canvas is not supported.
        if (!env$1.canvasSupported) {
            thisOption.realtime = false;
        }

        !isInit && replaceVisualOption(
            thisOption, newOption, this.replacableOptionKeys
        );

        this.textStyleModel = this.getModel('textStyle');

        this.resetItemSize();

        this.completeVisualOption();
    },

    /**
     * @protected
     */
    resetVisual: function (supplementVisualOption) {
        var stateList = this.stateList;
        supplementVisualOption = bind(supplementVisualOption, this);

        this.controllerVisuals = createVisualMappings(
            this.option.controller, stateList, supplementVisualOption
        );
        this.targetVisuals = createVisualMappings(
            this.option.target, stateList, supplementVisualOption
        );
    },

    /**
     * @protected
     * @return {Array.<number>} An array of series indices.
     */
    getTargetSeriesIndices: function () {
        var optionSeriesIndex = this.option.seriesIndex;
        var seriesIndices = [];

        if (optionSeriesIndex == null || optionSeriesIndex === 'all') {
            this.ecModel.eachSeries(function (seriesModel, index) {
                seriesIndices.push(index);
            });
        }
        else {
            seriesIndices = normalizeToArray(optionSeriesIndex);
        }

        return seriesIndices;
    },

    /**
     * @public
     */
    eachTargetSeries: function (callback, context) {
        each$1(this.getTargetSeriesIndices(), function (seriesIndex) {
            callback.call(context, this.ecModel.getSeriesByIndex(seriesIndex));
        }, this);
    },

    /**
     * @pubilc
     */
    isTargetSeries: function (seriesModel) {
        var is = false;
        this.eachTargetSeries(function (model) {
            model === seriesModel && (is = true);
        });
        return is;
    },

    /**
     * @example
     * this.formatValueText(someVal); // format single numeric value to text.
     * this.formatValueText(someVal, true); // format single category value to text.
     * this.formatValueText([min, max]); // format numeric min-max to text.
     * this.formatValueText([this.dataBound[0], max]); // using data lower bound.
     * this.formatValueText([min, this.dataBound[1]]); // using data upper bound.
     *
     * @param {number|Array.<number>} value Real value, or this.dataBound[0 or 1].
     * @param {boolean} [isCategory=false] Only available when value is number.
     * @param {Array.<string>} edgeSymbols Open-close symbol when value is interval.
     * @return {string}
     * @protected
     */
    formatValueText: function (value, isCategory, edgeSymbols) {
        var option = this.option;
        var precision = option.precision;
        var dataBound = this.dataBound;
        var formatter = option.formatter;
        var isMinMax;
        var textValue;
        edgeSymbols = edgeSymbols || ['<', '>'];

        if (isArray(value)) {
            value = value.slice();
            isMinMax = true;
        }

        textValue = isCategory
            ? value
            : (isMinMax
                ? [toFixed(value[0]), toFixed(value[1])]
                : toFixed(value)
            );

        if (isString(formatter)) {
            return formatter
                .replace('{value}', isMinMax ? textValue[0] : textValue)
                .replace('{value2}', isMinMax ? textValue[1] : textValue);
        }
        else if (isFunction$1(formatter)) {
            return isMinMax
                ? formatter(value[0], value[1])
                : formatter(value);
        }

        if (isMinMax) {
            if (value[0] === dataBound[0]) {
                return edgeSymbols[0] + ' ' + textValue[1];
            }
            else if (value[1] === dataBound[1]) {
                return edgeSymbols[1] + ' ' + textValue[0];
            }
            else {
                return textValue[0] + ' - ' + textValue[1];
            }
        }
        else { // Format single value (includes category case).
            return textValue;
        }

        function toFixed(val) {
            return val === dataBound[0]
                ? 'min'
                : val === dataBound[1]
                ? 'max'
                : (+val).toFixed(Math.min(precision, 20));
        }
    },

    /**
     * @protected
     */
    resetExtent: function () {
        var thisOption = this.option;

        // Can not calculate data extent by data here.
        // Because series and data may be modified in processing stage.
        // So we do not support the feature "auto min/max".

        var extent = asc$3([thisOption.min, thisOption.max]);

        this._dataExtent = extent;
    },

    /**
     * @public
     * @param {module:echarts/data/List} list
     * @return {string} Concrete dimention. If return null/undefined,
     *                  no dimension used.
     */
    getDataDimension: function (list) {
        var optDim = this.option.dimension;
        var listDimensions = list.dimensions;
        if (optDim == null && !listDimensions.length) {
            return;
        }

        if (optDim != null) {
            return list.getDimension(optDim);
        }

        var dimNames = list.dimensions;
        for (var i = dimNames.length - 1; i >= 0; i--) {
            var dimName = dimNames[i];
            var dimInfo = list.getDimensionInfo(dimName);
            if (!dimInfo.isCalculationCoord) {
                return dimName;
            }
        }
    },

    /**
     * @public
     * @override
     */
    getExtent: function () {
        return this._dataExtent.slice();
    },

    /**
     * @protected
     */
    completeVisualOption: function () {
        var ecModel = this.ecModel;
        var thisOption = this.option;
        var base = {inRange: thisOption.inRange, outOfRange: thisOption.outOfRange};

        var target = thisOption.target || (thisOption.target = {});
        var controller = thisOption.controller || (thisOption.controller = {});

        merge(target, base); // Do not override
        merge(controller, base); // Do not override

        var isCategory = this.isCategory();

        completeSingle.call(this, target);
        completeSingle.call(this, controller);
        completeInactive.call(this, target, 'inRange', 'outOfRange');
        // completeInactive.call(this, target, 'outOfRange', 'inRange');
        completeController.call(this, controller);

        function completeSingle(base) {
            // Compatible with ec2 dataRange.color.
            // The mapping order of dataRange.color is: [high value, ..., low value]
            // whereas inRange.color and outOfRange.color is [low value, ..., high value]
            // Notice: ec2 has no inverse.
            if (isArray$3(thisOption.color)
                // If there has been inRange: {symbol: ...}, adding color is a mistake.
                // So adding color only when no inRange defined.
                && !base.inRange
            ) {
                base.inRange = {color: thisOption.color.slice().reverse()};
            }

            // Compatible with previous logic, always give a defautl color, otherwise
            // simple config with no inRange and outOfRange will not work.
            // Originally we use visualMap.color as the default color, but setOption at
            // the second time the default color will be erased. So we change to use
            // constant DEFAULT_COLOR.
            // If user do not want the defualt color, set inRange: {color: null}.
            base.inRange = base.inRange || {color: ecModel.get('gradientColor')};

            // If using shortcut like: {inRange: 'symbol'}, complete default value.
            each$28(this.stateList, function (state) {
                var visualType = base[state];

                if (isString(visualType)) {
                    var defa = visualDefault.get(visualType, 'active', isCategory);
                    if (defa) {
                        base[state] = {};
                        base[state][visualType] = defa;
                    }
                    else {
                        // Mark as not specified.
                        delete base[state];
                    }
                }
            }, this);
        }

        function completeInactive(base, stateExist, stateAbsent) {
            var optExist = base[stateExist];
            var optAbsent = base[stateAbsent];

            if (optExist && !optAbsent) {
                optAbsent = base[stateAbsent] = {};
                each$28(optExist, function (visualData, visualType) {
                    if (!VisualMapping.isValidType(visualType)) {
                        return;
                    }

                    var defa = visualDefault.get(visualType, 'inactive', isCategory);

                    if (defa != null) {
                        optAbsent[visualType] = defa;

                        // Compatibable with ec2:
                        // Only inactive color to rgba(0,0,0,0) can not
                        // make label transparent, so use opacity also.
                        if (visualType === 'color'
                            && !optAbsent.hasOwnProperty('opacity')
                            && !optAbsent.hasOwnProperty('colorAlpha')
                        ) {
                            optAbsent.opacity = [0, 0];
                        }
                    }
                });
            }
        }

        function completeController(controller) {
            var symbolExists = (controller.inRange || {}).symbol
                || (controller.outOfRange || {}).symbol;
            var symbolSizeExists = (controller.inRange || {}).symbolSize
                || (controller.outOfRange || {}).symbolSize;
            var inactiveColor = this.get('inactiveColor');

            each$28(this.stateList, function (state) {

                var itemSize = this.itemSize;
                var visuals = controller[state];

                // Set inactive color for controller if no other color
                // attr (like colorAlpha) specified.
                if (!visuals) {
                    visuals = controller[state] = {
                        color: isCategory ? inactiveColor : [inactiveColor]
                    };
                }

                // Consistent symbol and symbolSize if not specified.
                if (visuals.symbol == null) {
                    visuals.symbol = symbolExists
                        && clone(symbolExists)
                        || (isCategory ? 'roundRect' : ['roundRect']);
                }
                if (visuals.symbolSize == null) {
                    visuals.symbolSize = symbolSizeExists
                        && clone(symbolSizeExists)
                        || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
                }

                // Filter square and none.
                visuals.symbol = mapVisual$2(visuals.symbol, function (symbol) {
                    return (symbol === 'none' || symbol === 'square') ? 'roundRect' : symbol;
                });

                // Normalize symbolSize
                var symbolSize = visuals.symbolSize;

                if (symbolSize != null) {
                    var max = -Infinity;
                    // symbolSize can be object when categories defined.
                    eachVisual(symbolSize, function (value) {
                        value > max && (max = value);
                    });
                    visuals.symbolSize = mapVisual$2(symbolSize, function (value) {
                        return linearMap$2(value, [0, max], [0, itemSize[0]], true);
                    });
                }

            }, this);
        }
    },

    /**
     * @protected
     */
    resetItemSize: function () {
        this.itemSize = [
            parseFloat(this.get('itemWidth')),
            parseFloat(this.get('itemHeight'))
        ];
    },

    /**
     * @public
     */
    isCategory: function () {
        return !!this.option.categories;
    },

    /**
     * @public
     * @abstract
     */
    setSelected: noop$2,

    /**
     * @public
     * @abstract
     * @param {*|module:echarts/data/List} valueOrData
     * @param {number} dataIndex
     * @return {string} state See this.stateList
     */
    getValueState: noop$2,

    /**
     * FIXME
     * Do not publish to thirt-part-dev temporarily
     * util the interface is stable. (Should it return
     * a function but not visual meta?)
     *
     * @pubilc
     * @abstract
     * @param {Function} getColorVisual
     *        params: value, valueState
     *        return: color
     * @return {Object} visualMeta
     *        should includes {stops, outerColors}
     *        outerColor means [colorBeyondMinValue, colorBeyondMaxValue]
     */
    getVisualMeta: noop$2

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Constant
var DEFAULT_BAR_BOUND = [20, 140];

var ContinuousModel = VisualMapModel.extend({

    type: 'visualMap.continuous',

    /**
     * @protected
     */
    defaultOption: {
        align: 'auto',           // 'auto', 'left', 'right', 'top', 'bottom'
        calculable: false,       // This prop effect default component type determine,
                                 // See echarts/component/visualMap/typeDefaulter.
        range: null,             // selected range. In default case `range` is [min, max]
                                 // and can auto change along with modification of min max,
                                 // util use specifid a range.
        realtime: true,          // Whether realtime update.
        itemHeight: null,        // The length of the range control edge.
        itemWidth: null,         // The length of the other side.
        hoverLink: true,         // Enable hover highlight.
        hoverLinkDataSize: null, // The size of hovered data.
        hoverLinkOnHandle: null  // Whether trigger hoverLink when hover handle.
                                 // If not specified, follow the value of `realtime`.
    },

    /**
     * @override
     */
    optionUpdated: function (newOption, isInit) {
        ContinuousModel.superApply(this, 'optionUpdated', arguments);

        this.resetExtent();

        this.resetVisual(function (mappingOption) {
            mappingOption.mappingMethod = 'linear';
            mappingOption.dataExtent = this.getExtent();
        });

        this._resetRange();
    },

    /**
     * @protected
     * @override
     */
    resetItemSize: function () {
        ContinuousModel.superApply(this, 'resetItemSize', arguments);

        var itemSize = this.itemSize;

        this._orient === 'horizontal' && itemSize.reverse();

        (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]);
        (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]);
    },

    /**
     * @private
     */
    _resetRange: function () {
        var dataExtent = this.getExtent();
        var range = this.option.range;

        if (!range || range.auto) {
            // `range` should always be array (so we dont use other
            // value like 'auto') for user-friend. (consider getOption).
            dataExtent.auto = 1;
            this.option.range = dataExtent;
        }
        else if (isArray(range)) {
            if (range[0] > range[1]) {
                range.reverse();
            }
            range[0] = Math.max(range[0], dataExtent[0]);
            range[1] = Math.min(range[1], dataExtent[1]);
        }
    },

    /**
     * @protected
     * @override
     */
    completeVisualOption: function () {
        VisualMapModel.prototype.completeVisualOption.apply(this, arguments);

        each$1(this.stateList, function (state) {
            var symbolSize = this.option.controller[state].symbolSize;
            if (symbolSize && symbolSize[0] !== symbolSize[1]) {
                symbolSize[0] = 0; // For good looking.
            }
        }, this);
    },

    /**
     * @override
     */
    setSelected: function (selected) {
        this.option.range = selected.slice();
        this._resetRange();
    },

    /**
     * @public
     */
    getSelected: function () {
        var dataExtent = this.getExtent();

        var dataInterval = asc(
            (this.get('range') || []).slice()
        );

        // Clamp
        dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]);
        dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]);
        dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]);
        dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]);

        return dataInterval;
    },

    /**
     * @override
     */
    getValueState: function (value) {
        var range = this.option.range;
        var dataExtent = this.getExtent();

        // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'.
        // range[1] is processed likewise.
        return (
            (range[0] <= dataExtent[0] || range[0] <= value)
            && (range[1] >= dataExtent[1] || value <= range[1])
        ) ? 'inRange' : 'outOfRange';
    },

    /**
     * @params {Array.<number>} range target value: range[0] <= value && value <= range[1]
     * @return {Array.<Object>} [{seriesId, dataIndices: <Array.<number>>}, ...]
     */
    findTargetDataIndices: function (range) {
        var result = [];

        this.eachTargetSeries(function (seriesModel) {
            var dataIndices = [];
            var data = seriesModel.getData();

            data.each(this.getDataDimension(data), function (value, dataIndex) {
                range[0] <= value && value <= range[1] && dataIndices.push(dataIndex);
            }, this);

            result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
        }, this);

        return result;
    },

    /**
     * @implement
     */
    getVisualMeta: function (getColorVisual) {
        var oVals = getColorStopValues(this, 'outOfRange', this.getExtent());
        var iVals = getColorStopValues(this, 'inRange', this.option.range.slice());
        var stops = [];

        function setStop(value, valueState) {
            stops.push({
                value: value,
                color: getColorVisual(value, valueState)
            });
        }

        // Format to: outOfRange -- inRange -- outOfRange.
        var iIdx = 0;
        var oIdx = 0;
        var iLen = iVals.length;
        var oLen = oVals.length;

        for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) {
            // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored.
            if (oVals[oIdx] < iVals[iIdx]) {
                setStop(oVals[oIdx], 'outOfRange');
            }
        }
        for (var first = 1; iIdx < iLen; iIdx++, first = 0) {
            // If range is full, value beyond min, max will be clamped.
            // make a singularity
            first && stops.length && setStop(iVals[iIdx], 'outOfRange');
            setStop(iVals[iIdx], 'inRange');
        }
        for (var first = 1; oIdx < oLen; oIdx++) {
            if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) {
                // make a singularity
                if (first) {
                    stops.length && setStop(stops[stops.length - 1].value, 'outOfRange');
                    first = 0;
                }
                setStop(oVals[oIdx], 'outOfRange');
            }
        }

        var stopsLen = stops.length;

        return {
            stops: stops,
            outerColors: [
                stopsLen ? stops[0].color : 'transparent',
                stopsLen ? stops[stopsLen - 1].color : 'transparent'
            ]
        };
    }

});

function getColorStopValues(visualMapModel, valueState, dataExtent) {
    if (dataExtent[0] === dataExtent[1]) {
        return dataExtent.slice();
    }

    // When using colorHue mapping, it is not linear color any more.
    // Moreover, canvas gradient seems not to be accurate linear.
    // FIXME
    // Should be arbitrary value 100? or based on pixel size?
    var count = 200;
    var step = (dataExtent[1] - dataExtent[0]) / count;

    var value = dataExtent[0];
    var stopValues = [];
    for (var i = 0; i <= count && value < dataExtent[1]; i++) {
        stopValues.push(value);
        value += step;
    }
    stopValues.push(dataExtent[1]);

    return stopValues;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var VisualMapView = extendComponentView({

    type: 'visualMap',

    /**
     * @readOnly
     * @type {Object}
     */
    autoPositionValues: {left: 1, right: 1, top: 1, bottom: 1},

    init: function (ecModel, api) {
        /**
         * @readOnly
         * @type {module:echarts/model/Global}
         */
        this.ecModel = ecModel;

        /**
         * @readOnly
         * @type {module:echarts/ExtensionAPI}
         */
        this.api = api;

        /**
         * @readOnly
         * @type {module:echarts/component/visualMap/visualMapModel}
         */
        this.visualMapModel;
    },

    /**
     * @protected
     */
    render: function (visualMapModel, ecModel, api, payload) {
        this.visualMapModel = visualMapModel;

        if (visualMapModel.get('show') === false) {
            this.group.removeAll();
            return;
        }

        this.doRender.apply(this, arguments);
    },

    /**
     * @protected
     */
    renderBackground: function (group) {
        var visualMapModel = this.visualMapModel;
        var padding = normalizeCssArray$1(visualMapModel.get('padding') || 0);
        var rect = group.getBoundingRect();

        group.add(new Rect({
            z2: -1, // Lay background rect on the lowest layer.
            silent: true,
            shape: {
                x: rect.x - padding[3],
                y: rect.y - padding[0],
                width: rect.width + padding[3] + padding[1],
                height: rect.height + padding[0] + padding[2]
            },
            style: {
                fill: visualMapModel.get('backgroundColor'),
                stroke: visualMapModel.get('borderColor'),
                lineWidth: visualMapModel.get('borderWidth')
            }
        }));
    },

    /**
     * @protected
     * @param {number} targetValue can be Infinity or -Infinity
     * @param {string=} visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize'
     * @param {Object} [opts]
     * @param {string=} [opts.forceState] Specify state, instead of using getValueState method.
     * @param {string=} [opts.convertOpacityToAlpha=false] For color gradient in controller widget.
     * @return {*} Visual value.
     */
    getControllerVisual: function (targetValue, visualCluster, opts) {
        opts = opts || {};

        var forceState = opts.forceState;
        var visualMapModel = this.visualMapModel;
        var visualObj = {};

        // Default values.
        if (visualCluster === 'symbol') {
            visualObj.symbol = visualMapModel.get('itemSymbol');
        }
        if (visualCluster === 'color') {
            var defaultColor = visualMapModel.get('contentColor');
            visualObj.color = defaultColor;
        }

        function getter(key) {
            return visualObj[key];
        }

        function setter(key, value) {
            visualObj[key] = value;
        }

        var mappings = visualMapModel.controllerVisuals[
            forceState || visualMapModel.getValueState(targetValue)
        ];
        var visualTypes = VisualMapping.prepareVisualTypes(mappings);

        each$1(visualTypes, function (type) {
            var visualMapping = mappings[type];
            if (opts.convertOpacityToAlpha && type === 'opacity') {
                type = 'colorAlpha';
                visualMapping = mappings.__alphaForOpacity;
            }
            if (VisualMapping.dependsOn(type, visualCluster)) {
                visualMapping && visualMapping.applyVisual(
                    targetValue, getter, setter
                );
            }
        });

        return visualObj[visualCluster];
    },

    /**
     * @protected
     */
    positionGroup: function (group) {
        var model = this.visualMapModel;
        var api = this.api;

        positionElement(
            group,
            model.getBoxLayoutParams(),
            {width: api.getWidth(), height: api.getHeight()}
        );
    },

    /**
     * @protected
     * @abstract
     */
    doRender: noop

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * @param {module:echarts/component/visualMap/VisualMapModel} visualMapModel\
 * @param {module:echarts/ExtensionAPI} api
 * @param {Array.<number>} itemSize always [short, long]
 * @return {string} 'left' or 'right' or 'top' or 'bottom'
 */
function getItemAlign(visualMapModel, api, itemSize) {
    var modelOption = visualMapModel.option;
    var itemAlign = modelOption.align;

    if (itemAlign != null && itemAlign !== 'auto') {
        return itemAlign;
    }

    // Auto decision align.
    var ecSize = {width: api.getWidth(), height: api.getHeight()};
    var realIndex = modelOption.orient === 'horizontal' ? 1 : 0;

    var paramsSet = [
        ['left', 'right', 'width'],
        ['top', 'bottom', 'height']
    ];
    var reals = paramsSet[realIndex];
    var fakeValue = [0, null, 10];

    var layoutInput = {};
    for (var i = 0; i < 3; i++) {
        layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i];
        layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]];
    }

    var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex];
    var rect = getLayoutRect(layoutInput, ecSize, modelOption.padding);

    return reals[
        (rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5
            < ecSize[rParam[1]] * 0.5 ? 0 : 1
    ];
}

/**
 * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and
 * dataIndexInside means filtered index.
 */
function makeHighDownBatch(batch, visualMapModel) {
    each$1(batch || [], function (batchItem) {
        if (batchItem.dataIndex != null) {
            batchItem.dataIndexInside = batchItem.dataIndex;
            batchItem.dataIndex = null;
        }
        batchItem.highlightKey = 'visualMap' + (visualMapModel ? visualMapModel.componentIndex : '');
    });
    return batch;
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var linearMap$3 = linearMap;
var each$29 = each$1;
var mathMin$8 = Math.min;
var mathMax$8 = Math.max;

// Arbitrary value
var HOVER_LINK_SIZE = 12;
var HOVER_LINK_OUT = 6;

// Notice:
// Any "interval" should be by the order of [low, high].
// "handle0" (handleIndex === 0) maps to
// low data value: this._dataInterval[0] and has low coord.
// "handle1" (handleIndex === 1) maps to
// high data value: this._dataInterval[1] and has high coord.
// The logic of transform is implemented in this._createBarGroup.

var ContinuousView = VisualMapView.extend({

    type: 'visualMap.continuous',

    /**
     * @override
     */
    init: function () {

        ContinuousView.superApply(this, 'init', arguments);

        /**
         * @private
         */
        this._shapes = {};

        /**
         * @private
         */
        this._dataInterval = [];

        /**
         * @private
         */
        this._handleEnds = [];

        /**
         * @private
         */
        this._orient;

        /**
         * @private
         */
        this._useHandle;

        /**
         * @private
         */
        this._hoverLinkDataIndices = [];

        /**
         * @private
         */
        this._dragging;

        /**
         * @private
         */
        this._hovering;
    },

    /**
     * @protected
     * @override
     */
    doRender: function (visualMapModel, ecModel, api, payload) {
        if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
            this._buildView();
        }
    },

    /**
     * @private
     */
    _buildView: function () {
        this.group.removeAll();

        var visualMapModel = this.visualMapModel;
        var thisGroup = this.group;

        this._orient = visualMapModel.get('orient');
        this._useHandle = visualMapModel.get('calculable');

        this._resetInterval();

        this._renderBar(thisGroup);

        var dataRangeText = visualMapModel.get('text');
        this._renderEndsText(thisGroup, dataRangeText, 0);
        this._renderEndsText(thisGroup, dataRangeText, 1);

        // Do this for background size calculation.
        this._updateView(true);

        // After updating view, inner shapes is built completely,
        // and then background can be rendered.
        this.renderBackground(thisGroup);

        // Real update view
        this._updateView();

        this._enableHoverLinkToSeries();
        this._enableHoverLinkFromSeries();

        this.positionGroup(thisGroup);
    },

    /**
     * @private
     */
    _renderEndsText: function (group, dataRangeText, endsIndex) {
        if (!dataRangeText) {
            return;
        }

        // Compatible with ec2, text[0] map to high value, text[1] map low value.
        var text = dataRangeText[1 - endsIndex];
        text = text != null ? text + '' : '';

        var visualMapModel = this.visualMapModel;
        var textGap = visualMapModel.get('textGap');
        var itemSize = visualMapModel.itemSize;

        var barGroup = this._shapes.barGroup;
        var position = this._applyTransform(
            [
                itemSize[0] / 2,
                endsIndex === 0 ? -textGap : itemSize[1] + textGap
            ],
            barGroup
        );
        var align = this._applyTransform(
            endsIndex === 0 ? 'bottom' : 'top',
            barGroup
        );
        var orient = this._orient;
        var textStyleModel = this.visualMapModel.textStyleModel;

        this.group.add(new Text({
            style: {
                x: position[0],
                y: position[1],
                textVerticalAlign: orient === 'horizontal' ? 'middle' : align,
                textAlign: orient === 'horizontal' ? align : 'center',
                text: text,
                textFont: textStyleModel.getFont(),
                textFill: textStyleModel.getTextColor()
            }
        }));
    },

    /**
     * @private
     */
    _renderBar: function (targetGroup) {
        var visualMapModel = this.visualMapModel;
        var shapes = this._shapes;
        var itemSize = visualMapModel.itemSize;
        var orient = this._orient;
        var useHandle = this._useHandle;
        var itemAlign = getItemAlign(visualMapModel, this.api, itemSize);
        var barGroup = shapes.barGroup = this._createBarGroup(itemAlign);

        // Bar
        barGroup.add(shapes.outOfRange = createPolygon());
        barGroup.add(shapes.inRange = createPolygon(
            null,
            useHandle ? getCursor$1(this._orient) : null,
            bind(this._dragHandle, this, 'all', false),
            bind(this._dragHandle, this, 'all', true)
        ));

        var textRect = visualMapModel.textStyleModel.getTextRect('国');
        var textSize = mathMax$8(textRect.width, textRect.height);

        // Handle
        if (useHandle) {
            shapes.handleThumbs = [];
            shapes.handleLabels = [];
            shapes.handleLabelPoints = [];

            this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign);
            this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign);
        }

        this._createIndicator(barGroup, itemSize, textSize, orient);

        targetGroup.add(barGroup);
    },

    /**
     * @private
     */
    _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) {
        var onDrift = bind(this._dragHandle, this, handleIndex, false);
        var onDragEnd = bind(this._dragHandle, this, handleIndex, true);
        var handleThumb = createPolygon(
            createHandlePoints(handleIndex, textSize),
            getCursor$1(this._orient),
            onDrift,
            onDragEnd
        );
        handleThumb.position[0] = itemSize[0];
        barGroup.add(handleThumb);

        // Text is always horizontal layout but should not be effected by
        // transform (orient/inverse). So label is built separately but not
        // use zrender/graphic/helper/RectText, and is located based on view
        // group (according to handleLabelPoint) but not barGroup.
        var textStyleModel = this.visualMapModel.textStyleModel;
        var handleLabel = new Text({
            draggable: true,
            drift: onDrift,
            onmousemove: function (e) {
                // Fot mobile devicem, prevent screen slider on the button.
                stop(e.event);
            },
            ondragend: onDragEnd,
            style: {
                x: 0, y: 0, text: '',
                textFont: textStyleModel.getFont(),
                textFill: textStyleModel.getTextColor()
            }
        });
        this.group.add(handleLabel);

        var handleLabelPoint = [
            orient === 'horizontal'
                ? textSize / 2
                : textSize * 1.5,
            orient === 'horizontal'
                ? (handleIndex === 0 ? -(textSize * 1.5) : (textSize * 1.5))
                : (handleIndex === 0 ? -textSize / 2 : textSize / 2)
        ];

        var shapes = this._shapes;
        shapes.handleThumbs[handleIndex] = handleThumb;
        shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
        shapes.handleLabels[handleIndex] = handleLabel;
    },

    /**
     * @private
     */
    _createIndicator: function (barGroup, itemSize, textSize, orient) {
        var indicator = createPolygon([[0, 0]], 'move');
        indicator.position[0] = itemSize[0];
        indicator.attr({invisible: true, silent: true});
        barGroup.add(indicator);

        var textStyleModel = this.visualMapModel.textStyleModel;
        var indicatorLabel = new Text({
            silent: true,
            invisible: true,
            style: {
                x: 0, y: 0, text: '',
                textFont: textStyleModel.getFont(),
                textFill: textStyleModel.getTextColor()
            }
        });
        this.group.add(indicatorLabel);

        var indicatorLabelPoint = [
            orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3,
            0
        ];

        var shapes = this._shapes;
        shapes.indicator = indicator;
        shapes.indicatorLabel = indicatorLabel;
        shapes.indicatorLabelPoint = indicatorLabelPoint;
    },

    /**
     * @private
     */
    _dragHandle: function (handleIndex, isEnd, dx, dy) {
        if (!this._useHandle) {
            return;
        }

        this._dragging = !isEnd;

        if (!isEnd) {
            // Transform dx, dy to bar coordination.
            var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true);
            this._updateInterval(handleIndex, vertex[1]);

            // Considering realtime, update view should be executed
            // before dispatch action.
            this._updateView();
        }

        // dragEnd do not dispatch action when realtime.
        if (isEnd === !this.visualMapModel.get('realtime')) { // jshint ignore:line
            this.api.dispatchAction({
                type: 'selectDataRange',
                from: this.uid,
                visualMapId: this.visualMapModel.id,
                selected: this._dataInterval.slice()
            });
        }

        if (isEnd) {
            !this._hovering && this._clearHoverLinkToSeries();
        }
        else if (useHoverLinkOnHandle(this.visualMapModel)) {
            this._doHoverLinkToSeries(this._handleEnds[handleIndex], false);
        }
    },

    /**
     * @private
     */
    _resetInterval: function () {
        var visualMapModel = this.visualMapModel;

        var dataInterval = this._dataInterval = visualMapModel.getSelected();
        var dataExtent = visualMapModel.getExtent();
        var sizeExtent = [0, visualMapModel.itemSize[1]];

        this._handleEnds = [
            linearMap$3(dataInterval[0], dataExtent, sizeExtent, true),
            linearMap$3(dataInterval[1], dataExtent, sizeExtent, true)
        ];
    },

    /**
     * @private
     * @param {(number|string)} handleIndex 0 or 1 or 'all'
     * @param {number} dx
     * @param {number} dy
     */
    _updateInterval: function (handleIndex, delta) {
        delta = delta || 0;
        var visualMapModel = this.visualMapModel;
        var handleEnds = this._handleEnds;
        var sizeExtent = [0, visualMapModel.itemSize[1]];

        sliderMove(
            delta,
            handleEnds,
            sizeExtent,
            handleIndex,
            // cross is forbiden
            0
        );

        var dataExtent = visualMapModel.getExtent();
        // Update data interval.
        this._dataInterval = [
            linearMap$3(handleEnds[0], sizeExtent, dataExtent, true),
            linearMap$3(handleEnds[1], sizeExtent, dataExtent, true)
        ];
    },

    /**
     * @private
     */
    _updateView: function (forSketch) {
        var visualMapModel = this.visualMapModel;
        var dataExtent = visualMapModel.getExtent();
        var shapes = this._shapes;

        var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
        var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;

        var visualInRange = this._createBarVisual(
            this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'
        );
        var visualOutOfRange = this._createBarVisual(
            dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'
        );

        shapes.inRange
            .setStyle({
                fill: visualInRange.barColor,
                opacity: visualInRange.opacity
            })
            .setShape('points', visualInRange.barPoints);
        shapes.outOfRange
            .setStyle({
                fill: visualOutOfRange.barColor,
                opacity: visualOutOfRange.opacity
            })
            .setShape('points', visualOutOfRange.barPoints);

        this._updateHandle(inRangeHandleEnds, visualInRange);
    },

    /**
     * @private
     */
    _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) {
        var opts = {
            forceState: forceState,
            convertOpacityToAlpha: true
        };
        var colorStops = this._makeColorGradient(dataInterval, opts);

        var symbolSizes = [
            this.getControllerVisual(dataInterval[0], 'symbolSize', opts),
            this.getControllerVisual(dataInterval[1], 'symbolSize', opts)
        ];
        var barPoints = this._createBarPoints(handleEnds, symbolSizes);

        return {
            barColor: new LinearGradient(0, 0, 0, 1, colorStops),
            barPoints: barPoints,
            handlesColor: [
                colorStops[0].color,
                colorStops[colorStops.length - 1].color
            ]
        };
    },

    /**
     * @private
     */
    _makeColorGradient: function (dataInterval, opts) {
        // Considering colorHue, which is not linear, so we have to sample
        // to calculate gradient color stops, but not only caculate head
        // and tail.
        var sampleNumber = 100; // Arbitrary value.
        var colorStops = [];
        var step = (dataInterval[1] - dataInterval[0]) / sampleNumber;

        colorStops.push({
            color: this.getControllerVisual(dataInterval[0], 'color', opts),
            offset: 0
        });

        for (var i = 1; i < sampleNumber; i++) {
            var currValue = dataInterval[0] + step * i;
            if (currValue > dataInterval[1]) {
                break;
            }
            colorStops.push({
                color: this.getControllerVisual(currValue, 'color', opts),
                offset: i / sampleNumber
            });
        }

        colorStops.push({
            color: this.getControllerVisual(dataInterval[1], 'color', opts),
            offset: 1
        });

        return colorStops;
    },

    /**
     * @private
     */
    _createBarPoints: function (handleEnds, symbolSizes) {
        var itemSize = this.visualMapModel.itemSize;

        return [
            [itemSize[0] - symbolSizes[0], handleEnds[0]],
            [itemSize[0], handleEnds[0]],
            [itemSize[0], handleEnds[1]],
            [itemSize[0] - symbolSizes[1], handleEnds[1]]
        ];
    },

    /**
     * @private
     */
    _createBarGroup: function (itemAlign) {
        var orient = this._orient;
        var inverse = this.visualMapModel.get('inverse');

        return new Group(
            (orient === 'horizontal' && !inverse)
            ? {scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1], rotation: Math.PI / 2}
            : (orient === 'horizontal' && inverse)
            ? {scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1], rotation: -Math.PI / 2}
            : (orient === 'vertical' && !inverse)
            ? {scale: itemAlign === 'left' ? [1, -1] : [-1, -1]}
            : {scale: itemAlign === 'left' ? [1, 1] : [-1, 1]}
        );
    },

    /**
     * @private
     */
    _updateHandle: function (handleEnds, visualInRange) {
        if (!this._useHandle) {
            return;
        }

        var shapes = this._shapes;
        var visualMapModel = this.visualMapModel;
        var handleThumbs = shapes.handleThumbs;
        var handleLabels = shapes.handleLabels;

        each$29([0, 1], function (handleIndex) {
            var handleThumb = handleThumbs[handleIndex];
            handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]);
            handleThumb.position[1] = handleEnds[handleIndex];

            // Update handle label position.
            var textPoint = applyTransform$1(
                shapes.handleLabelPoints[handleIndex],
                getTransform(handleThumb, this.group)
            );
            handleLabels[handleIndex].setStyle({
                x: textPoint[0],
                y: textPoint[1],
                text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
                textVerticalAlign: 'middle',
                textAlign: this._applyTransform(
                    this._orient === 'horizontal'
                        ? (handleIndex === 0 ? 'bottom' : 'top')
                        : 'left',
                    shapes.barGroup
                )
            });
        }, this);
    },

    /**
     * @private
     * @param {number} cursorValue
     * @param {number} textValue
     * @param {string} [rangeSymbol]
     * @param {number} [halfHoverLinkSize]
     */
    _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) {
        var visualMapModel = this.visualMapModel;
        var dataExtent = visualMapModel.getExtent();
        var itemSize = visualMapModel.itemSize;
        var sizeExtent = [0, itemSize[1]];
        var pos = linearMap$3(cursorValue, dataExtent, sizeExtent, true);

        var shapes = this._shapes;
        var indicator = shapes.indicator;
        if (!indicator) {
            return;
        }

        indicator.position[1] = pos;
        indicator.attr('invisible', false);
        indicator.setShape('points', createIndicatorPoints(
            !!rangeSymbol, halfHoverLinkSize, pos, itemSize[1]
        ));

        var opts = {convertOpacityToAlpha: true};
        var color = this.getControllerVisual(cursorValue, 'color', opts);
        indicator.setStyle('fill', color);

        // Update handle label position.
        var textPoint = applyTransform$1(
            shapes.indicatorLabelPoint,
            getTransform(indicator, this.group)
        );

        var indicatorLabel = shapes.indicatorLabel;
        indicatorLabel.attr('invisible', false);
        var align = this._applyTransform('left', shapes.barGroup);
        var orient = this._orient;
        indicatorLabel.setStyle({
            text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
            textVerticalAlign: orient === 'horizontal' ? align : 'middle',
            textAlign: orient === 'horizontal' ? 'center' : align,
            x: textPoint[0],
            y: textPoint[1]
        });
    },

    /**
     * @private
     */
    _enableHoverLinkToSeries: function () {
        var self = this;
        this._shapes.barGroup

            .on('mousemove', function (e) {
                self._hovering = true;

                if (!self._dragging) {
                    var itemSize = self.visualMapModel.itemSize;
                    var pos = self._applyTransform(
                        [e.offsetX, e.offsetY], self._shapes.barGroup, true, true
                    );
                    // For hover link show when hover handle, which might be
                    // below or upper than sizeExtent.
                    pos[1] = mathMin$8(mathMax$8(0, pos[1]), itemSize[1]);
                    self._doHoverLinkToSeries(
                        pos[1],
                        0 <= pos[0] && pos[0] <= itemSize[0]
                    );
                }
            })

            .on('mouseout', function () {
                // When mouse is out of handle, hoverLink still need
                // to be displayed when realtime is set as false.
                self._hovering = false;
                !self._dragging && self._clearHoverLinkToSeries();
            });
    },

    /**
     * @private
     */
    _enableHoverLinkFromSeries: function () {
        var zr = this.api.getZr();

        if (this.visualMapModel.option.hoverLink) {
            zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this);
            zr.on('mouseout', this._hideIndicator, this);
        }
        else {
            this._clearHoverLinkFromSeries();
        }
    },

    /**
     * @private
     */
    _doHoverLinkToSeries: function (cursorPos, hoverOnBar) {
        var visualMapModel = this.visualMapModel;
        var itemSize = visualMapModel.itemSize;

        if (!visualMapModel.option.hoverLink) {
            return;
        }

        var sizeExtent = [0, itemSize[1]];
        var dataExtent = visualMapModel.getExtent();

        // For hover link show when hover handle, which might be below or upper than sizeExtent.
        cursorPos = mathMin$8(mathMax$8(sizeExtent[0], cursorPos), sizeExtent[1]);

        var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent);
        var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize];
        var cursorValue = linearMap$3(cursorPos, sizeExtent, dataExtent, true);
        var valueRange = [
            linearMap$3(hoverRange[0], sizeExtent, dataExtent, true),
            linearMap$3(hoverRange[1], sizeExtent, dataExtent, true)
        ];
        // Consider data range is out of visualMap range, see test/visualMap-continuous.html,
        // where china and india has very large population.
        hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity);
        hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity);

        // Do not show indicator when mouse is over handle,
        // otherwise labels overlap, especially when dragging.
        if (hoverOnBar) {
            if (valueRange[0] === -Infinity) {
                this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize);
            }
            else if (valueRange[1] === Infinity) {
                this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize);
            }
            else {
                this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize);
            }
        }

        // When realtime is set as false, handles, which are in barGroup,
        // also trigger hoverLink, which help user to realize where they
        // focus on when dragging. (see test/heatmap-large.html)
        // When realtime is set as true, highlight will not show when hover
        // handle, because the label on handle, which displays a exact value
        // but not range, might mislead users.
        var oldBatch = this._hoverLinkDataIndices;
        var newBatch = [];
        if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
            newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
        }

        var resultBatches = compressBatches(oldBatch, newBatch);

        this._dispatchHighDown('downplay', makeHighDownBatch(resultBatches[0], visualMapModel));
        this._dispatchHighDown('highlight', makeHighDownBatch(resultBatches[1], visualMapModel));
    },

    /**
     * @private
     */
    _hoverLinkFromSeriesMouseOver: function (e) {
        var el = e.target;
        var visualMapModel = this.visualMapModel;

        if (!el || el.dataIndex == null) {
            return;
        }

        var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex);

        if (!visualMapModel.isTargetSeries(dataModel)) {
            return;
        }

        var data = dataModel.getData(el.dataType);
        var value = data.get(visualMapModel.getDataDimension(data), el.dataIndex, true);

        if (!isNaN(value)) {
            this._showIndicator(value, value);
        }
    },

    /**
     * @private
     */
    _hideIndicator: function () {
        var shapes = this._shapes;
        shapes.indicator && shapes.indicator.attr('invisible', true);
        shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);
    },

    /**
     * @private
     */
    _clearHoverLinkToSeries: function () {
        this._hideIndicator();

        var indices = this._hoverLinkDataIndices;
        this._dispatchHighDown('downplay', makeHighDownBatch(indices, this.visualMapModel));

        indices.length = 0;
    },

    /**
     * @private
     */
    _clearHoverLinkFromSeries: function () {
        this._hideIndicator();

        var zr = this.api.getZr();
        zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
        zr.off('mouseout', this._hideIndicator);
    },

    /**
     * @private
     */
    _applyTransform: function (vertex, element, inverse, global) {
        var transform = getTransform(element, global ? null : this.group);

        return graphic[
            isArray(vertex) ? 'applyTransform' : 'transformDirection'
        ](vertex, transform, inverse);
    },

    /**
     * @private
     */
    _dispatchHighDown: function (type, batch) {
        batch && batch.length && this.api.dispatchAction({
            type: type,
            batch: batch
        });
    },

    /**
     * @override
     */
    dispose: function () {
        this._clearHoverLinkFromSeries();
        this._clearHoverLinkToSeries();
    },

    /**
     * @override
     */
    remove: function () {
        this._clearHoverLinkFromSeries();
        this._clearHoverLinkToSeries();
    }

});

function createPolygon(points, cursor, onDrift, onDragEnd) {
    return new Polygon({
        shape: {points: points},
        draggable: !!onDrift,
        cursor: cursor,
        drift: onDrift,
        onmousemove: function (e) {
            // Fot mobile devicem, prevent screen slider on the button.
            stop(e.event);
        },
        ondragend: onDragEnd
    });
}

function createHandlePoints(handleIndex, textSize) {
    return handleIndex === 0
        ? [[0, 0], [textSize, 0], [textSize, -textSize]]
        : [[0, 0], [textSize, 0], [textSize, textSize]];
}

function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) {
    return isRange
        ? [ // indicate range
            [0, -mathMin$8(halfHoverLinkSize, mathMax$8(pos, 0))],
            [HOVER_LINK_OUT, 0],
            [0, mathMin$8(halfHoverLinkSize, mathMax$8(extentMax - pos, 0))]
        ]
        : [ // indicate single value
            [0, 0], [5, -5], [5, 5]
        ];
}

function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
    var halfHoverLinkSize = HOVER_LINK_SIZE / 2;
    var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');
    if (hoverLinkDataSize) {
        halfHoverLinkSize = linearMap$3(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2;
    }
    return halfHoverLinkSize;
}

function useHoverLinkOnHandle(visualMapModel) {
    var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle');
    return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle);
}

function getCursor$1(orient) {
    return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var actionInfo$2 = {
    type: 'selectDataRange',
    event: 'dataRangeSelected',
    // FIXME use updateView appears wrong
    update: 'update'
};

registerAction(actionInfo$2, function (payload, ecModel) {

    ecModel.eachComponent({mainType: 'visualMap', query: payload}, function (model) {
        model.setSelected(payload.selected);
    });

});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * DataZoom component entry
 */

registerPreprocessor(preprocessor$3);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PiecewiseModel = VisualMapModel.extend({

    type: 'visualMap.piecewise',

    /**
     * Order Rule:
     *
     * option.categories / option.pieces / option.text / option.selected:
     *     If !option.inverse,
     *     Order when vertical: ['top', ..., 'bottom'].
     *     Order when horizontal: ['left', ..., 'right'].
     *     If option.inverse, the meaning of
     *     the order should be reversed.
     *
     * this._pieceList:
     *     The order is always [low, ..., high].
     *
     * Mapping from location to low-high:
     *     If !option.inverse
     *     When vertical, top is high.
     *     When horizontal, right is high.
     *     If option.inverse, reverse.
     */

    /**
     * @protected
     */
    defaultOption: {
        selected: null,             // Object. If not specified, means selected.
                                    // When pieces and splitNumber: {'0': true, '5': true}
                                    // When categories: {'cate1': false, 'cate3': true}
                                    // When selected === false, means all unselected.

        minOpen: false,             // Whether include values that smaller than `min`.
        maxOpen: false,             // Whether include values that bigger than `max`.

        align: 'auto',              // 'auto', 'left', 'right'
        itemWidth: 20,              // When put the controller vertically, it is the length of
                                    // horizontal side of each item. Otherwise, vertical side.
        itemHeight: 14,             // When put the controller vertically, it is the length of
                                    // vertical side of each item. Otherwise, horizontal side.
        itemSymbol: 'roundRect',
        pieceList: null,            // Each item is Object, with some of those attrs:
                                    // {min, max, lt, gt, lte, gte, value,
                                    // color, colorSaturation, colorAlpha, opacity,
                                    // symbol, symbolSize}, which customize the range or visual
                                    // coding of the certain piece. Besides, see "Order Rule".
        categories: null,           // category names, like: ['some1', 'some2', 'some3'].
                                    // Attr min/max are ignored when categories set. See "Order Rule"
        splitNumber: 5,             // If set to 5, auto split five pieces equally.
                                    // If set to 0 and component type not set, component type will be
                                    // determined as "continuous". (It is less reasonable but for ec2
                                    // compatibility, see echarts/component/visualMap/typeDefaulter)
        selectedMode: 'multiple',   // Can be 'multiple' or 'single'.
        itemGap: 10,                // The gap between two items, in px.
        hoverLink: true,            // Enable hover highlight.

        showLabel: null             // By default, when text is used, label will hide (the logic
                                    // is remained for compatibility reason)
    },

    /**
     * @override
     */
    optionUpdated: function (newOption, isInit) {
        PiecewiseModel.superApply(this, 'optionUpdated', arguments);

        /**
         * The order is always [low, ..., high].
         * [{text: string, interval: Array.<number>}, ...]
         * @private
         * @type {Array.<Object>}
         */
        this._pieceList = [];

        this.resetExtent();

        /**
         * 'pieces', 'categories', 'splitNumber'
         * @type {string}
         */
        var mode = this._mode = this._determineMode();

        resetMethods[this._mode].call(this);

        this._resetSelected(newOption, isInit);

        var categories = this.option.categories;

        this.resetVisual(function (mappingOption, state) {
            if (mode === 'categories') {
                mappingOption.mappingMethod = 'category';
                mappingOption.categories = clone(categories);
            }
            else {
                mappingOption.dataExtent = this.getExtent();
                mappingOption.mappingMethod = 'piecewise';
                mappingOption.pieceList = map(this._pieceList, function (piece) {
                    var piece = clone(piece);
                    if (state !== 'inRange') {
                        // FIXME
                        // outOfRange do not support special visual in pieces.
                        piece.visual = null;
                    }
                    return piece;
                });
            }
        });
    },

    /**
     * @protected
     * @override
     */
    completeVisualOption: function () {
        // Consider this case:
        // visualMap: {
        //      pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}]
        // }
        // where no inRange/outOfRange set but only pieces. So we should make
        // default inRange/outOfRange for this case, otherwise visuals that only
        // appear in `pieces` will not be taken into account in visual encoding.

        var option = this.option;
        var visualTypesInPieces = {};
        var visualTypes = VisualMapping.listVisualTypes();
        var isCategory = this.isCategory();

        each$1(option.pieces, function (piece) {
            each$1(visualTypes, function (visualType) {
                if (piece.hasOwnProperty(visualType)) {
                    visualTypesInPieces[visualType] = 1;
                }
            });
        });

        each$1(visualTypesInPieces, function (v, visualType) {
            var exists = 0;
            each$1(this.stateList, function (state) {
                exists |= has(option, state, visualType)
                    || has(option.target, state, visualType);
            }, this);

            !exists && each$1(this.stateList, function (state) {
                (option[state] || (option[state] = {}))[visualType] = visualDefault.get(
                    visualType, state === 'inRange' ? 'active' : 'inactive', isCategory
                );
            });
        }, this);

        function has(obj, state, visualType) {
            return obj && obj[state] && (
                isObject$1(obj[state])
                    ? obj[state].hasOwnProperty(visualType)
                    : obj[state] === visualType // e.g., inRange: 'symbol'
            );
        }

        VisualMapModel.prototype.completeVisualOption.apply(this, arguments);
    },

    _resetSelected: function (newOption, isInit) {
        var thisOption = this.option;
        var pieceList = this._pieceList;

        // Selected do not merge but all override.
        var selected = (isInit ? thisOption : newOption).selected || {};
        thisOption.selected = selected;

        // Consider 'not specified' means true.
        each$1(pieceList, function (piece, index) {
            var key = this.getSelectedMapKey(piece);
            if (!selected.hasOwnProperty(key)) {
                selected[key] = true;
            }
        }, this);

        if (thisOption.selectedMode === 'single') {
            // Ensure there is only one selected.
            var hasSel = false;

            each$1(pieceList, function (piece, index) {
                var key = this.getSelectedMapKey(piece);
                if (selected[key]) {
                    hasSel
                        ? (selected[key] = false)
                        : (hasSel = true);
                }
            }, this);
        }
        // thisOption.selectedMode === 'multiple', default: all selected.
    },

    /**
     * @public
     */
    getSelectedMapKey: function (piece) {
        return this._mode === 'categories'
            ? piece.value + '' : piece.index + '';
    },

    /**
     * @public
     */
    getPieceList: function () {
        return this._pieceList;
    },

    /**
     * @private
     * @return {string}
     */
    _determineMode: function () {
        var option = this.option;

        return option.pieces && option.pieces.length > 0
            ? 'pieces'
            : this.option.categories
            ? 'categories'
            : 'splitNumber';
    },

    /**
     * @public
     * @override
     */
    setSelected: function (selected) {
        this.option.selected = clone(selected);
    },

    /**
     * @public
     * @override
     */
    getValueState: function (value) {
        var index = VisualMapping.findPieceIndex(value, this._pieceList);

        return index != null
            ? (this.option.selected[this.getSelectedMapKey(this._pieceList[index])]
                ? 'inRange' : 'outOfRange'
            )
            : 'outOfRange';
    },

    /**
     * @public
     * @params {number} pieceIndex piece index in visualMapModel.getPieceList()
     * @return {Array.<Object>} [{seriesId, dataIndex: <Array.<number>>}, ...]
     */
    findTargetDataIndices: function (pieceIndex) {
        var result = [];

        this.eachTargetSeries(function (seriesModel) {
            var dataIndices = [];
            var data = seriesModel.getData();

            data.each(this.getDataDimension(data), function (value, dataIndex) {
                // Should always base on model pieceList, because it is order sensitive.
                var pIdx = VisualMapping.findPieceIndex(value, this._pieceList);
                pIdx === pieceIndex && dataIndices.push(dataIndex);
            }, this);

            result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
        }, this);

        return result;
    },

    /**
     * @private
     * @param {Object} piece piece.value or piece.interval is required.
     * @return {number} Can be Infinity or -Infinity
     */
    getRepresentValue: function (piece) {
        var representValue;
        if (this.isCategory()) {
            representValue = piece.value;
        }
        else {
            if (piece.value != null) {
                representValue = piece.value;
            }
            else {
                var pieceInterval = piece.interval || [];
                representValue = (pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity)
                    ? 0
                    : (pieceInterval[0] + pieceInterval[1]) / 2;
            }
        }
        return representValue;
    },

    getVisualMeta: function (getColorVisual) {
        // Do not support category. (category axis is ordinal, numerical)
        if (this.isCategory()) {
            return;
        }

        var stops = [];
        var outerColors = [];
        var visualMapModel = this;

        function setStop(interval, valueState) {
            var representValue = visualMapModel.getRepresentValue({interval: interval});
            if (!valueState) {
                valueState = visualMapModel.getValueState(representValue);
            }
            var color = getColorVisual(representValue, valueState);
            if (interval[0] === -Infinity) {
                outerColors[0] = color;
            }
            else if (interval[1] === Infinity) {
                outerColors[1] = color;
            }
            else {
                stops.push(
                    {value: interval[0], color: color},
                    {value: interval[1], color: color}
                );
            }
        }

        // Suplement
        var pieceList = this._pieceList.slice();
        if (!pieceList.length) {
            pieceList.push({interval: [-Infinity, Infinity]});
        }
        else {
            var edge = pieceList[0].interval[0];
            edge !== -Infinity && pieceList.unshift({interval: [-Infinity, edge]});
            edge = pieceList[pieceList.length - 1].interval[1];
            edge !== Infinity && pieceList.push({interval: [edge, Infinity]});
        }

        var curr = -Infinity;
        each$1(pieceList, function (piece) {
            var interval = piece.interval;
            if (interval) {
                // Fulfill gap.
                interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
                setStop(interval.slice());
                curr = interval[1];
            }
        }, this);

        return {stops: stops, outerColors: outerColors};
    }

});

/**
 * Key is this._mode
 * @type {Object}
 * @this {module:echarts/component/viusalMap/PiecewiseMode}
 */
var resetMethods = {

    splitNumber: function () {
        var thisOption = this.option;
        var pieceList = this._pieceList;
        var precision = Math.min(thisOption.precision, 20);
        var dataExtent = this.getExtent();
        var splitNumber = thisOption.splitNumber;
        splitNumber = Math.max(parseInt(splitNumber, 10), 1);
        thisOption.splitNumber = splitNumber;

        var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber;
        // Precision auto-adaption
        while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
            precision++;
        }
        thisOption.precision = precision;
        splitStep = +splitStep.toFixed(precision);

        var index = 0;

        if (thisOption.minOpen) {
            pieceList.push({
                index: index++,
                interval: [-Infinity, dataExtent[0]],
                close: [0, 0]
            });
        }

        for (
            var curr = dataExtent[0], len = index + splitNumber;
            index < len;
            curr += splitStep
        ) {
            var max = index === splitNumber - 1 ? dataExtent[1] : (curr + splitStep);

            pieceList.push({
                index: index++,
                interval: [curr, max],
                close: [1, 1]
            });
        }

        if (thisOption.maxOpen) {
            pieceList.push({
                index: index++,
                interval: [dataExtent[1], Infinity],
                close: [0, 0]
            });
        }

        reformIntervals(pieceList);

        each$1(pieceList, function (piece) {
            piece.text = this.formatValueText(piece.interval);
        }, this);
    },

    categories: function () {
        var thisOption = this.option;
        each$1(thisOption.categories, function (cate) {
            // FIXME category模式也使用pieceList，但在visualMapping中不是使用pieceList。
            // 是否改一致。
            this._pieceList.push({
                text: this.formatValueText(cate, true),
                value: cate
            });
        }, this);

        // See "Order Rule".
        normalizeReverse(thisOption, this._pieceList);
    },

    pieces: function () {
        var thisOption = this.option;
        var pieceList = this._pieceList;

        each$1(thisOption.pieces, function (pieceListItem, index) {

            if (!isObject$1(pieceListItem)) {
                pieceListItem = {value: pieceListItem};
            }

            var item = {text: '', index: index};

            if (pieceListItem.label != null) {
                item.text = pieceListItem.label;
            }

            if (pieceListItem.hasOwnProperty('value')) {
                var value = item.value = pieceListItem.value;
                item.interval = [value, value];
                item.close = [1, 1];
            }
            else {
                // `min` `max` is legacy option.
                // `lt` `gt` `lte` `gte` is recommanded.
                var interval = item.interval = [];
                var close = item.close = [0, 0];

                var closeList = [1, 0, 1];
                var infinityList = [-Infinity, Infinity];

                var useMinMax = [];
                for (var lg = 0; lg < 2; lg++) {
                    var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg];
                    for (var i = 0; i < 3 && interval[lg] == null; i++) {
                        interval[lg] = pieceListItem[names[i]];
                        close[lg] = closeList[i];
                        useMinMax[lg] = i === 2;
                    }
                    interval[lg] == null && (interval[lg] = infinityList[lg]);
                }
                useMinMax[0] && interval[1] === Infinity && (close[0] = 0);
                useMinMax[1] && interval[0] === -Infinity && (close[1] = 0);

                if (__DEV__) {
                    if (interval[0] > interval[1]) {
                        console.warn(
                            'Piece ' + index + 'is illegal: ' + interval
                            + ' lower bound should not greater then uppper bound.'
                        );
                    }
                }

                if (interval[0] === interval[1] && close[0] && close[1]) {
                    // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}],
                    // we use value to lift the priority when min === max
                    item.value = interval[0];
                }
            }

            item.visual = VisualMapping.retrieveVisuals(pieceListItem);

            pieceList.push(item);

        }, this);

        // See "Order Rule".
        normalizeReverse(thisOption, pieceList);
        // Only pieces
        reformIntervals(pieceList);

        each$1(pieceList, function (piece) {
            var close = piece.close;
            var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
            piece.text = piece.text || this.formatValueText(
                piece.value != null ? piece.value : piece.interval,
                false,
                edgeSymbols
            );
        }, this);
    }
};

function normalizeReverse(thisOption, pieceList) {
    var inverse = thisOption.inverse;
    if (thisOption.orient === 'vertical' ? !inverse : inverse) {
            pieceList.reverse();
    }
}

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

var PiecewiseVisualMapView = VisualMapView.extend({

    type: 'visualMap.piecewise',

    /**
     * @protected
     * @override
     */
    doRender: function () {
        var thisGroup = this.group;

        thisGroup.removeAll();

        var visualMapModel = this.visualMapModel;
        var textGap = visualMapModel.get('textGap');
        var textStyleModel = visualMapModel.textStyleModel;
        var textFont = textStyleModel.getFont();
        var textFill = textStyleModel.getTextColor();
        var itemAlign = this._getItemAlign();
        var itemSize = visualMapModel.itemSize;
        var viewData = this._getViewData();
        var endsText = viewData.endsText;
        var showLabel = retrieve(visualMapModel.get('showLabel', true), !endsText);

        endsText && this._renderEndsText(
            thisGroup, endsText[0], itemSize, showLabel, itemAlign
        );

        each$1(viewData.viewPieceList, renderItem, this);

        endsText && this._renderEndsText(
            thisGroup, endsText[1], itemSize, showLabel, itemAlign
        );

        box(
            visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap')
        );

        this.renderBackground(thisGroup);

        this.positionGroup(thisGroup);

        function renderItem(item) {
            var piece = item.piece;

            var itemGroup = new Group();
            itemGroup.onclick = bind(this._onItemClick, this, piece);

            this._enableHoverLink(itemGroup, item.indexInModelPieceList);

            var representValue = visualMapModel.getRepresentValue(piece);

            this._createItemSymbol(
                itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]
            );

            if (showLabel) {
                var visualState = this.visualMapModel.getValueState(representValue);

                itemGroup.add(new Text({
                    style: {
                        x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap,
                        y: itemSize[1] / 2,
                        text: piece.text,
                        textVerticalAlign: 'middle',
                        textAlign: itemAlign,
                        textFont: textFont,
                        textFill: textFill,
                        opacity: visualState === 'outOfRange' ? 0.5 : 1
                    }
                }));
            }

            thisGroup.add(itemGroup);
        }
    },

    /**
     * @private
     */
    _enableHoverLink: function (itemGroup, pieceIndex) {
        itemGroup
            .on('mouseover', bind(onHoverLink, this, 'highlight'))
            .on('mouseout', bind(onHoverLink, this, 'downplay'));

        function onHoverLink(method) {
            var visualMapModel = this.visualMapModel;

            visualMapModel.option.hoverLink && this.api.dispatchAction({
                type: method,
                batch: makeHighDownBatch(
                    visualMapModel.findTargetDataIndices(pieceIndex),
                    visualMapModel
                )
            });
        }
    },

    /**
     * @private
     */
    _getItemAlign: function () {
        var visualMapModel = this.visualMapModel;
        var modelOption = visualMapModel.option;

        if (modelOption.orient === 'vertical') {
            return getItemAlign(
                visualMapModel, this.api, visualMapModel.itemSize
            );
        }
        else { // horizontal, most case left unless specifying right.
            var align = modelOption.align;
            if (!align || align === 'auto') {
                align = 'left';
            }
            return align;
        }
    },

    /**
     * @private
     */
    _renderEndsText: function (group, text, itemSize, showLabel, itemAlign) {
        if (!text) {
            return;
        }

        var itemGroup = new Group();
        var textStyleModel = this.visualMapModel.textStyleModel;

        itemGroup.add(new Text({
            style: {
                x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2,
                y: itemSize[1] / 2,
                textVerticalAlign: 'middle',
                textAlign: showLabel ? itemAlign : 'center',
                text: text,
                textFont: textStyleModel.getFont(),
                textFill: textStyleModel.getTextColor()
            }
        }));

        group.add(itemGroup);
    },

    /**
     * @private
     * @return {Object} {peiceList, endsText} The order is the same as screen pixel order.
     */
    _getViewData: function () {
        var visualMapModel = this.visualMapModel;

        var viewPieceList = map(visualMapModel.getPieceList(), function (piece, index) {
            return {piece: piece, indexInModelPieceList: index};
        });
        var endsText = visualMapModel.get('text');

        // Consider orient and inverse.
        var orient = visualMapModel.get('orient');
        var inverse = visualMapModel.get('inverse');

        // Order of model pieceList is always [low, ..., high]
        if (orient === 'horizontal' ? inverse : !inverse) {
            viewPieceList.reverse();
        }
        // Origin order of endsText is [high, low]
        else if (endsText) {
            endsText = endsText.slice().reverse();
        }

        return {viewPieceList: viewPieceList, endsText: endsText};
    },

    /**
     * @private
     */
    _createItemSymbol: function (group, representValue, shapeParam) {
        group.add(createSymbol(
            this.getControllerVisual(representValue, 'symbol'),
            shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3],
            this.getControllerVisual(representValue, 'color')
        ));
    },

    /**
     * @private
     */
    _onItemClick: function (piece) {
        var visualMapModel = this.visualMapModel;
        var option = visualMapModel.option;
        var selected = clone(option.selected);
        var newKey = visualMapModel.getSelectedMapKey(piece);

        if (option.selectedMode === 'single') {
            selected[newKey] = true;
            each$1(selected, function (o, key) {
                selected[key] = key === newKey;
            });
        }
        else {
            selected[newKey] = !selected[newKey];
        }

        this.api.dispatchAction({
            type: 'selectDataRange',
            from: this.uid,
            visualMapId: this.visualMapModel.id,
            selected: selected
        });
    }
});

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * DataZoom component entry
 */

registerPreprocessor(preprocessor$3);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * visualMap component entry
 */

var urn = 'urn:schemas-microsoft-com:vml';
var win = typeof window === 'undefined' ? null : window;

var vmlInited = false;

var doc = win && win.document;

function createNode(tagName) {
    return doCreateNode(tagName);
}

// Avoid assign to an exported variable, for transforming to cjs.
var doCreateNode;

if (doc && !env$1.canvasSupported) {
    try {
        !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn);
        doCreateNode = function (tagName) {
            return doc.createElement('<zrvml:' + tagName + ' class="zrvml">');
        };
    }
    catch (e) {
        doCreateNode = function (tagName) {
            return doc.createElement('<' + tagName + ' xmlns="' + urn + '" class="zrvml">');
        };
    }
}

// From raphael
function initVML() {
    if (vmlInited || !doc) {
        return;
    }
    vmlInited = true;

    var styleSheets = doc.styleSheets;
    if (styleSheets.length < 31) {
        doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)');
    }
    else {
        // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
        styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)');
    }
}

// http://www.w3.org/TR/NOTE-VML
// TODO Use proxy like svg instead of overwrite brush methods

var CMD$3 = PathProxy.CMD;
var round$3 = Math.round;
var sqrt = Math.sqrt;
var abs$1 = Math.abs;
var cos = Math.cos;
var sin = Math.sin;
var mathMax$9 = Math.max;

if (!env$1.canvasSupported) {

    var comma = ',';
    var imageTransformPrefix = 'progid:DXImageTransform.Microsoft';

    var Z = 21600;
    var Z2 = Z / 2;

    var ZLEVEL_BASE = 100000;
    var Z_BASE$1 = 1000;

    var initRootElStyle = function (el) {
        el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;';
        el.coordsize = Z + ',' + Z;
        el.coordorigin = '0,0';
    };

    var encodeHtmlAttribute = function (s) {
        return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
    };

    var rgb2Str = function (r, g, b) {
        return 'rgb(' + [r, g, b].join(',') + ')';
    };

    var append = function (parent, child) {
        if (child && parent && child.parentNode !== parent) {
            parent.appendChild(child);
        }
    };

    var remove = function (parent, child) {
        if (child && parent && child.parentNode === parent) {
            parent.removeChild(child);
        }
    };

    var getZIndex = function (zlevel, z, z2) {
        // z 的取值范围为 [0, 1000]
        return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE$1 + z2;
    };

    var parsePercent$3 = parsePercent;

    /***************************************************
     * PATH
     **************************************************/

    var setColorAndOpacity = function (el, color, opacity) {
        var colorArr = parse(color);
        opacity = +opacity;
        if (isNaN(opacity)) {
            opacity = 1;
        }
        if (colorArr) {
            el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]);
            el.opacity = opacity * colorArr[3];
        }
    };

    var getColorAndAlpha = function (color) {
        var colorArr = parse(color);
        return [
            rgb2Str(colorArr[0], colorArr[1], colorArr[2]),
            colorArr[3]
        ];
    };

    var updateFillNode = function (el, style, zrEl) {
        // TODO pattern
        var fill = style.fill;
        if (fill != null) {
            // Modified from excanvas
            if (fill instanceof Gradient) {
                var gradientType;
                var angle = 0;
                var focus = [0, 0];
                // additional offset
                var shift = 0;
                // scale factor for offset
                var expansion = 1;
                var rect = zrEl.getBoundingRect();
                var rectWidth = rect.width;
                var rectHeight = rect.height;
                if (fill.type === 'linear') {
                    gradientType = 'gradient';
                    var transform = zrEl.transform;
                    var p0 = [fill.x * rectWidth, fill.y * rectHeight];
                    var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight];
                    if (transform) {
                        applyTransform(p0, p0, transform);
                        applyTransform(p1, p1, transform);
                    }
                    var dx = p1[0] - p0[0];
                    var dy = p1[1] - p0[1];
                    angle = Math.atan2(dx, dy) * 180 / Math.PI;
                    // The angle should be a non-negative number.
                    if (angle < 0) {
                        angle += 360;
                    }

                    // Very small angles produce an unexpected result because they are
                    // converted to a scientific notation string.
                    if (angle < 1e-6) {
                        angle = 0;
                    }
                }
                else {
                    gradientType = 'gradientradial';
                    var p0 = [fill.x * rectWidth, fill.y * rectHeight];
                    var transform = zrEl.transform;
                    var scale$$1 = zrEl.scale;
                    var width = rectWidth;
                    var height = rectHeight;
                    focus = [
                        // Percent in bounding rect
                        (p0[0] - rect.x) / width,
                        (p0[1] - rect.y) / height
                    ];
                    if (transform) {
                        applyTransform(p0, p0, transform);
                    }

                    width /= scale$$1[0] * Z;
                    height /= scale$$1[1] * Z;
                    var dimension = mathMax$9(width, height);
                    shift = 2 * 0 / dimension;
                    expansion = 2 * fill.r / dimension - shift;
                }

                // We need to sort the color stops in ascending order by offset,
                // otherwise IE won't interpret it correctly.
                var stops = fill.colorStops.slice();
                stops.sort(function (cs1, cs2) {
                    return cs1.offset - cs2.offset;
                });

                var length$$1 = stops.length;
                // Color and alpha list of first and last stop
                var colorAndAlphaList = [];
                var colors = [];
                for (var i = 0; i < length$$1; i++) {
                    var stop = stops[i];
                    var colorAndAlpha = getColorAndAlpha(stop.color);
                    colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]);
                    if (i === 0 || i === length$$1 - 1) {
                        colorAndAlphaList.push(colorAndAlpha);
                    }
                }

                if (length$$1 >= 2) {
                    var color1 = colorAndAlphaList[0][0];
                    var color2 = colorAndAlphaList[1][0];
                    var opacity1 = colorAndAlphaList[0][1] * style.opacity;
                    var opacity2 = colorAndAlphaList[1][1] * style.opacity;

                    el.type = gradientType;
                    el.method = 'none';
                    el.focus = '100%';
                    el.angle = angle;
                    el.color = color1;
                    el.color2 = color2;
                    el.colors = colors.join(',');
                    // When colors attribute is used, the meanings of opacity and o:opacity2
                    // are reversed.
                    el.opacity = opacity2;
                    // FIXME g_o_:opacity ?
                    el.opacity2 = opacity1;
                }
                if (gradientType === 'radial') {
                    el.focusposition = focus.join(',');
                }
            }
            else {
                // FIXME Change from Gradient fill to color fill
                setColorAndOpacity(el, fill, style.opacity);
            }
        }
    };

    var updateStrokeNode = function (el, style) {
        // if (style.lineJoin != null) {
        //     el.joinstyle = style.lineJoin;
        // }
        // if (style.miterLimit != null) {
        //     el.miterlimit = style.miterLimit * Z;
        // }
        // if (style.lineCap != null) {
        //     el.endcap = style.lineCap;
        // }
        if (style.lineDash) {
            el.dashstyle = style.lineDash.join(' ');
        }
        if (style.stroke != null && !(style.stroke instanceof Gradient)) {
            setColorAndOpacity(el, style.stroke, style.opacity);
        }
    };

    var updateFillAndStroke = function (vmlEl, type, style, zrEl) {
        var isFill = type === 'fill';
        var el = vmlEl.getElementsByTagName(type)[0];
        // Stroke must have lineWidth
        if (style[type] != null && style[type] !== 'none' && (isFill || (!isFill && style.lineWidth))) {
            vmlEl[isFill ? 'filled' : 'stroked'] = 'true';
            // FIXME Remove before updating, or set `colors` will throw error
            if (style[type] instanceof Gradient) {
                remove(vmlEl, el);
            }
            if (!el) {
                el = createNode(type);
            }

            isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style);
            append(vmlEl, el);
        }
        else {
            vmlEl[isFill ? 'filled' : 'stroked'] = 'false';
            remove(vmlEl, el);
        }
    };

    var points$3 = [[], [], []];
    var pathDataToString = function (path, m) {
        var M = CMD$3.M;
        var C = CMD$3.C;
        var L = CMD$3.L;
        var A = CMD$3.A;
        var Q = CMD$3.Q;

        var str = [];
        var nPoint;
        var cmdStr;
        var cmd;
        var i;
        var xi;
        var yi;
        var data = path.data;
        var dataLength = path.len();
        for (i = 0; i < dataLength;) {
            cmd = data[i++];
            cmdStr = '';
            nPoint = 0;
            switch (cmd) {
                case M:
                    cmdStr = ' m ';
                    nPoint = 1;
                    xi = data[i++];
                    yi = data[i++];
                    points$3[0][0] = xi;
                    points$3[0][1] = yi;
                    break;
                case L:
                    cmdStr = ' l ';
                    nPoint = 1;
                    xi = data[i++];
                    yi = data[i++];
                    points$3[0][0] = xi;
                    points$3[0][1] = yi;
                    break;
                case Q:
                case C:
                    cmdStr = ' c ';
                    nPoint = 3;
                    var x1 = data[i++];
                    var y1 = data[i++];
                    var x2 = data[i++];
                    var y2 = data[i++];
                    var x3;
                    var y3;
                    if (cmd === Q) {
                        // Convert quadratic to cubic using degree elevation
                        x3 = x2;
                        y3 = y2;
                        x2 = (x2 + 2 * x1) / 3;
                        y2 = (y2 + 2 * y1) / 3;
                        x1 = (xi + 2 * x1) / 3;
                        y1 = (yi + 2 * y1) / 3;
                    }
                    else {
                        x3 = data[i++];
                        y3 = data[i++];
                    }
                    points$3[0][0] = x1;
                    points$3[0][1] = y1;
                    points$3[1][0] = x2;
                    points$3[1][1] = y2;
                    points$3[2][0] = x3;
                    points$3[2][1] = y3;

                    xi = x3;
                    yi = y3;
                    break;
                case A:
                    var x = 0;
                    var y = 0;
                    var sx = 1;
                    var sy = 1;
                    var angle = 0;
                    if (m) {
                        // Extract SRT from matrix
                        x = m[4];
                        y = m[5];
                        sx = sqrt(m[0] * m[0] + m[1] * m[1]);
                        sy = sqrt(m[2] * m[2] + m[3] * m[3]);
                        angle = Math.atan2(-m[1] / sy, m[0] / sx);
                    }

                    var cx = data[i++];
                    var cy = data[i++];
                    var rx = data[i++];
                    var ry = data[i++];
                    var startAngle = data[i++] + angle;
                    var endAngle = data[i++] + startAngle + angle;
                    // FIXME
                    // var psi = data[i++];
                    i++;
                    var clockwise = data[i++];

                    var x0 = cx + cos(startAngle) * rx;
                    var y0 = cy + sin(startAngle) * ry;

                    var x1 = cx + cos(endAngle) * rx;
                    var y1 = cy + sin(endAngle) * ry;

                    var type = clockwise ? ' wa ' : ' at ';
                    if (Math.abs(x0 - x1) < 1e-4) {
                        // IE won't render arches drawn counter clockwise if x0 == x1.
                        if (Math.abs(endAngle - startAngle) > 1e-2) {
                            // Offset x0 by 1/80 of a pixel. Use something
                            // that can be represented in binary
                            if (clockwise) {
                                x0 += 270 / Z;
                            }
                        }
                        else {
                            // Avoid case draw full circle
                            if (Math.abs(y0 - cy) < 1e-4) {
                                if ((clockwise && x0 < cx) || (!clockwise && x0 > cx)) {
                                    y1 -= 270 / Z;
                                }
                                else {
                                    y1 += 270 / Z;
                                }
                            }
                            else if ((clockwise && y0 < cy) || (!clockwise && y0 > cy)) {
                                x1 += 270 / Z;
                            }
                            else {
                                x1 -= 270 / Z;
                            }
                        }
                    }
                    str.push(
                        type,
                        round$3(((cx - rx) * sx + x) * Z - Z2), comma,
                        round$3(((cy - ry) * sy + y) * Z - Z2), comma,
                        round$3(((cx + rx) * sx + x) * Z - Z2), comma,
                        round$3(((cy + ry) * sy + y) * Z - Z2), comma,
                        round$3((x0 * sx + x) * Z - Z2), comma,
                        round$3((y0 * sy + y) * Z - Z2), comma,
                        round$3((x1 * sx + x) * Z - Z2), comma,
                        round$3((y1 * sy + y) * Z - Z2)
                    );

                    xi = x1;
                    yi = y1;
                    break;
                case CMD$3.R:
                    var p0 = points$3[0];
                    var p1 = points$3[1];
                    // x0, y0
                    p0[0] = data[i++];
                    p0[1] = data[i++];
                    // x1, y1
                    p1[0] = p0[0] + data[i++];
                    p1[1] = p0[1] + data[i++];

                    if (m) {
                        applyTransform(p0, p0, m);
                        applyTransform(p1, p1, m);
                    }

                    p0[0] = round$3(p0[0] * Z - Z2);
                    p1[0] = round$3(p1[0] * Z - Z2);
                    p0[1] = round$3(p0[1] * Z - Z2);
                    p1[1] = round$3(p1[1] * Z - Z2);
                    str.push(
                        // x0, y0
                        ' m ', p0[0], comma, p0[1],
                        // x1, y0
                        ' l ', p1[0], comma, p0[1],
                        // x1, y1
                        ' l ', p1[0], comma, p1[1],
                        // x0, y1
                        ' l ', p0[0], comma, p1[1]
                    );
                    break;
                case CMD$3.Z:
                    // FIXME Update xi, yi
                    str.push(' x ');
            }

            if (nPoint > 0) {
                str.push(cmdStr);
                for (var k = 0; k < nPoint; k++) {
                    var p = points$3[k];

                    m && applyTransform(p, p, m);
                    // 不 round 会非常慢
                    str.push(
                        round$3(p[0] * Z - Z2), comma, round$3(p[1] * Z - Z2),
                        k < nPoint - 1 ? comma : ''
                    );
                }
            }
        }

        return str.join('');
    };

    // Rewrite the original path method
    Path.prototype.brushVML = function (vmlRoot) {
        var style = this.style;

        var vmlEl = this._vmlEl;
        if (!vmlEl) {
            vmlEl = createNode('shape');
            initRootElStyle(vmlEl);

            this._vmlEl = vmlEl;
        }

        updateFillAndStroke(vmlEl, 'fill', style, this);
        updateFillAndStroke(vmlEl, 'stroke', style, this);

        var m = this.transform;
        var needTransform = m != null;
        var strokeEl = vmlEl.getElementsByTagName('stroke')[0];
        if (strokeEl) {
            var lineWidth = style.lineWidth;
            // Get the line scale.
            // Determinant of this.m_ means how much the area is enlarged by the
            // transformation. So its square root can be used as a scale factor
            // for width.
            if (needTransform && !style.strokeNoScale) {
                var det = m[0] * m[3] - m[1] * m[2];
                lineWidth *= sqrt(abs$1(det));
            }
            strokeEl.weight = lineWidth + 'px';
        }

        var path = this.path || (this.path = new PathProxy());
        if (this.__dirtyPath) {
            path.beginPath();
            path.subPixelOptimize = false;
            this.buildPath(path, this.shape);
            path.toStatic();
            this.__dirtyPath = false;
        }

        vmlEl.path = pathDataToString(path, this.transform);

        vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);

        // Append to root
        append(vmlRoot, vmlEl);

        // Text
        if (style.text != null) {
            this.drawRectText(vmlRoot, this.getBoundingRect());
        }
        else {
            this.removeRectText(vmlRoot);
        }
    };

    Path.prototype.onRemove = function (vmlRoot) {
        remove(vmlRoot, this._vmlEl);
        this.removeRectText(vmlRoot);
    };

    Path.prototype.onAdd = function (vmlRoot) {
        append(vmlRoot, this._vmlEl);
        this.appendRectText(vmlRoot);
    };

    /***************************************************
     * IMAGE
     **************************************************/
    var isImage = function (img) {
        // FIXME img instanceof Image 如果 img 是一个字符串的时候，IE8 下会报错
        return (typeof img === 'object') && img.tagName && img.tagName.toUpperCase() === 'IMG';
        // return img instanceof Image;
    };

    // Rewrite the original path method
    ZImage.prototype.brushVML = function (vmlRoot) {
        var style = this.style;
        var image = style.image;

        // Image original width, height
        var ow;
        var oh;

        if (isImage(image)) {
            var src = image.src;
            if (src === this._imageSrc) {
                ow = this._imageWidth;
                oh = this._imageHeight;
            }
            else {
                var imageRuntimeStyle = image.runtimeStyle;
                var oldRuntimeWidth = imageRuntimeStyle.width;
                var oldRuntimeHeight = imageRuntimeStyle.height;
                imageRuntimeStyle.width = 'auto';
                imageRuntimeStyle.height = 'auto';

                // get the original size
                ow = image.width;
                oh = image.height;

                // and remove overides
                imageRuntimeStyle.width = oldRuntimeWidth;
                imageRuntimeStyle.height = oldRuntimeHeight;

                // Caching image original width, height and src
                this._imageSrc = src;
                this._imageWidth = ow;
                this._imageHeight = oh;
            }
            image = src;
        }
        else {
            if (image === this._imageSrc) {
                ow = this._imageWidth;
                oh = this._imageHeight;
            }
        }
        if (!image) {
            return;
        }

        var x = style.x || 0;
        var y = style.y || 0;

        var dw = style.width;
        var dh = style.height;

        var sw = style.sWidth;
        var sh = style.sHeight;
        var sx = style.sx || 0;
        var sy = style.sy || 0;

        var hasCrop = sw && sh;

        var vmlEl = this._vmlEl;
        if (!vmlEl) {
            // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。
            // vmlEl = vmlCore.createNode('group');
            vmlEl = doc.createElement('div');
            initRootElStyle(vmlEl);

            this._vmlEl = vmlEl;
        }

        var vmlElStyle = vmlEl.style;
        var hasRotation = false;
        var m;
        var scaleX = 1;
        var scaleY = 1;
        if (this.transform) {
            m = this.transform;
            scaleX = sqrt(m[0] * m[0] + m[1] * m[1]);
            scaleY = sqrt(m[2] * m[2] + m[3] * m[3]);

            hasRotation = m[1] || m[2];
        }
        if (hasRotation) {
            // If filters are necessary (rotation exists), create them
            // filters are bog-slow, so only create them if abbsolutely necessary
            // The following check doesn't account for skews (which don't exist
            // in the canvas spec (yet) anyway.
            // From excanvas
            var p0 = [x, y];
            var p1 = [x + dw, y];
            var p2 = [x, y + dh];
            var p3 = [x + dw, y + dh];
            applyTransform(p0, p0, m);
            applyTransform(p1, p1, m);
            applyTransform(p2, p2, m);
            applyTransform(p3, p3, m);

            var maxX = mathMax$9(p0[0], p1[0], p2[0], p3[0]);
            var maxY = mathMax$9(p0[1], p1[1], p2[1], p3[1]);

            var transformFilter = [];
            transformFilter.push('M11=', m[0] / scaleX, comma,
                        'M12=', m[2] / scaleY, comma,
                        'M21=', m[1] / scaleX, comma,
                        'M22=', m[3] / scaleY, comma,
                        'Dx=', round$3(x * scaleX + m[4]), comma,
                        'Dy=', round$3(y * scaleY + m[5]));

            vmlElStyle.padding = '0 ' + round$3(maxX) + 'px ' + round$3(maxY) + 'px 0';
            // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用
            vmlElStyle.filter = imageTransformPrefix + '.Matrix('
                + transformFilter.join('') + ', SizingMethod=clip)';

        }
        else {
            if (m) {
                x = x * scaleX + m[4];
                y = y * scaleY + m[5];
            }
            vmlElStyle.filter = '';
            vmlElStyle.left = round$3(x) + 'px';
            vmlElStyle.top = round$3(y) + 'px';
        }

        var imageEl = this._imageEl;
        var cropEl = this._cropEl;

        if (!imageEl) {
            imageEl = doc.createElement('div');
            this._imageEl = imageEl;
        }
        var imageELStyle = imageEl.style;
        if (hasCrop) {
            // Needs know image original width and height
            if (!(ow && oh)) {
                var tmpImage = new Image();
                var self = this;
                tmpImage.onload = function () {
                    tmpImage.onload = null;
                    ow = tmpImage.width;
                    oh = tmpImage.height;
                    // Adjust image width and height to fit the ratio destinationSize / sourceSize
                    imageELStyle.width = round$3(scaleX * ow * dw / sw) + 'px';
                    imageELStyle.height = round$3(scaleY * oh * dh / sh) + 'px';

                    // Caching image original width, height and src
                    self._imageWidth = ow;
                    self._imageHeight = oh;
                    self._imageSrc = image;
                };
                tmpImage.src = image;
            }
            else {
                imageELStyle.width = round$3(scaleX * ow * dw / sw) + 'px';
                imageELStyle.height = round$3(scaleY * oh * dh / sh) + 'px';
            }

            if (!cropEl) {
                cropEl = doc.createElement('div');
                cropEl.style.overflow = 'hidden';
                this._cropEl = cropEl;
            }
            var cropElStyle = cropEl.style;
            cropElStyle.width = round$3((dw + sx * dw / sw) * scaleX);
            cropElStyle.height = round$3((dh + sy * dh / sh) * scaleY);
            cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx='
                    + (-sx * dw / sw * scaleX) + ',Dy=' + (-sy * dh / sh * scaleY) + ')';

            if (!cropEl.parentNode) {
                vmlEl.appendChild(cropEl);
            }
            if (imageEl.parentNode !== cropEl) {
                cropEl.appendChild(imageEl);
            }
        }
        else {
            imageELStyle.width = round$3(scaleX * dw) + 'px';
            imageELStyle.height = round$3(scaleY * dh) + 'px';

            vmlEl.appendChild(imageEl);

            if (cropEl && cropEl.parentNode) {
                vmlEl.removeChild(cropEl);
                this._cropEl = null;
            }
        }

        var filterStr = '';
        var alpha = style.opacity;
        if (alpha < 1) {
            filterStr += '.Alpha(opacity=' + round$3(alpha * 100) + ') ';
        }
        filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)';

        imageELStyle.filter = filterStr;

        vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);

        // Append to root
        append(vmlRoot, vmlEl);

        // Text
        if (style.text != null) {
            this.drawRectText(vmlRoot, this.getBoundingRect());
        }
    };

    ZImage.prototype.onRemove = function (vmlRoot) {
        remove(vmlRoot, this._vmlEl);

        this._vmlEl = null;
        this._cropEl = null;
        this._imageEl = null;

        this.removeRectText(vmlRoot);
    };

    ZImage.prototype.onAdd = function (vmlRoot) {
        append(vmlRoot, this._vmlEl);
        this.appendRectText(vmlRoot);
    };


    /***************************************************
     * TEXT
     **************************************************/

    var DEFAULT_STYLE_NORMAL = 'normal';

    var fontStyleCache = {};
    var fontStyleCacheCount = 0;
    var MAX_FONT_CACHE_SIZE = 100;
    var fontEl = document.createElement('div');

    var getFontStyle = function (fontString) {
        var fontStyle = fontStyleCache[fontString];
        if (!fontStyle) {
            // Clear cache
            if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) {
                fontStyleCacheCount = 0;
                fontStyleCache = {};
            }

            var style = fontEl.style;
            var fontFamily;
            try {
                style.font = fontString;
                fontFamily = style.fontFamily.split(',')[0];
            }
            catch (e) {
            }

            fontStyle = {
                style: style.fontStyle || DEFAULT_STYLE_NORMAL,
                variant: style.fontVariant || DEFAULT_STYLE_NORMAL,
                weight: style.fontWeight || DEFAULT_STYLE_NORMAL,
                size: parseFloat(style.fontSize || 12) | 0,
                family: fontFamily || 'Microsoft YaHei'
            };

            fontStyleCache[fontString] = fontStyle;
            fontStyleCacheCount++;
        }
        return fontStyle;
    };

    var textMeasureEl;
    // Overwrite measure text method
    $override$1('measureText', function (text, textFont) {
        var doc$$1 = doc;
        if (!textMeasureEl) {
            textMeasureEl = doc$$1.createElement('div');
            textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;'
                + 'padding:0;margin:0;border:none;white-space:pre;';
            doc.body.appendChild(textMeasureEl);
        }

        try {
            textMeasureEl.style.font = textFont;
        }
        catch (ex) {
            // Ignore failures to set to invalid font.
        }
        textMeasureEl.innerHTML = '';
        // Don't use innerHTML or innerText because they allow markup/whitespace.
        textMeasureEl.appendChild(doc$$1.createTextNode(text));
        return {
            width: textMeasureEl.offsetWidth
        };
    });

    var tmpRect$2 = new BoundingRect();

    var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) {

        var style = this.style;

        // Optimize, avoid normalize every time.
        this.__dirty && normalizeTextStyle(style, true);

        var text = style.text;
        // Convert to string
        text != null && (text += '');
        if (!text) {
            return;
        }

        // Convert rich text to plain text. Rich text is not supported in
        // IE8-, but tags in rich text template will be removed.
        if (style.rich) {
            var contentBlock = parseRichText(text, style);
            text = [];
            for (var i = 0; i < contentBlock.lines.length; i++) {
                var tokens = contentBlock.lines[i].tokens;
                var textLine = [];
                for (var j = 0; j < tokens.length; j++) {
                    textLine.push(tokens[j].text);
                }
                text.push(textLine.join(''));
            }
            text = text.join('\n');
        }

        var x;
        var y;
        var align = style.textAlign;
        var verticalAlign = style.textVerticalAlign;

        var fontStyle = getFontStyle(style.font);
        // FIXME encodeHtmlAttribute ?
        var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' '
            + fontStyle.size + 'px "' + fontStyle.family + '"';

        textRect = textRect || getBoundingRect(
            text, font, align, verticalAlign, style.textPadding, style.textLineHeight
        );

        // Transform rect to view space
        var m = this.transform;
        // Ignore transform for text in other element
        if (m && !fromTextEl) {
            tmpRect$2.copy(rect);
            tmpRect$2.applyTransform(m);
            rect = tmpRect$2;
        }

        if (!fromTextEl) {
            var textPosition = style.textPosition;
            // Text position represented by coord
            if (textPosition instanceof Array) {
                x = rect.x + parsePercent$3(textPosition[0], rect.width);
                y = rect.y + parsePercent$3(textPosition[1], rect.height);

                align = align || 'left';
            }
            else {
                var res = this.calculateTextPosition
                    ? this.calculateTextPosition({}, style, rect)
                    : calculateTextPosition({}, style, rect);
                x = res.x;
                y = res.y;

                // Default align and baseline when has textPosition
                align = align || res.textAlign;
                verticalAlign = verticalAlign || res.textVerticalAlign;
            }
        }
        else {
            x = rect.x;
            y = rect.y;
        }

        x = adjustTextX(x, textRect.width, align);
        y = adjustTextY(y, textRect.height, verticalAlign);

        // Force baseline 'middle'
        y += textRect.height / 2;

        // var fontSize = fontStyle.size;
        // 1.75 is an arbitrary number, as there is no info about the text baseline
        // switch (baseline) {
            // case 'hanging':
            // case 'top':
            //     y += fontSize / 1.75;
            //     break;
        //     case 'middle':
        //         break;
        //     default:
        //     // case null:
        //     // case 'alphabetic':
        //     // case 'ideographic':
        //     // case 'bottom':
        //         y -= fontSize / 2.25;
        //         break;
        // }

        // switch (align) {
        //     case 'left':
        //         break;
        //     case 'center':
        //         x -= textRect.width / 2;
        //         break;
        //     case 'right':
        //         x -= textRect.width;
        //         break;
            // case 'end':
                // align = elementStyle.direction == 'ltr' ? 'right' : 'left';
                // break;
            // case 'start':
                // align = elementStyle.direction == 'rtl' ? 'right' : 'left';
                // break;
            // default:
            //     align = 'left';
        // }

        var createNode$$1 = createNode;

        var textVmlEl = this._textVmlEl;
        var pathEl;
        var textPathEl;
        var skewEl;
        if (!textVmlEl) {
            textVmlEl = createNode$$1('line');
            pathEl = createNode$$1('path');
            textPathEl = createNode$$1('textpath');
            skewEl = createNode$$1('skew');

            // FIXME Why here is not cammel case
            // Align 'center' seems wrong
            textPathEl.style['v-text-align'] = 'left';

            initRootElStyle(textVmlEl);

            pathEl.textpathok = true;
            textPathEl.on = true;

            textVmlEl.from = '0 0';
            textVmlEl.to = '1000 0.05';

            append(textVmlEl, skewEl);
            append(textVmlEl, pathEl);
            append(textVmlEl, textPathEl);

            this._textVmlEl = textVmlEl;
        }
        else {
            // 这里是在前面 appendChild 保证顺序的前提下
            skewEl = textVmlEl.firstChild;
            pathEl = skewEl.nextSibling;
            textPathEl = pathEl.nextSibling;
        }

        var coords = [x, y];
        var textVmlElStyle = textVmlEl.style;
        // Ignore transform for text in other element
        if (m && fromTextEl) {
            applyTransform(coords, coords, m);

            skewEl.on = true;

            skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma
                            + m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0';

            // Text position
            skewEl.offset = (round$3(coords[0]) || 0) + ',' + (round$3(coords[1]) || 0);
            // Left top point as origin
            skewEl.origin = '0 0';

            textVmlElStyle.left = '0px';
            textVmlElStyle.top = '0px';
        }
        else {
            skewEl.on = false;
            textVmlElStyle.left = round$3(x) + 'px';
            textVmlElStyle.top = round$3(y) + 'px';
        }

        textPathEl.string = encodeHtmlAttribute(text);
        // TODO
        try {
            textPathEl.style.font = font;
        }
        // Error font format
        catch (e) {}

        updateFillAndStroke(textVmlEl, 'fill', {
            fill: style.textFill,
            opacity: style.opacity
        }, this);
        updateFillAndStroke(textVmlEl, 'stroke', {
            stroke: style.textStroke,
            opacity: style.opacity,
            lineDash: style.lineDash || null // style.lineDash can be `false`.
        }, this);

        textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);

        // Attached to root
        append(vmlRoot, textVmlEl);
    };

    var removeRectText = function (vmlRoot) {
        remove(vmlRoot, this._textVmlEl);
        this._textVmlEl = null;
    };

    var appendRectText = function (vmlRoot) {
        append(vmlRoot, this._textVmlEl);
    };

    var list = [RectText, Displayable, ZImage, Path, Text];

    // In case Displayable has been mixed in RectText
    for (var i$3 = 0; i$3 < list.length; i$3++) {
        var proto$8 = list[i$3].prototype;
        proto$8.drawRectText = drawRectText;
        proto$8.removeRectText = removeRectText;
        proto$8.appendRectText = appendRectText;
    }

    Text.prototype.brushVML = function (vmlRoot) {
        var style = this.style;
        if (style.text != null) {
            this.drawRectText(vmlRoot, {
                x: style.x || 0, y: style.y || 0,
                width: 0, height: 0
            }, this.getBoundingRect(), true);
        }
        else {
            this.removeRectText(vmlRoot);
        }
    };

    Text.prototype.onRemove = function (vmlRoot) {
        this.removeRectText(vmlRoot);
    };

    Text.prototype.onAdd = function (vmlRoot) {
        this.appendRectText(vmlRoot);
    };
}

/**
 * VML Painter.
 *
 * @module zrender/vml/Painter
 */

function parseInt10$1(val) {
    return parseInt(val, 10);
}

/**
 * @alias module:zrender/vml/Painter
 */
function VMLPainter(root, storage) {

    initVML();

    this.root = root;

    this.storage = storage;

    var vmlViewport = document.createElement('div');

    var vmlRoot = document.createElement('div');

    vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;';

    vmlRoot.style.cssText = 'position:absolute;left:0;top:0;';

    root.appendChild(vmlViewport);

    this._vmlRoot = vmlRoot;
    this._vmlViewport = vmlViewport;

    this.resize();

    // Modify storage
    var oldDelFromStorage = storage.delFromStorage;
    var oldAddToStorage = storage.addToStorage;
    storage.delFromStorage = function (el) {
        oldDelFromStorage.call(storage, el);

        if (el) {
            el.onRemove && el.onRemove(vmlRoot);
        }
    };

    storage.addToStorage = function (el) {
        // Displayable already has a vml node
        el.onAdd && el.onAdd(vmlRoot);

        oldAddToStorage.call(storage, el);
    };

    this._firstPaint = true;
}

VMLPainter.prototype = {

    constructor: VMLPainter,

    getType: function () {
        return 'vml';
    },

    /**
     * @return {HTMLDivElement}
     */
    getViewportRoot: function () {
        return this._vmlViewport;
    },

    getViewportRootOffset: function () {
        var viewportRoot = this.getViewportRoot();
        if (viewportRoot) {
            return {
                offsetLeft: viewportRoot.offsetLeft || 0,
                offsetTop: viewportRoot.offsetTop || 0
            };
        }
    },

    /**
     * 刷新
     */
    refresh: function () {

        var list = this.storage.getDisplayList(true, true);

        this._paintList(list);
    },

    _paintList: function (list) {
        var vmlRoot = this._vmlRoot;
        for (var i = 0; i < list.length; i++) {
            var el = list[i];
            if (el.invisible || el.ignore) {
                if (!el.__alreadyNotVisible) {
                    el.onRemove(vmlRoot);
                }
                // Set as already invisible
                el.__alreadyNotVisible = true;
            }
            else {
                if (el.__alreadyNotVisible) {
                    el.onAdd(vmlRoot);
                }
                el.__alreadyNotVisible = false;
                if (el.__dirty) {
                    el.beforeBrush && el.beforeBrush();
                    (el.brushVML || el.brush).call(el, vmlRoot);
                    el.afterBrush && el.afterBrush();
                }
            }
            el.__dirty = false;
        }

        if (this._firstPaint) {
            // Detached from document at first time
            // to avoid page refreshing too many times

            // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变
            this._vmlViewport.appendChild(vmlRoot);
            this._firstPaint = false;
        }
    },

    resize: function (width, height) {
        var width = width == null ? this._getWidth() : width;
        var height = height == null ? this._getHeight() : height;

        if (this._width !== width || this._height !== height) {
            this._width = width;
            this._height = height;

            var vmlViewportStyle = this._vmlViewport.style;
            vmlViewportStyle.width = width + 'px';
            vmlViewportStyle.height = height + 'px';
        }
    },

    dispose: function () {
        this.root.innerHTML = '';

        this._vmlRoot =
        this._vmlViewport =
        this.storage = null;
    },

    getWidth: function () {
        return this._width;
    },

    getHeight: function () {
        return this._height;
    },

    clear: function () {
        if (this._vmlViewport) {
            this.root.removeChild(this._vmlViewport);
        }
    },

    _getWidth: function () {
        var root = this.root;
        var stl = root.currentStyle;

        return ((root.clientWidth || parseInt10$1(stl.width))
                - parseInt10$1(stl.paddingLeft)
                - parseInt10$1(stl.paddingRight)) | 0;
    },

    _getHeight: function () {
        var root = this.root;
        var stl = root.currentStyle;

        return ((root.clientHeight || parseInt10$1(stl.height))
                - parseInt10$1(stl.paddingTop)
                - parseInt10$1(stl.paddingBottom)) | 0;
    }
};

// Not supported methods
function createMethodNotSupport(method) {
    return function () {
        logError$1('In IE8.0 VML mode painter not support method "' + method + '"');
    };
}

// Unsupported methods
each$1([
    'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers',
    'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage'
], function (name) {
    VMLPainter.prototype[name] = createMethodNotSupport(name);
});

registerPainter('vml', VMLPainter);

var svgURI = 'http://www.w3.org/2000/svg';

function createElement(name) {
    return document.createElementNS(svgURI, name);
}

// TODO
// 1. shadow
// 2. Image: sx, sy, sw, sh

var CMD$4 = PathProxy.CMD;
var arrayJoin = Array.prototype.join;

var NONE = 'none';
var mathRound = Math.round;
var mathSin$3 = Math.sin;
var mathCos$3 = Math.cos;
var PI$6 = Math.PI;
var PI2$6 = Math.PI * 2;
var degree = 180 / PI$6;

var EPSILON$4 = 1e-4;

function round4(val) {
    return mathRound(val * 1e4) / 1e4;
}

function isAroundZero$1(val) {
    return val < EPSILON$4 && val > -EPSILON$4;
}

function pathHasFill(style, isText) {
    var fill = isText ? style.textFill : style.fill;
    return fill != null && fill !== NONE;
}

function pathHasStroke(style, isText) {
    var stroke = isText ? style.textStroke : style.stroke;
    return stroke != null && stroke !== NONE;
}

function setTransform(svgEl, m) {
    if (m) {
        attr(svgEl, 'transform', 'matrix(' + arrayJoin.call(m, ',') + ')');
    }
}

function attr(el, key, val) {
    if (!val || val.type !== 'linear' && val.type !== 'radial') {
        // Don't set attribute for gradient, since it need new dom nodes
        el.setAttribute(key, val);
    }
}

function attrXLink(el, key, val) {
    el.setAttributeNS('http://www.w3.org/1999/xlink', key, val);
}

function bindStyle(svgEl, style, isText, el) {
    if (pathHasFill(style, isText)) {
        var fill = isText ? style.textFill : style.fill;
        fill = fill === 'transparent' ? NONE : fill;
        attr(svgEl, 'fill', fill);
        attr(svgEl, 'fill-opacity', style.fillOpacity != null ? style.fillOpacity * style.opacity : style.opacity);
    }
    else {
        attr(svgEl, 'fill', NONE);
    }

    if (pathHasStroke(style, isText)) {
        var stroke = isText ? style.textStroke : style.stroke;
        stroke = stroke === 'transparent' ? NONE : stroke;
        attr(svgEl, 'stroke', stroke);
        var strokeWidth = isText
            ? style.textStrokeWidth
            : style.lineWidth;
        var strokeScale = !isText && style.strokeNoScale
            ? el.getLineScale()
            : 1;
        attr(svgEl, 'stroke-width', strokeWidth / strokeScale);
        // stroke then fill for text; fill then stroke for others
        attr(svgEl, 'paint-order', isText ? 'stroke' : 'fill');
        attr(svgEl, 'stroke-opacity', style.strokeOpacity != null ? style.strokeOpacity : style.opacity);
        var lineDash = style.lineDash;
        if (lineDash) {
            attr(svgEl, 'stroke-dasharray', style.lineDash.join(','));
            attr(svgEl, 'stroke-dashoffset', mathRound(style.lineDashOffset || 0));
        }
        else {
            attr(svgEl, 'stroke-dasharray', '');
        }

        // PENDING
        style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap);
        style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin);
        style.miterLimit && attr(svgEl, 'stroke-miterlimit', style.miterLimit);
    }
    else {
        attr(svgEl, 'stroke', NONE);
    }
}

/***************************************************
 * PATH
 **************************************************/
function pathDataToString$1(path) {
    var str = [];
    var data = path.data;
    var dataLength = path.len();
    for (var i = 0; i < dataLength;) {
        var cmd = data[i++];
        var cmdStr = '';
        var nData = 0;
        switch (cmd) {
            case CMD$4.M:
                cmdStr = 'M';
                nData = 2;
                break;
            case CMD$4.L:
                cmdStr = 'L';
                nData = 2;
                break;
            case CMD$4.Q:
                cmdStr = 'Q';
                nData = 4;
                break;
            case CMD$4.C:
                cmdStr = 'C';
                nData = 6;
                break;
            case CMD$4.A:
                var cx = data[i++];
                var cy = data[i++];
                var rx = data[i++];
                var ry = data[i++];
                var theta = data[i++];
                var dTheta = data[i++];
                var psi = data[i++];
                var clockwise = data[i++];

                var dThetaPositive = Math.abs(dTheta);
                var isCircle = isAroundZero$1(dThetaPositive - PI2$6)
                    || (clockwise ? dTheta >= PI2$6 : -dTheta >= PI2$6);

                // Mapping to 0~2PI
                var unifiedTheta = dTheta > 0 ? dTheta % PI2$6 : (dTheta % PI2$6 + PI2$6);

                var large = false;
                if (isCircle) {
                    large = true;
                }
                else if (isAroundZero$1(dThetaPositive)) {
                    large = false;
                }
                else {
                    large = (unifiedTheta >= PI$6) === !!clockwise;
                }

                var x0 = round4(cx + rx * mathCos$3(theta));
                var y0 = round4(cy + ry * mathSin$3(theta));

                // It will not draw if start point and end point are exactly the same
                // We need to shift the end point with a small value
                // FIXME A better way to draw circle ?
                if (isCircle) {
                    if (clockwise) {
                        dTheta = PI2$6 - 1e-4;
                    }
                    else {
                        dTheta = -PI2$6 + 1e-4;
                    }

                    large = true;

                    if (i === 9) {
                        // Move to (x0, y0) only when CMD.A comes at the
                        // first position of a shape.
                        // For instance, when drawing a ring, CMD.A comes
                        // after CMD.M, so it's unnecessary to move to
                        // (x0, y0).
                        str.push('M', x0, y0);
                    }
                }

                var x = round4(cx + rx * mathCos$3(theta + dTheta));
                var y = round4(cy + ry * mathSin$3(theta + dTheta));

                // FIXME Ellipse
                str.push('A', round4(rx), round4(ry),
                    mathRound(psi * degree), +large, +clockwise, x, y);
                break;
            case CMD$4.Z:
                cmdStr = 'Z';
                break;
            case CMD$4.R:
                var x = round4(data[i++]);
                var y = round4(data[i++]);
                var w = round4(data[i++]);
                var h = round4(data[i++]);
                str.push(
                    'M', x, y,
                    'L', x + w, y,
                    'L', x + w, y + h,
                    'L', x, y + h,
                    'L', x, y
                );
                break;
        }
        cmdStr && str.push(cmdStr);
        for (var j = 0; j < nData; j++) {
            // PENDING With scale
            str.push(round4(data[i++]));
        }
    }
    return str.join(' ');
}

var svgPath = {};
svgPath.brush = function (el) {
    var style = el.style;

    var svgEl = el.__svgEl;
    if (!svgEl) {
        svgEl = createElement('path');
        el.__svgEl = svgEl;
    }

    if (!el.path) {
        el.createPathProxy();
    }
    var path = el.path;

    if (el.__dirtyPath) {
        path.beginPath();
        path.subPixelOptimize = false;
        el.buildPath(path, el.shape);
        el.__dirtyPath = false;

        var pathStr = pathDataToString$1(path);
        if (pathStr.indexOf('NaN') < 0) {
            // Ignore illegal path, which may happen such in out-of-range
            // data in Calendar series.
            attr(svgEl, 'd', pathStr);
        }
    }

    bindStyle(svgEl, style, false, el);
    setTransform(svgEl, el.transform);

    if (style.text != null) {
        svgTextDrawRectText(el, el.getBoundingRect());
    }
};

/***************************************************
 * IMAGE
 **************************************************/
var svgImage = {};
svgImage.brush = function (el) {
    var style = el.style;
    var image = style.image;

    if (image instanceof HTMLImageElement) {
        var src = image.src;
        image = src;
    }
    if (!image) {
        return;
    }

    var x = style.x || 0;
    var y = style.y || 0;

    var dw = style.width;
    var dh = style.height;

    var svgEl = el.__svgEl;
    if (!svgEl) {
        svgEl = createElement('image');
        el.__svgEl = svgEl;
    }

    if (image !== el.__imageSrc) {
        attrXLink(svgEl, 'href', image);
        // Caching image src
        el.__imageSrc = image;
    }

    attr(svgEl, 'width', dw);
    attr(svgEl, 'height', dh);

    attr(svgEl, 'x', x);
    attr(svgEl, 'y', y);

    setTransform(svgEl, el.transform);

    if (style.text != null) {
        svgTextDrawRectText(el, el.getBoundingRect());
    }
};

/***************************************************
 * TEXT
 **************************************************/
var svgText = {};
var _tmpTextHostRect = new BoundingRect();
var _tmpTextBoxPos = {};
var _tmpTextTransform = [];
var TEXT_ALIGN_TO_ANCHRO = {
    left: 'start',
    right: 'end',
    center: 'middle',
    middle: 'middle'
};

/**
 * @param {module:zrender/Element} el
 * @param {Object|boolean} [hostRect] {x, y, width, height}
 *        If set false, rect text is not used.
 */
var svgTextDrawRectText = function (el, hostRect) {
    var style = el.style;
    var elTransform = el.transform;
    var needTransformTextByHostEl = el instanceof Text || style.transformText;

    el.__dirty && normalizeTextStyle(style, true);

    var text = style.text;
    // Convert to string
    text != null && (text += '');
    if (!needDrawText(text, style)) {
        return;
    }
    // render empty text for svg if no text but need draw text.
    text == null && (text = '');

    // Follow the setting in the canvas renderer, if not transform the
    // text, transform the hostRect, by which the text is located.
    if (!needTransformTextByHostEl && elTransform) {
        _tmpTextHostRect.copy(hostRect);
        _tmpTextHostRect.applyTransform(elTransform);
        hostRect = _tmpTextHostRect;
    }

    var textSvgEl = el.__textSvgEl;
    if (!textSvgEl) {
        textSvgEl = createElement('text');
        el.__textSvgEl = textSvgEl;
    }

    // style.font has been normalized by `normalizeTextStyle`.
    var textSvgElStyle = textSvgEl.style;
    var font = style.font || DEFAULT_FONT$1;
    var computedFont = textSvgEl.__computedFont;
    if (font !== textSvgEl.__styleFont) {
        textSvgElStyle.font = textSvgEl.__styleFont = font;
        // The computedFont might not be the orginal font if it is illegal font.
        computedFont = textSvgEl.__computedFont = textSvgElStyle.font;
    }

    var textPadding = style.textPadding;
    var textLineHeight = style.textLineHeight;

    var contentBlock = el.__textCotentBlock;
    if (!contentBlock || el.__dirtyText) {
        contentBlock = el.__textCotentBlock = parsePlainText(
            text, computedFont, textPadding, textLineHeight, style.truncate
        );
    }

    var outerHeight = contentBlock.outerHeight;
    var lineHeight = contentBlock.lineHeight;

    getBoxPosition(_tmpTextBoxPos, el, style, hostRect);
    var baseX = _tmpTextBoxPos.baseX;
    var baseY = _tmpTextBoxPos.baseY;
    var textAlign = _tmpTextBoxPos.textAlign || 'left';
    var textVerticalAlign = _tmpTextBoxPos.textVerticalAlign;

    setTextTransform(
        textSvgEl, needTransformTextByHostEl, elTransform, style, hostRect, baseX, baseY
    );

    var boxY = adjustTextY(baseY, outerHeight, textVerticalAlign);
    var textX = baseX;
    var textY = boxY;

    // TODO needDrawBg
    if (textPadding) {
        textX = getTextXForPadding$1(baseX, textAlign, textPadding);
        textY += textPadding[0];
    }

    // `textBaseline` is set as 'middle'.
    textY += lineHeight / 2;

    bindStyle(textSvgEl, style, true, el);

    // FIXME
    // Add a <style> to reset all of the text font as inherit?
    // otherwise the outer <style> may set the unexpected style.

    // Font may affect position of each tspan elements
    var canCacheByTextString = contentBlock.canCacheByTextString;
    var tspanList = el.__tspanList || (el.__tspanList = []);
    var tspanOriginLen = tspanList.length;

    // Optimize for most cases, just compare text string to determine change.
    if (canCacheByTextString && el.__canCacheByTextString && el.__text === text) {
        if (el.__dirtyText && tspanOriginLen) {
            for (var idx = 0; idx < tspanOriginLen; ++idx) {
                updateTextLocation(tspanList[idx], textAlign, textX, textY + idx * lineHeight);
            }
        }
    }
    else {
        el.__text = text;
        el.__canCacheByTextString = canCacheByTextString;
        var textLines = contentBlock.lines;
        var nTextLines = textLines.length;

        var idx = 0;
        for (; idx < nTextLines; idx++) {
            // Using cached tspan elements
            var tspan = tspanList[idx];
            var singleLineText = textLines[idx];

            if (!tspan) {
                tspan = tspanList[idx] = createElement('tspan');
                textSvgEl.appendChild(tspan);
                tspan.appendChild(document.createTextNode(singleLineText));
            }
            else if (tspan.__zrText !== singleLineText) {
                tspan.innerHTML = '';
                tspan.appendChild(document.createTextNode(singleLineText));
            }
            updateTextLocation(tspan, textAlign, textX, textY + idx * lineHeight);
        }
        // Remove unused tspan elements
        if (tspanOriginLen > nTextLines) {
            for (; idx < tspanOriginLen; idx++) {
                textSvgEl.removeChild(tspanList[idx]);
            }
            tspanList.length = nTextLines;
        }
    }
};

function setTextTransform(textSvgEl, needTransformTextByHostEl, elTransform, style, hostRect, baseX, baseY) {
    identity(_tmpTextTransform);

    if (needTransformTextByHostEl && elTransform) {
        copy$1(_tmpTextTransform, elTransform);
    }

    // textRotation only apply in RectText.
    var textRotation = style.textRotation;
    if (hostRect && textRotation) {
        var origin = style.textOrigin;
        if (origin === 'center') {
            baseX = hostRect.width / 2 + hostRect.x;
            baseY = hostRect.height / 2 + hostRect.y;
        }
        else if (origin) {
            baseX = origin[0] + hostRect.x;
            baseY = origin[1] + hostRect.y;
        }

        _tmpTextTransform[4] -= baseX;
        _tmpTextTransform[5] -= baseY;
        // Positive: anticlockwise
        rotate(_tmpTextTransform, _tmpTextTransform, textRotation);
        _tmpTextTransform[4] += baseX;
        _tmpTextTransform[5] += baseY;
    }
    // See the definition in `Style.js#textOrigin`, the default
    // origin is from the result of `getBoxPosition`.

    setTransform(textSvgEl, _tmpTextTransform);
}

// FIXME merge the same code with `helper/text.js#getTextXForPadding`;
function getTextXForPadding$1(x, textAlign, textPadding) {
    return textAlign === 'right'
        ? (x - textPadding[1])
        : textAlign === 'center'
        ? (x + textPadding[3] / 2 - textPadding[1] / 2)
        : (x + textPadding[3]);
}

function updateTextLocation(tspan, textAlign, x, y) {
    // Consider different font display differently in vertial align, we always
    // set vertialAlign as 'middle', and use 'y' to locate text vertically.
    attr(tspan, 'dominant-baseline', 'middle');
    attr(tspan, 'text-anchor', TEXT_ALIGN_TO_ANCHRO[textAlign]);
    attr(tspan, 'x', x);
    attr(tspan, 'y', y);
}

svgText.drawRectText = svgTextDrawRectText;

svgText.brush = function (el) {
    var style = el.style;
    if (style.text != null) {
        svgTextDrawRectText(el, false);
    }
};

// Myers' Diff Algorithm
// Modified from https://github.com/kpdecker/jsdiff/blob/master/src/diff/base.js

function Diff() {}

Diff.prototype = {
    diff: function (oldArr, newArr, equals) {
        if (!equals) {
            equals = function (a, b) {
                return a === b;
            };
        }
        this.equals = equals;

        var self = this;

        oldArr = oldArr.slice();
        newArr = newArr.slice();
        // Allow subclasses to massage the input prior to running
        var newLen = newArr.length;
        var oldLen = oldArr.length;
        var editLength = 1;
        var maxEditLength = newLen + oldLen;
        var bestPath = [{ newPos: -1, components: [] }];

        // Seed editLength = 0, i.e. the content starts with the same values
        var oldPos = this.extractCommon(bestPath[0], newArr, oldArr, 0);
        if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
            var indices = [];
            for (var i = 0; i < newArr.length; i++) {
                indices.push(i);
            }
            // Identity per the equality and tokenizer
            return [{
                indices: indices, count: newArr.length
            }];
        }

        // Main worker method. checks all permutations of a given edit length for acceptance.
        function execEditLength() {
            for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
                var basePath;
                var addPath = bestPath[diagonalPath - 1];
                var removePath = bestPath[diagonalPath + 1];
                var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
                if (addPath) {
                    // No one else is going to attempt to use this value, clear it
                    bestPath[diagonalPath - 1] = undefined;
                }

                var canAdd = addPath && addPath.newPos + 1 < newLen;
                var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
                if (!canAdd && !canRemove) {
                    // If this path is a terminal then prune
                    bestPath[diagonalPath] = undefined;
                    continue;
                }

                // Select the diagonal that we want to branch from. We select the prior
                // path whose position in the new string is the farthest from the origin
                // and does not pass the bounds of the diff graph
                if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
                    basePath = clonePath(removePath);
                    self.pushComponent(basePath.components, undefined, true);
                }
                else {
                    basePath = addPath;   // No need to clone, we've pulled it from the list
                    basePath.newPos++;
                    self.pushComponent(basePath.components, true, undefined);
                }

                oldPos = self.extractCommon(basePath, newArr, oldArr, diagonalPath);

                // If we have hit the end of both strings, then we are done
                if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
                    return buildValues(self, basePath.components, newArr, oldArr);
                }
                else {
                    // Otherwise track this path as a potential candidate and continue.
                    bestPath[diagonalPath] = basePath;
                }
            }

            editLength++;
        }

        while (editLength <= maxEditLength) {
            var ret = execEditLength();
            if (ret) {
                return ret;
            }
        }
    },

    pushComponent: function (components, added, removed) {
        var last = components[components.length - 1];
        if (last && last.added === added && last.removed === removed) {
            // We need to clone here as the component clone operation is just
            // as shallow array clone
            components[components.length - 1] = {count: last.count + 1, added: added, removed: removed };
        }
        else {
            components.push({count: 1, added: added, removed: removed });
        }
    },
    extractCommon: function (basePath, newArr, oldArr, diagonalPath) {
        var newLen = newArr.length;
        var oldLen = oldArr.length;
        var newPos = basePath.newPos;
        var oldPos = newPos - diagonalPath;
        var commonCount = 0;

        while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newArr[newPos + 1], oldArr[oldPos + 1])) {
            newPos++;
            oldPos++;
            commonCount++;
        }

        if (commonCount) {
            basePath.components.push({count: commonCount});
        }

        basePath.newPos = newPos;
        return oldPos;
    },
    tokenize: function (value) {
        return value.slice();
    },
    join: function (value) {
        return value.slice();
    }
};

function buildValues(diff, components, newArr, oldArr) {
    var componentPos = 0;
    var componentLen = components.length;
    var newPos = 0;
    var oldPos = 0;

    for (; componentPos < componentLen; componentPos++) {
        var component = components[componentPos];
        if (!component.removed) {
            var indices = [];
            for (var i = newPos; i < newPos + component.count; i++) {
                indices.push(i);
            }
            component.indices = indices;
            newPos += component.count;
            // Common case
            if (!component.added) {
                oldPos += component.count;
            }
        }
        else {
            var indices = [];
            for (var i = oldPos; i < oldPos + component.count; i++) {
                indices.push(i);
            }
            component.indices = indices;
            oldPos += component.count;
        }
    }

    return components;
}

function clonePath(path) {
    return { newPos: path.newPos, components: path.components.slice(0) };
}

var arrayDiff = new Diff();

var arrayDiff$1 = function (oldArr, newArr, callback) {
    return arrayDiff.diff(oldArr, newArr, callback);
};

/**
 * @file Manages elements that can be defined in <defs> in SVG,
 *       e.g., gradients, clip path, etc.
 * @author Zhang Wenli
 */

var MARK_UNUSED = '0';
var MARK_USED = '1';

/**
 * Manages elements that can be defined in <defs> in SVG,
 * e.g., gradients, clip path, etc.
 *
 * @class
 * @param {number}          zrId      zrender instance id
 * @param {SVGElement}      svgRoot   root of SVG document
 * @param {string|string[]} tagNames  possible tag names
 * @param {string}          markLabel label name to make if the element
 *                                    is used
 */
function Definable(
    zrId,
    svgRoot,
    tagNames,
    markLabel,
    domName
) {
    this._zrId = zrId;
    this._svgRoot = svgRoot;
    this._tagNames = typeof tagNames === 'string' ? [tagNames] : tagNames;
    this._markLabel = markLabel;
    this._domName = domName || '_dom';

    this.nextId = 0;
}


Definable.prototype.createElement = createElement;


/**
 * Get the <defs> tag for svgRoot; optionally creates one if not exists.
 *
 * @param {boolean} isForceCreating if need to create when not exists
 * @return {SVGDefsElement} SVG <defs> element, null if it doesn't
 * exist and isForceCreating is false
 */
Definable.prototype.getDefs = function (isForceCreating) {
    var svgRoot = this._svgRoot;
    var defs = this._svgRoot.getElementsByTagName('defs');
    if (defs.length === 0) {
        // Not exist
        if (isForceCreating) {
            defs = svgRoot.insertBefore(
                this.createElement('defs'), // Create new tag
                svgRoot.firstChild // Insert in the front of svg
            );
            if (!defs.contains) {
                // IE doesn't support contains method
                defs.contains = function (el) {
                    var children = defs.children;
                    if (!children) {
                        return false;
                    }
                    for (var i = children.length - 1; i >= 0; --i) {
                        if (children[i] === el) {
                            return true;
                        }
                    }
                    return false;
                };
            }
            return defs;
        }
        else {
            return null;
        }
    }
    else {
        return defs[0];
    }
};


/**
 * Update DOM element if necessary.
 *
 * @param {Object|string} element style element. e.g., for gradient,
 *                                it may be '#ccc' or {type: 'linear', ...}
 * @param {Function|undefined} onUpdate update callback
 */
Definable.prototype.update = function (element, onUpdate) {
    if (!element) {
        return;
    }

    var defs = this.getDefs(false);
    if (element[this._domName] && defs.contains(element[this._domName])) {
        // Update DOM
        if (typeof onUpdate === 'function') {
            onUpdate(element);
        }
    }
    else {
        // No previous dom, create new
        var dom = this.add(element);
        if (dom) {
            element[this._domName] = dom;
        }
    }
};


/**
 * Add gradient dom to defs
 *
 * @param {SVGElement} dom DOM to be added to <defs>
 */
Definable.prototype.addDom = function (dom) {
    var defs = this.getDefs(true);
    defs.appendChild(dom);
};


/**
 * Remove DOM of a given element.
 *
 * @param {SVGElement} element element to remove dom
 */
Definable.prototype.removeDom = function (element) {
    var defs = this.getDefs(false);
    if (defs && element[this._domName]) {
        defs.removeChild(element[this._domName]);
        element[this._domName] = null;
    }
};


/**
 * Get DOMs of this element.
 *
 * @return {HTMLDomElement} doms of this defineable elements in <defs>
 */
Definable.prototype.getDoms = function () {
    var defs = this.getDefs(false);
    if (!defs) {
        // No dom when defs is not defined
        return [];
    }

    var doms = [];
    each$1(this._tagNames, function (tagName) {
        var tags = defs.getElementsByTagName(tagName);
        // Note that tags is HTMLCollection, which is array-like
        // rather than real array.
        // So `doms.concat(tags)` add tags as one object.
        doms = doms.concat([].slice.call(tags));
    });

    return doms;
};


/**
 * Mark DOMs to be unused before painting, and clear unused ones at the end
 * of the painting.
 */
Definable.prototype.markAllUnused = function () {
    var doms = this.getDoms();
    var that = this;
    each$1(doms, function (dom) {
        dom[that._markLabel] = MARK_UNUSED;
    });
};


/**
 * Mark a single DOM to be used.
 *
 * @param {SVGElement} dom DOM to mark
 */
Definable.prototype.markUsed = function (dom) {
    if (dom) {
        dom[this._markLabel] = MARK_USED;
    }
};


/**
 * Remove unused DOMs defined in <defs>
 */
Definable.prototype.removeUnused = function () {
    var defs = this.getDefs(false);
    if (!defs) {
        // Nothing to remove
        return;
    }

    var doms = this.getDoms();
    var that = this;
    each$1(doms, function (dom) {
        if (dom[that._markLabel] !== MARK_USED) {
            // Remove gradient
            defs.removeChild(dom);
        }
    });
};


/**
 * Get SVG proxy.
 *
 * @param {Displayable} displayable displayable element
 * @return {Path|Image|Text} svg proxy of given element
 */
Definable.prototype.getSvgProxy = function (displayable) {
    if (displayable instanceof Path) {
        return svgPath;
    }
    else if (displayable instanceof ZImage) {
        return svgImage;
    }
    else if (displayable instanceof Text) {
        return svgText;
    }
    else {
        return svgPath;
    }
};


/**
 * Get text SVG element.
 *
 * @param {Displayable} displayable displayable element
 * @return {SVGElement} SVG element of text
 */
Definable.prototype.getTextSvgElement = function (displayable) {
    return displayable.__textSvgEl;
};


/**
 * Get SVG element.
 *
 * @param {Displayable} displayable displayable element
 * @return {SVGElement} SVG element
 */
Definable.prototype.getSvgElement = function (displayable) {
    return displayable.__svgEl;
};

/**
 * @file Manages SVG gradient elements.
 * @author Zhang Wenli
 */

/**
 * Manages SVG gradient elements.
 *
 * @class
 * @extends Definable
 * @param   {number}     zrId    zrender instance id
 * @param   {SVGElement} svgRoot root of SVG document
 */
function GradientManager(zrId, svgRoot) {
    Definable.call(
        this,
        zrId,
        svgRoot,
        ['linearGradient', 'radialGradient'],
        '__gradient_in_use__'
    );
}


inherits(GradientManager, Definable);


/**
 * Create new gradient DOM for fill or stroke if not exist,
 * but will not update gradient if exists.
 *
 * @param {SvgElement}  svgElement   SVG element to paint
 * @param {Displayable} displayable  zrender displayable element
 */
GradientManager.prototype.addWithoutUpdate = function (
    svgElement,
    displayable
) {
    if (displayable && displayable.style) {
        var that = this;
        each$1(['fill', 'stroke'], function (fillOrStroke) {
            if (displayable.style[fillOrStroke]
                && (displayable.style[fillOrStroke].type === 'linear'
                || displayable.style[fillOrStroke].type === 'radial')
            ) {
                var gradient = displayable.style[fillOrStroke];
                var defs = that.getDefs(true);

                // Create dom in <defs> if not exists
                var dom;
                if (gradient._dom) {
                    // Gradient exists
                    dom = gradient._dom;
                    if (!defs.contains(gradient._dom)) {
                        // _dom is no longer in defs, recreate
                        that.addDom(dom);
                    }
                }
                else {
                    // New dom
                    dom = that.add(gradient);
                }

                that.markUsed(displayable);

                var id = dom.getAttribute('id');
                svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')');
            }
        });
    }
};


/**
 * Add a new gradient tag in <defs>
 *
 * @param   {Gradient} gradient zr gradient instance
 * @return {SVGLinearGradientElement | SVGRadialGradientElement}
 *                            created DOM
 */
GradientManager.prototype.add = function (gradient) {
    var dom;
    if (gradient.type === 'linear') {
        dom = this.createElement('linearGradient');
    }
    else if (gradient.type === 'radial') {
        dom = this.createElement('radialGradient');
    }
    else {
        logError$1('Illegal gradient type.');
        return null;
    }

    // Set dom id with gradient id, since each gradient instance
    // will have no more than one dom element.
    // id may exists before for those dirty elements, in which case
    // id should remain the same, and other attributes should be
    // updated.
    gradient.id = gradient.id || this.nextId++;
    dom.setAttribute('id', 'zr' + this._zrId
        + '-gradient-' + gradient.id);

    this.updateDom(gradient, dom);
    this.addDom(dom);

    return dom;
};


/**
 * Update gradient.
 *
 * @param {Gradient} gradient zr gradient instance
 */
GradientManager.prototype.update = function (gradient) {
    var that = this;
    Definable.prototype.update.call(this, gradient, function () {
        var type = gradient.type;
        var tagName = gradient._dom.tagName;
        if (type === 'linear' && tagName === 'linearGradient'
            || type === 'radial' && tagName === 'radialGradient'
        ) {
            // Gradient type is not changed, update gradient
            that.updateDom(gradient, gradient._dom);
        }
        else {
            // Remove and re-create if type is changed
            that.removeDom(gradient);
            that.add(gradient);
        }
    });
};


/**
 * Update gradient dom
 *
 * @param {Gradient} gradient zr gradient instance
 * @param {SVGLinearGradientElement | SVGRadialGradientElement} dom
 *                            DOM to update
 */
GradientManager.prototype.updateDom = function (gradient, dom) {
    if (gradient.type === 'linear') {
        dom.setAttribute('x1', gradient.x);
        dom.setAttribute('y1', gradient.y);
        dom.setAttribute('x2', gradient.x2);
        dom.setAttribute('y2', gradient.y2);
    }
    else if (gradient.type === 'radial') {
        dom.setAttribute('cx', gradient.x);
        dom.setAttribute('cy', gradient.y);
        dom.setAttribute('r', gradient.r);
    }
    else {
        logError$1('Illegal gradient type.');
        return;
    }

    if (gradient.global) {
        // x1, x2, y1, y2 in range of 0 to canvas width or height
        dom.setAttribute('gradientUnits', 'userSpaceOnUse');
    }
    else {
        // x1, x2, y1, y2 in range of 0 to 1
        dom.setAttribute('gradientUnits', 'objectBoundingBox');
    }

    // Remove color stops if exists
    dom.innerHTML = '';

    // Add color stops
    var colors = gradient.colorStops;
    for (var i = 0, len = colors.length; i < len; ++i) {
        var stop = this.createElement('stop');
        stop.setAttribute('offset', colors[i].offset * 100 + '%');

        var color = colors[i].color;
        if (color.indexOf('rgba' > -1)) {
            // Fix Safari bug that stop-color not recognizing alpha #9014
            var opacity = parse(color)[3];
            var hex = toHex(color);

            // stop-color cannot be color, since:
            // The opacity value used for the gradient calculation is the
            // *product* of the value of stop-opacity and the opacity of the
            // value of stop-color.
            // See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty
            stop.setAttribute('stop-color', '#' + hex);
            stop.setAttribute('stop-opacity', opacity);
        }
        else {
            stop.setAttribute('stop-color', colors[i].color);
        }

        dom.appendChild(stop);
    }

    // Store dom element in gradient, to avoid creating multiple
    // dom instances for the same gradient element
    gradient._dom = dom;
};

/**
 * Mark a single gradient to be used
 *
 * @param {Displayable} displayable displayable element
 */
GradientManager.prototype.markUsed = function (displayable) {
    if (displayable.style) {
        var gradient = displayable.style.fill;
        if (gradient && gradient._dom) {
            Definable.prototype.markUsed.call(this, gradient._dom);
        }

        gradient = displayable.style.stroke;
        if (gradient && gradient._dom) {
            Definable.prototype.markUsed.call(this, gradient._dom);
        }
    }
};

/**
 * @file Manages SVG clipPath elements.
 * @author Zhang Wenli
 */

/**
 * Manages SVG clipPath elements.
 *
 * @class
 * @extends Definable
 * @param   {number}     zrId    zrender instance id
 * @param   {SVGElement} svgRoot root of SVG document
 */
function ClippathManager(zrId, svgRoot) {
    Definable.call(this, zrId, svgRoot, 'clipPath', '__clippath_in_use__');
}


inherits(ClippathManager, Definable);


/**
 * Update clipPath.
 *
 * @param {Displayable} displayable displayable element
 */
ClippathManager.prototype.update = function (displayable) {
    var svgEl = this.getSvgElement(displayable);
    if (svgEl) {
        this.updateDom(svgEl, displayable.__clipPaths, false);
    }

    var textEl = this.getTextSvgElement(displayable);
    if (textEl) {
        // Make another clipPath for text, since it's transform
        // matrix is not the same with svgElement
        this.updateDom(textEl, displayable.__clipPaths, true);
    }

    this.markUsed(displayable);
};


/**
 * Create an SVGElement of displayable and create a <clipPath> of its
 * clipPath
 *
 * @param {Displayable} parentEl  parent element
 * @param {ClipPath[]}  clipPaths clipPaths of parent element
 * @param {boolean}     isText    if parent element is Text
 */
ClippathManager.prototype.updateDom = function (
    parentEl,
    clipPaths,
    isText
) {
    if (clipPaths && clipPaths.length > 0) {
        // Has clipPath, create <clipPath> with the first clipPath
        var defs = this.getDefs(true);
        var clipPath = clipPaths[0];
        var clipPathEl;
        var id;

        var dom = isText ? '_textDom' : '_dom';

        if (clipPath[dom]) {
            // Use a dom that is already in <defs>
            id = clipPath[dom].getAttribute('id');
            clipPathEl = clipPath[dom];

            // Use a dom that is already in <defs>
            if (!defs.contains(clipPathEl)) {
                // This happens when set old clipPath that has
                // been previously removed
                defs.appendChild(clipPathEl);
            }
        }
        else {
            // New <clipPath>
            id = 'zr' + this._zrId + '-clip-' + this.nextId;
            ++this.nextId;
            clipPathEl = this.createElement('clipPath');
            clipPathEl.setAttribute('id', id);
            defs.appendChild(clipPathEl);

            clipPath[dom] = clipPathEl;
        }

        // Build path and add to <clipPath>
        var svgProxy = this.getSvgProxy(clipPath);
        if (clipPath.transform
            && clipPath.parent.invTransform
            && !isText
        ) {
            /**
             * If a clipPath has a parent with transform, the transform
             * of parent should not be considered when setting transform
             * of clipPath. So we need to transform back from parent's
             * transform, which is done by multiplying parent's inverse
             * transform.
             */
            // Store old transform
            var transform = Array.prototype.slice.call(
                clipPath.transform
            );

            // Transform back from parent, and brush path
            mul$1(
                clipPath.transform,
                clipPath.parent.invTransform,
                clipPath.transform
            );
            svgProxy.brush(clipPath);

            // Set back transform of clipPath
            clipPath.transform = transform;
        }
        else {
            svgProxy.brush(clipPath);
        }

        var pathEl = this.getSvgElement(clipPath);

        clipPathEl.innerHTML = '';
        /**
         * Use `cloneNode()` here to appendChild to multiple parents,
         * which may happend when Text and other shapes are using the same
         * clipPath. Since Text will create an extra clipPath DOM due to
         * different transform rules.
         */
        clipPathEl.appendChild(pathEl.cloneNode());

        parentEl.setAttribute('clip-path', 'url(#' + id + ')');

        if (clipPaths.length > 1) {
            // Make the other clipPaths recursively
            this.updateDom(clipPathEl, clipPaths.slice(1), isText);
        }
    }
    else {
        // No clipPath
        if (parentEl) {
            parentEl.setAttribute('clip-path', 'none');
        }
    }
};

/**
 * Mark a single clipPath to be used
 *
 * @param {Displayable} displayable displayable element
 */
ClippathManager.prototype.markUsed = function (displayable) {
    var that = this;
    // displayable.__clipPaths can only be `null`/`undefined` or an non-empty array.
    if (displayable.__clipPaths) {
        each$1(displayable.__clipPaths, function (clipPath) {
            if (clipPath._dom) {
                Definable.prototype.markUsed.call(that, clipPath._dom);
            }
            if (clipPath._textDom) {
                Definable.prototype.markUsed.call(that, clipPath._textDom);
            }
        });
    }
};

/**
 * @file Manages SVG shadow elements.
 * @author Zhang Wenli
 */

/**
 * Manages SVG shadow elements.
 *
 * @class
 * @extends Definable
 * @param   {number}     zrId    zrender instance id
 * @param   {SVGElement} svgRoot root of SVG document
 */
function ShadowManager(zrId, svgRoot) {
    Definable.call(
        this,
        zrId,
        svgRoot,
        ['filter'],
        '__filter_in_use__',
        '_shadowDom'
    );
}


inherits(ShadowManager, Definable);


/**
 * Create new shadow DOM for fill or stroke if not exist,
 * but will not update shadow if exists.
 *
 * @param {SvgElement}  svgElement   SVG element to paint
 * @param {Displayable} displayable  zrender displayable element
 */
ShadowManager.prototype.addWithoutUpdate = function (
    svgElement,
    displayable
) {
    if (displayable && hasShadow(displayable.style)) {

        // Create dom in <defs> if not exists
        var dom;
        if (displayable._shadowDom) {
            // Gradient exists
            dom = displayable._shadowDom;

            var defs = this.getDefs(true);
            if (!defs.contains(displayable._shadowDom)) {
                // _shadowDom is no longer in defs, recreate
                this.addDom(dom);
            }
        }
        else {
            // New dom
            dom = this.add(displayable);
        }

        this.markUsed(displayable);

        var id = dom.getAttribute('id');
        svgElement.style.filter = 'url(#' + id + ')';
    }
};


/**
 * Add a new shadow tag in <defs>
 *
 * @param {Displayable} displayable  zrender displayable element
 * @return {SVGFilterElement} created DOM
 */
ShadowManager.prototype.add = function (displayable) {
    var dom = this.createElement('filter');

    // Set dom id with shadow id, since each shadow instance
    // will have no more than one dom element.
    // id may exists before for those dirty elements, in which case
    // id should remain the same, and other attributes should be
    // updated.
    displayable._shadowDomId = displayable._shadowDomId || this.nextId++;
    dom.setAttribute('id', 'zr' + this._zrId
        + '-shadow-' + displayable._shadowDomId);

    this.updateDom(displayable, dom);
    this.addDom(dom);

    return dom;
};


/**
 * Update shadow.
 *
 * @param {Displayable} displayable  zrender displayable element
 */
ShadowManager.prototype.update = function (svgElement, displayable) {
    var style = displayable.style;
    if (hasShadow(style)) {
        var that = this;
        Definable.prototype.update.call(this, displayable, function () {
            that.updateDom(displayable, displayable._shadowDom);
        });
    }
    else {
        // Remove shadow
        this.remove(svgElement, displayable);
    }
};


/**
 * Remove DOM and clear parent filter
 */
ShadowManager.prototype.remove = function (svgElement, displayable) {
    if (displayable._shadowDomId != null) {
        this.removeDom(svgElement);
        svgElement.style.filter = '';
    }
};


/**
 * Update shadow dom
 *
 * @param {Displayable} displayable  zrender displayable element
 * @param {SVGFilterElement} dom DOM to update
 */
ShadowManager.prototype.updateDom = function (displayable, dom) {
    var domChild = dom.getElementsByTagName('feDropShadow');
    if (domChild.length === 0) {
        domChild = this.createElement('feDropShadow');
    }
    else {
        domChild = domChild[0];
    }

    var style = displayable.style;
    var scaleX = displayable.scale ? (displayable.scale[0] || 1) : 1;
    var scaleY = displayable.scale ? (displayable.scale[1] || 1) : 1;

    // TODO: textBoxShadowBlur is not supported yet
    var offsetX;
    var offsetY;
    var blur;
    var color;
    if (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY) {
        offsetX = style.shadowOffsetX || 0;
        offsetY = style.shadowOffsetY || 0;
        blur = style.shadowBlur;
        color = style.shadowColor;
    }
    else if (style.textShadowBlur) {
        offsetX = style.textShadowOffsetX || 0;
        offsetY = style.textShadowOffsetY || 0;
        blur = style.textShadowBlur;
        color = style.textShadowColor;
    }
    else {
        // Remove shadow
        this.removeDom(dom, style);
        return;
    }

    domChild.setAttribute('dx', offsetX / scaleX);
    domChild.setAttribute('dy', offsetY / scaleY);
    domChild.setAttribute('flood-color', color);

    // Divide by two here so that it looks the same as in canvas
    // See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur
    var stdDx = blur / 2 / scaleX;
    var stdDy = blur / 2 / scaleY;
    var stdDeviation = stdDx + ' ' + stdDy;
    domChild.setAttribute('stdDeviation', stdDeviation);

    // Fix filter clipping problem
    dom.setAttribute('x', '-100%');
    dom.setAttribute('y', '-100%');
    dom.setAttribute('width', Math.ceil(blur / 2 * 200) + '%');
    dom.setAttribute('height', Math.ceil(blur / 2 * 200) + '%');

    dom.appendChild(domChild);

    // Store dom element in shadow, to avoid creating multiple
    // dom instances for the same shadow element
    displayable._shadowDom = dom;
};

/**
 * Mark a single shadow to be used
 *
 * @param {Displayable} displayable displayable element
 */
ShadowManager.prototype.markUsed = function (displayable) {
    if (displayable._shadowDom) {
        Definable.prototype.markUsed.call(this, displayable._shadowDom);
    }
};

function hasShadow(style) {
    // TODO: textBoxShadowBlur is not supported yet
    return style
        && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY
            || style.textShadowBlur || style.textShadowOffsetX
            || style.textShadowOffsetY);
}

/**
 * SVG Painter
 * @module zrender/svg/Painter
 */

function parseInt10$2(val) {
    return parseInt(val, 10);
}

function getSvgProxy(el) {
    if (el instanceof Path) {
        return svgPath;
    }
    else if (el instanceof ZImage) {
        return svgImage;
    }
    else if (el instanceof Text) {
        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 append(parent, child) {
//     if (checkParentAvailable(parent, child)) {
//         parent.appendChild(child);
//     }
// }

function remove$1(parent, child) {
    if (child && parent && child.parentNode === parent) {
        parent.removeChild(child);
    }
}

function getTextSvgElement(displayable) {
    return displayable.__textSvgEl;
}

function getSvgElement(displayable) {
    return displayable.__svgEl;
}

/**
 * @alias module:zrender/svg/Painter
 * @constructor
 * @param {HTMLElement} root 绘图容器
 * @param {module:zrender/Storage} storage
 * @param {Object} opts
 */
var SVGPainter = function (root, storage, opts, zrId) {

    this.root = root;
    this.storage = storage;
    this._opts = opts = extend({}, opts || {});

    var svgRoot = createElement('svg');
    svgRoot.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
    svgRoot.setAttribute('version', '1.1');
    svgRoot.setAttribute('baseProfile', 'full');
    svgRoot.style.cssText = 'user-select:none;position:absolute;left:0;top:0;';

    this.gradientManager = new GradientManager(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._svgRoot = svgRoot;
    this._viewport = viewport;

    root.appendChild(viewport);
    viewport.appendChild(svgRoot);

    this.resize(opts.width, opts.height);

    this._visibleList = [];
};

SVGPainter.prototype = {

    constructor: SVGPainter,

    getType: function () {
        return 'svg';
    },

    getViewportRoot: function () {
        return this._viewport;
    },

    getViewportRootOffset: function () {
        var viewportRoot = this.getViewportRoot();
        if (viewportRoot) {
            return {
                offsetLeft: viewportRoot.offsetLeft || 0,
                offsetTop: viewportRoot.offsetTop || 0
            };
        }
    },

    refresh: function () {

        var list = this.storage.getDisplayList(true);

        this._paintList(list);
    },

    setBackgroundColor: function (backgroundColor) {
        // TODO gradient
        this._viewport.style.background = backgroundColor;
    },

    _paintList: function (list) {
        this.gradientManager.markAllUnused();
        this.clipPathManager.markAllUnused();
        this.shadowManager.markAllUnused();

        var svgRoot = this._svgRoot;
        var visibleList = this._visibleList;
        var listLen = list.length;

        var newVisibleList = [];
        var i;
        for (i = 0; i < listLen; i++) {
            var displayable = list[i];
            var svgProxy = getSvgProxy(displayable);
            var svgElement = getSvgElement(displayable)
                || getTextSvgElement(displayable);
            if (!displayable.invisible) {
                if (displayable.__dirty) {
                    svgProxy && svgProxy.brush(displayable);

                    // Update clipPath
                    this.clipPathManager.update(displayable);

                    // Update gradient and shadow
                    if (displayable.style) {
                        this.gradientManager
                            .update(displayable.style.fill);
                        this.gradientManager
                            .update(displayable.style.stroke);

                        this.shadowManager
                            .update(svgElement, displayable);
                    }

                    displayable.__dirty = false;
                }
                newVisibleList.push(displayable);
            }
        }

        var diff = arrayDiff$1(visibleList, newVisibleList);
        var prevSvgElement;

        // First do remove, in case element moved to the head and do remove
        // after add
        for (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);
                    var textSvgElement = getTextSvgElement(displayable);
                    remove$1(svgRoot, svgElement);
                    remove$1(svgRoot, textSvgElement);
                }
            }
        }
        for (i = 0; i < diff.length; i++) {
            var item = diff[i];
            if (item.added) {
                for (var k = 0; k < item.count; k++) {
                    var displayable = newVisibleList[item.indices[k]];
                    var svgElement = getSvgElement(displayable);
                    var textSvgElement = getTextSvgElement(displayable);
                    prevSvgElement
                        ? insertAfter(svgRoot, svgElement, prevSvgElement)
                        : prepend(svgRoot, svgElement);
                    if (svgElement) {
                        insertAfter(svgRoot, textSvgElement, svgElement);
                    }
                    else if (prevSvgElement) {
                        insertAfter(
                            svgRoot, textSvgElement, prevSvgElement
                        );
                    }
                    else {
                        prepend(svgRoot, textSvgElement);
                    }
                    // Insert text
                    insertAfter(svgRoot, textSvgElement, svgElement);
                    prevSvgElement = textSvgElement || svgElement
                        || prevSvgElement;

                    // zrender.Text only create textSvgElement.
                    this.gradientManager
                        .addWithoutUpdate(svgElement || textSvgElement, displayable);
                    this.shadowManager
                        .addWithoutUpdate(svgElement || textSvgElement, displayable);
                    this.clipPathManager.markUsed(displayable);
                }
            }
            else if (!item.removed) {
                for (var k = 0; k < item.count; k++) {
                    var displayable = newVisibleList[item.indices[k]];
                    prevSvgElement = getTextSvgElement(displayable)
                        || getSvgElement(displayable) || prevSvgElement;

                    var svgElement = getSvgElement(displayable);
                    var textSvgElement = getTextSvgElement(displayable);

                    this.gradientManager.markUsed(displayable);
                    this.gradientManager
                        .addWithoutUpdate(svgElement || textSvgElement, displayable);

                    this.shadowManager.markUsed(displayable);
                    this.shadowManager
                        .addWithoutUpdate(svgElement || textSvgElement, displayable);

                    this.clipPathManager.markUsed(displayable);
                }
            }
        }

        this.gradientManager.removeUnused();
        this.clipPathManager.removeUnused();
        this.shadowManager.removeUnused();

        this._visibleList = newVisibleList;
    },

    _getDefs: function (isForceCreating) {
        var svgRoot = this._svgRoot;
        var defs = this._svgRoot.getElementsByTagName('defs');
        if (defs.length === 0) {
            // Not exist
            if (isForceCreating) {
                var defs = svgRoot.insertBefore(
                    createElement('defs'), // Create new tag
                    svgRoot.firstChild // Insert in the front of svg
                );
                if (!defs.contains) {
                    // IE doesn't support contains method
                    defs.contains = function (el) {
                        var children = defs.children;
                        if (!children) {
                            return false;
                        }
                        for (var i = children.length - 1; i >= 0; --i) {
                            if (children[i] === el) {
                                return true;
                            }
                        }
                        return false;
                    };
                }
                return defs;
            }
            else {
                return null;
            }
        }
        else {
            return defs[0];
        }
    },

    resize: function (width, height) {
        var viewport = this._viewport;
        // FIXME Why ?
        viewport.style.display = 'none';

        // Save input w/h
        var opts = this._opts;
        width != null && (opts.width = width);
        height != null && (opts.height = height);

        width = this._getSize(0);
        height = this._getSize(1);

        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._svgRoot;
            // Set width by 'svgRoot.width = width' is invalid
            svgRoot.setAttribute('width', width);
            svgRoot.setAttribute('height', height);
        }
    },

    /**
     * 获取绘图区域宽度
     */
    getWidth: function () {
        return this._width;
    },

    /**
     * 获取绘图区域高度
     */
    getHeight: function () {
        return this._height;
    },

    _getSize: function (whIdx) {
        var opts = this._opts;
        var wh = ['width', 'height'][whIdx];
        var cwh = ['clientWidth', 'clientHeight'][whIdx];
        var plt = ['paddingLeft', 'paddingTop'][whIdx];
        var prb = ['paddingRight', 'paddingBottom'][whIdx];

        if (opts[wh] != null && opts[wh] !== 'auto') {
            return parseFloat(opts[wh]);
        }

        var root = this.root;
        // IE8 does not support getComputedStyle, but it use VML.
        var stl = document.defaultView.getComputedStyle(root);

        return (
            (root[cwh] || parseInt10$2(stl[wh]) || parseInt10$2(root.style[wh]))
            - (parseInt10$2(stl[plt]) || 0)
            - (parseInt10$2(stl[prb]) || 0)
        ) | 0;
    },

    dispose: function () {
        this.root.innerHTML = '';

        this._svgRoot =
            this._viewport =
            this.storage =
            null;
    },

    clear: function () {
        if (this._viewport) {
            this.root.removeChild(this._viewport);
        }
    },

    pathToDataUrl: function () {
        this.refresh();
        var html = this._svgRoot.outerHTML;
        return 'data:image/svg+xml;charset=UTF-8,' + html;
    }
};

// Not supported methods
function createMethodNotSupport$1(method) {
    return function () {
        logError$1('In SVG mode painter not support method "' + method + '"');
    };
}

// Unsuppoted methods
each$1([
    'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer',
    'eachOtherLayer', 'getLayers', 'modLayer', 'delLayer', 'clearLayer',
    'toDataURL', 'pathToImage'
], function (name) {
    SVGPainter.prototype[name] = createMethodNotSupport$1(name);
});

registerPainter('svg', SVGPainter);

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// ----------------------------------------------
// All of the modules that are allowed to be
// imported are listed below.
//
// Users MUST NOT import other modules that are
// not included in this list.
// ----------------------------------------------



// ----------------
// Charts (series)
// ----------------



// All of the series types, for example:
// chart.setOption({
//     series: [{
//         type: 'line' // or 'bar', 'pie', ...
//     }]
// });

// -------------------
// Coordinate systems
// -------------------



// All of the axis modules have been included in the
// coordinate system module below, do not need to
// make extra import.

// `cartesian` coordinate system. For some historical
// reasons, it is named as grid, for example:
// chart.setOption({
//     grid: {...},
//     xAxis: {...},
//     yAxis: {...},
//     series: [{...}]
// });
// `polar` coordinate system, for example:
// chart.setOption({
//     polar: {...},
//     radiusAxis: {...},
//     angleAxis: {...},
//     series: [{
//         coordinateSystem: 'polar'
//     }]
// });
// `geo` coordinate system, for example:
// chart.setOption({
//     geo: {...},
//     series: [{
//         coordinateSystem: 'geo'
//     }]
// });
// `singleAxis` coordinate system (notice, it is a coordinate system
// with only one axis, work for chart like theme river), for example:
// chart.setOption({
//     singleAxis: {...}
//     series: [{type: 'themeRiver', ...}]
// });
// `parallel` coordinate system, only work for parallel series, for example:
// chart.setOption({
//     parallel: {...},
//     parallelAxis: [{...}, ...],
//     series: [{
//         type: 'parallel'
//     }]
// });
// `calendar` coordinate system. for example,
// chart.setOptionp({
//     calendar: {...},
//     series: [{
//         coordinateSystem: 'calendar'
//     }]
// );
// ------------------
// Other components
// ------------------



// `graphic` component, for example:
// chart.setOption({
//     graphic: {...}
// });
// `toolbox` component, for example:
// chart.setOption({
//     toolbox: {...}
// });
// `tooltip` component, for example:
// chart.setOption({
//     tooltip: {...}
// });
// `axisPointer` component, for example:
// chart.setOption({
//     tooltip: {axisPointer: {...}, ...}
// });
// Or
// chart.setOption({
//     axisPointer: {...}
// });
// `brush` component, for example:
// chart.setOption({
//     brush: {...}
// });
// Or
// chart.setOption({
//     tooltip: {feature: {brush: {...}}
// })
// `title` component, for example:
// chart.setOption({
//     title: {...}
// });
// `timeline` component, for example:
// chart.setOption({
//     timeline: {...}
// });
// `markPoint` component, for example:
// chart.setOption({
//     series: [{markPoint: {...}}]
// });
// `markLine` component, for example:
// chart.setOption({
//     series: [{markLine: {...}}]
// });
// `markArea` component, for example:
// chart.setOption({
//     series: [{markArea: {...}}]
// });
// `legend` component scrollable, for example:
// chart.setOption({
//     legend: {type: 'scroll'}
// });
// `legend` component not scrollable. for example:
// chart.setOption({
//     legend: {...}
// });
// `dataZoom` component including both `dataZoomInside` and `dataZoomSlider`.
// `dataZoom` component providing drag, pinch, wheel behaviors
// inside coodinate system, for example:
// chart.setOption({
//     dataZoom: {type: 'inside'}
// });
// `dataZoom` component providing a slider bar, for example:
// chart.setOption({
//     dataZoom: {type: 'slider'}
// });
// `dataZoom` component including both `visualMapContinuous` and `visualMapPiecewise`.
// `visualMap` component providing continuous bar, for example:
// chart.setOption({
//     visualMap: {type: 'continuous'}
// });
// `visualMap` component providing pieces bar, for example:
// chart.setOption({
//     visualMap: {type: 'piecewise'}
// });
// -----------------
// Render engines
// -----------------



// Provide IE 6,7,8 compatibility.
// Render via SVG rather than canvas.

exports.version = version;
exports.dependencies = dependencies;
exports.PRIORITY = PRIORITY;
exports.init = init;
exports.connect = connect;
exports.disConnect = disConnect;
exports.disconnect = disconnect;
exports.dispose = dispose;
exports.getInstanceByDom = getInstanceByDom;
exports.getInstanceById = getInstanceById;
exports.registerTheme = registerTheme;
exports.registerPreprocessor = registerPreprocessor;
exports.registerProcessor = registerProcessor;
exports.registerPostUpdate = registerPostUpdate;
exports.registerAction = registerAction;
exports.registerCoordinateSystem = registerCoordinateSystem;
exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions;
exports.registerLayout = registerLayout;
exports.registerVisual = registerVisual;
exports.registerLoading = registerLoading;
exports.extendComponentModel = extendComponentModel;
exports.extendComponentView = extendComponentView;
exports.extendSeriesModel = extendSeriesModel;
exports.extendChartView = extendChartView;
exports.setCanvasCreator = setCanvasCreator;
exports.registerMap = registerMap;
exports.getMap = getMap;
exports.dataTool = dataTool;
exports.zrender = zrender;
exports.number = number;
exports.format = format;
exports.throttle = throttle;
exports.helper = helper;
exports.matrix = matrix;
exports.vector = vector;
exports.color = color;
exports.parseGeoJSON = parseGeoJson$1;
exports.parseGeoJson = parseGeoJson;
exports.util = ecUtil;
exports.graphic = graphic$1;
exports.List = List;
exports.Model = Model;
exports.Axis = Axis;
exports.env = env$1;

})));
//# sourceMappingURL=echarts-en.js.map
