/*!
 * ====================================================
 * kitygraph - v1.0.0 - 2014-03-06
 * https://github.com/kitygraph/kity
 * GitHub: https://github.com/kitygraph/kity.git 
 * Copyright (c) 2014 Baidu UEditor Group; Licensed MIT
 * ====================================================
 */

(function () {
/**
 * cmd 内部定义
 */

// 模块存储
var _modules = {};

function define ( id, deps, factory ) {

    _modules[ id ] = {

        exports: {},
        value: null,
        factory: null

    };

    if ( arguments.length === 2 ) {

        factory = deps;

    }

    if ( _modules.toString.call( factory ) === '[object Object]' ) {

        _modules[ id ][ 'value' ] = factory;

    } else if ( typeof factory === 'function' ) {

        _modules[ id ][ 'factory' ] = factory;

    } else {

        throw new Error( 'define函数未定义的行为' );

    }

}

function require ( id ) {

    var module = _modules[ id ],
        exports = null;

    if ( !module ) {

        return null;

    }

    if ( module.value ) {

        return module.value;

    }


    exports = module.factory.call( null, require, module.exports, module );

    // return 值不为空， 则以return值为最终值
    if ( exports ) {

        module.exports = exports;

    }

    module.value = module.exports;

    return module.value;

}

function use ( id ) {

    return require( id );

}
define("animate/animator", [ "animate/timeline", "graphic/color", "graphic/matrix", "graphic/eventhandler", "core/class", "animate/easing", "core/config", "graphic/shape", "graphic/svg", "core/utils", "graphic/styled", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    function parseTime(str) {
        var value = parseFloat(str, 10);
        if (/ms/.test(str)) {
            return value;
        }
        if (/s/.test(str)) {
            return value * 1e3;
        }
        if (/min/.test(str)) {
            return value * 60 * 1e3;
        }
        return value;
    }
    var Timeline = require("animate/timeline");
    var easingTable = require("animate/easing");
    var Animator = require("core/class").createClass("Animator", {
        constructor: function(beginValue, finishValue, setter) {
            if (arguments.length == 1) {
                var opt = arguments[0];
                this.beginVal = opt.beginValue;
                this.finishVal = opt.finishValue;
                this.setter = opt.setter;
            } else {
                this.beginVal = beginValue;
                this.finishVal = finishValue;
                this.setter = setter;
            }
        },
        start: function(target, duration, easing, delay, callback) {
            if (arguments.length === 4 && typeof delay == "function") {
                callback = delay;
                delay = 0;
            }
            var timeline = this.create(target, duration, easing, callback);
            delay = parseTime(delay);
            if (delay > 0) {
                setTimeout(function() {
                    timeline.play();
                }, delay);
            } else {
                timeline.play();
            }
            return timeline;
        },
        create: function(target, duration, easing, callback) {
            var timeline;
            duration = duration && parseTime(duration) || Animator.DEFAULT_DURATION;
            easing = easing || Animator.DEFAULT_EASING;
            if (typeof easing == "string") {
                easing = easingTable[easing];
            }
            timeline = new Timeline(this, target, duration, easing);
            if (typeof callback == "function") {
                timeline.on("finish", callback);
            }
            return timeline;
        },
        reverse: function() {
            return new Animator(this.finishVal, this.beginVal, this.setter);
        }
    });
    Animator.DEFAULT_DURATION = 300;
    Animator.DEFAULT_EASING = "linear";
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        animate: function(animator, duration, easing, delay, callback) {
            var queue = this._KityAnimateQueue = this._KityAnimateQueue || [];
            var timeline = animator.create(this, duration, easing, callback);
            function dequeue() {
                queue.shift();
                if (queue.length) {
                    setTimeout(queue[0].t.play.bind(queue[0].t), queue[0].d);
                }
            }
            timeline.on("finish", dequeue);
            queue.push({
                t: timeline,
                d: delay
            });
            if (queue.length == 1) {
                setTimeout(timeline.play.bind(timeline), delay);
            }
            return this;
        },
        stop: function() {
            var queue = this._KityAnimateQueue;
            if (queue) {
                while (queue.length) {
                    queue.shift().stop();
                }
            }
        }
    });
    return Animator;
});
/**
 * Kity Animate Easing modified from jQuery Easing
 * Author: techird
 * Changes: 
 *     1. make easing functions standalone
 *     2. remove the 'x' parameter
 */
/* ============================================================
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Open source under the BSD License.
 *
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * https://raw.github.com/danro/jquery-easing/master/LICENSE
 * ======================================================== */
define("animate/easing", [], function(require, exports, module) {
    var easings = {
        // t: current_time, b: begin_value, c: change_value, d: duration
        linear: function(t, b, c, d) {
            return c * (t / d) + b;
        },
        swing: function(t, b, c, d) {
            return easings.easeOutQuad(t, b, c, d);
        },
        ease: function(t, b, c, d) {
            return easings.easeInOutCubic(t, b, c, d);
        },
        easeInQuad: function(t, b, c, d) {
            return c * (t /= d) * t + b;
        },
        easeOutQuad: function(t, b, c, d) {
            return -c * (t /= d) * (t - 2) + b;
        },
        easeInOutQuad: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return c / 2 * t * t + b;
            return -c / 2 * (--t * (t - 2) - 1) + b;
        },
        easeInCubic: function(t, b, c, d) {
            return c * (t /= d) * t * t + b;
        },
        easeOutCubic: function(t, b, c, d) {
            return c * ((t = t / d - 1) * t * t + 1) + b;
        },
        easeInOutCubic: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
            return c / 2 * ((t -= 2) * t * t + 2) + b;
        },
        easeInQuart: function(t, b, c, d) {
            return c * (t /= d) * t * t * t + b;
        },
        easeOutQuart: function(t, b, c, d) {
            return -c * ((t = t / d - 1) * t * t * t - 1) + b;
        },
        easeInOutQuart: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
            return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
        },
        easeInQuint: function(t, b, c, d) {
            return c * (t /= d) * t * t * t * t + b;
        },
        easeOutQuint: function(t, b, c, d) {
            return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
        },
        easeInOutQuint: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
            return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
        },
        easeInSine: function(t, b, c, d) {
            return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
        },
        easeOutSine: function(t, b, c, d) {
            return c * Math.sin(t / d * (Math.PI / 2)) + b;
        },
        easeInOutSine: function(t, b, c, d) {
            return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
        },
        easeInExpo: function(t, b, c, d) {
            return t == 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
        },
        easeOutExpo: function(t, b, c, d) {
            return t == d ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
        },
        easeInOutExpo: function(t, b, c, d) {
            if (t == 0) return b;
            if (t == d) return b + c;
            if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
            return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
        },
        easeInCirc: function(t, b, c, d) {
            return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
        },
        easeOutCirc: function(t, b, c, d) {
            return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
        },
        easeInOutCirc: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
            return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
        },
        easeInElastic: function(t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) return b;
            if ((t /= d) == 1) return b + c;
            if (!p) p = d * .3;
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else var s = p / (2 * Math.PI) * Math.asin(c / a);
            return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * 2 * Math.PI / p)) + b;
        },
        easeOutElastic: function(t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) return b;
            if ((t /= d) == 1) return b + c;
            if (!p) p = d * .3;
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else var s = p / (2 * Math.PI) * Math.asin(c / a);
            return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * 2 * Math.PI / p) + c + b;
        },
        easeInOutElastic: function(t, b, c, d) {
            var s = 1.70158;
            var p = 0;
            var a = c;
            if (t == 0) return b;
            if ((t /= d / 2) == 2) return b + c;
            if (!p) p = d * .3 * 1.5;
            if (a < Math.abs(c)) {
                a = c;
                var s = p / 4;
            } else var s = p / (2 * Math.PI) * Math.asin(c / a);
            if (t < 1) return -.5 * a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * 2 * Math.PI / p) + b;
            return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * 2 * Math.PI / p) * .5 + c + b;
        },
        easeInBack: function(t, b, c, d, s) {
            if (s == undefined) s = 1.70158;
            return c * (t /= d) * t * ((s + 1) * t - s) + b;
        },
        easeOutBack: function(t, b, c, d, s) {
            if (s == undefined) s = 1.70158;
            return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
        },
        easeInOutBack: function(t, b, c, d, s) {
            if (s == undefined) s = 1.70158;
            if ((t /= d / 2) < 1) return c / 2 * t * t * (((s *= 1.525) + 1) * t - s) + b;
            return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b;
        },
        easeInBounce: function(t, b, c, d) {
            return c - easings.easeOutBounce(d - t, 0, c, d) + b;
        },
        easeOutBounce: function(t, b, c, d) {
            if ((t /= d) < 1 / 2.75) {
                return c * 7.5625 * t * t + b;
            } else if (t < 2 / 2.75) {
                return c * (7.5625 * (t -= 1.5 / 2.75) * t + .75) + b;
            } else if (t < 2.5 / 2.75) {
                return c * (7.5625 * (t -= 2.25 / 2.75) * t + .9375) + b;
            } else {
                return c * (7.5625 * (t -= 2.625 / 2.75) * t + .984375) + b;
            }
        },
        easeInOutBounce: function(t, b, c, d) {
            if (t < d / 2) return easings.easeInBounce(t * 2, 0, c, d) * .5 + b;
            return easings.easeOutBounce(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
        }
    };
    return easings;
});
define("animate/opacityanimator", [ "animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/matrix", "core/utils", "graphic/vector", "core/config", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    var Animator = require("animate/animator");
    var Matrix = require("graphic/matrix");
    var OpacityAnimator = require("core/class").createClass("OpacityAnimator", {
        base: Animator,
        constructor: function(opacity) {
            this.callBase({
                beginValue: function(target) {
                    return target.getOpacity();
                },
                finishValue: opacity,
                setter: function(target, value) {
                    target.setOpacity(value);
                }
            });
        }
    });
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        fxOpacity: function(opacity, duration, easing, delay, callback) {
            return this.animate(new OpacityAnimator(opacity), duration, easing, delay, callback);
        },
        fadeTo: function() {
            return this.fxOpacity.apply(this, arguments);
        },
        fadeIn: function() {
            return this.fxOpacity.apply(this, [ 1 ].concat([].slice.call(arguments)));
        },
        fadeOut: function() {
            return this.fxOpacity.apply(this, [ 0 ].concat([].slice.call(arguments)));
        }
    });
    return OpacityAnimator;
});
define("animate/rotateanimator", [ "animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/matrix", "core/utils", "graphic/vector", "core/config", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    var Animator = require("animate/animator");
    var Matrix = require("graphic/matrix");
    var RotateAnimator = require("core/class").createClass("RotateAnimator", {
        base: Animator,
        constructor: function(deg, ax, ay) {
            this.callBase({
                beginValue: 0,
                finishValue: deg,
                setter: function(target, value, timeline) {
                    var delta = timeline.getDelta();
                    target.rotate(delta, ax, ay);
                }
            });
        }
    });
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        fxRotate: function(deg, duration, easing, delay, callback) {
            return this.animate(new RotateAnimator(deg), duration, easing, delay, callback);
        },
        fxRotateAnchor: function(deg, ax, ay, duration, easing, delay, callback) {
            return this.animate(new RotateAnimator(deg, ax, ay), duration, easing, delay, callback);
        }
    });
    return RotateAnimator;
});
define("animate/scaleanimator", [ "animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/matrix", "core/utils", "graphic/vector", "core/config", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    var Animator = require("animate/animator");
    var Matrix = require("graphic/matrix");
    var ScaleAnimator = require("core/class").createClass("ScaleAnimator", {
        base: Animator,
        constructor: function(sx, sy, ax, ay) {
            this.callBase({
                beginValue: 0,
                finishValue: 1,
                setter: function(target, value, timeline) {
                    var delta = timeline.getDelta();
                    var kx = Math.pow(sx, delta);
                    var ky = Math.pow(sy, delta);
                    target.scale(ky, kx);
                }
            });
        }
    });
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        fxScale: function(sx, sy, duration, easing, delay, callback) {
            return this.animate(new ScaleAnimator(sx, sy), duration, easing, delay, callback);
        }
    });
    return ScaleAnimator;
});
define("animate/timeline", [ "graphic/color", "core/utils", "graphic/standardcolor", "core/class", "graphic/matrix", "graphic/vector", "graphic/eventhandler", "graphic/shapeevent", "core/config" ], function(require, exports, module) {
    var Color = require("graphic/color");
    var Matrix = require("graphic/matrix");
    var EventHandler = require("graphic/eventhandler");
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(fn) {
        return setTimeout(fn, 16);
    };
    var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || function(reqId) {
        return clearTimeout(reqId);
    };
    var globalFrameAction = [];
    var frameRequests = [];
    var frameRequestId = 0;
    function requestFrame(id) {
        if (!~frameRequests.indexOf(id)) {
            frameRequests.push(id);
        }
        if (frameRequests.length === 1) {
            frameRequestId = execGlobalFrameAction();
        }
    }
    function releaseFrame(id) {
        var index = frameRequests.indexOf(id);
        if (index !== -1) {
            frameRequests.splice(index, 1);
        }
        if (frameRequests.length === 0) {
            cancelAnimationFrame(frameRequestId);
        }
    }
    function execGlobalFrameAction() {
        var pending = globalFrameAction;
        globalFrameAction = [];
        while (pending.length) {
            pending.shift()();
        }
        if (frameRequests.length > 0) {
            frameRequestId = requestAnimationFrame(execGlobalFrameAction);
        }
    }
    function paralle(v1, v2, op) {
        if (false === isNaN(parseFloat(v1))) {
            return op(v1, v2);
        }
        var value = {};
        for (var n in v1) {
            if (v1.hasOwnProperty(n)) {
                value[n] = paralle(v1[n], v2[n], op);
            }
        }
        return value;
    }
    function getDelta(v1, v2) {
        return paralle(v1, v2, function(v1, v2) {
            return v2 - v1;
        });
    }
    // 不会深度遍历
    function getPercentValue(b, f, p) {
        return paralle(b, f, function(b, f) {
            return b + (f - b) * p;
        });
    }
    function TimelineEvent(timeline, type, param) {
        this.timeline = timeline;
        this.target = timeline.target;
        this.type = type;
        for (var name in param) {
            if (param.hasOwnProperty(name)) {
                this[name] = param[name];
            }
        }
    }
    var timelineId = 0;
    var Timeline = require("core/class").createClass("Timeline", {
        mixins: [ EventHandler ],
        constructor: function(animator, target, duration, easing) {
            this.callMixin();
            this.time = 0;
            this.duration = duration;
            this.target = target;
            this.easing = easing;
            this.status = "ready";
            this.animator = animator;
            this.beginVal = animator.beginVal;
            this.finishVal = animator.finishVal;
            this.setter = animator.setter;
            this.id = timelineId++;
        },
        guessValueType: function() {
            var value = this.beginVal;
            if (parseFloat(value)) {
                this.valueType = "number";
                return;
            }
            // string as color
            if (typeof value == "string" || value instanceof Color) {
                this.valueType = "color";
                return;
            }
            if (value.x && value.y) {
                this.valueType = "point";
                return;
            }
            if (value instanceof Matrix) {
                this.valueType = "matrix";
            }
        },
        nextFrame: function() {
            if (this.status != "playing") {
                return;
            }
            var ts = +new Date(), lts = this.lastFrameTS || 0, elapsed = ts - lts;
            var target = this.target, setter = this.setter;
            // 
            // 1. 首次播放 lts 为 0，则修正 elapsed 为一帧的长度
            // 
            // 2. 浏览器最小化或切换标签，requestAnimationFrame 不会执行。
            //    检测时间超过 200 ms（频率小于 5Hz ） 判定为计时器暂停，重置为一帧长度
            //    
            //    ref: http://stackoverflow.com/questions/13133434/requestanimationframe-detect-stop
            if (elapsed > 200) {
                elapsed = 1e3 / 60;
            }
            this.time += elapsed;
            this.setValue(this.getValue());
            this.lastFrameTS = ts;
            if (this.time >= this.duration) {
                this.timeUp();
            }
            globalFrameAction.push(this.nextFrame.bind(this));
        },
        getPlayTime: function() {
            return this.rollbacking ? this.duration - this.time : this.time;
        },
        getTimeProportion: function() {
            return this.getPlayTime() / this.duration;
        },
        getValueProportion: function() {
            return this.easing(this.getPlayTime(), 0, 1, this.duration);
        },
        getValue: function() {
            var b = this.beginVal, f = this.finishVal, p = this.getValueProportion(), v;
            switch (this.valueType) {
              case "color":
                b = b.getValues();
                f = f.getValues();
                v = getPercentValue(b, f, p);
                return Color.createRGBA(v.r, v.g, v.b, v.a);

              case "matrix":
                b = b.getMatrix();
                f = f.getMatrix();
                v = getPercentValue(b, f, p);
                return new Matrix(v);

              default:
                return getPercentValue(b, f, p);
            }
        },
        getDelta: function() {
            this.lastValue = this.lastValue || this.beginVal;
            return getDelta(this.lastValue, this.currentValue);
        },
        setValue: function(value, lastValue) {
            this.currentValue = value;
            this.setter.call(this.target, this.target, value, this);
            this.lastValue = value;
        },
        play: function() {
            var ctx = this.context;
            var me = this;
            var lastStatus = this.status;
            this.status = "playing";
            switch (lastStatus) {
              case "ready":
                this.beginVal = typeof this.beginVal == "function" ? this.beginVal.call(this.target, this.target) : this.beginVal;
                this.finishVal = typeof this.finishVal == "function" ? this.finishVal.call(this.target, this.target) : this.finishVal;
                this.time = 0;
                this.guessValueType();
                this.nextFrame();
                break;

              case "finished":
              case "stoped":
                this.time = 0;
                this.nextFrame();
                break;

              case "paused":
                this.lastFrameTS = 0;
                this.nextFrame();
            }
            this.fire("play", new TimelineEvent(this, "play", {
                lastStatus: lastStatus
            }));
            requestFrame(this.id);
            return this;
        },
        pause: function() {
            this.status = "paused";
            this.fire("pause", new TimelineEvent(this, "pause"));
            releaseFrame(this.id);
            return this;
        },
        stop: function() {
            this.status = "stoped";
            this.setValue(this.finishVal);
            this.rollbacking = false;
            this.fire("stop", new TimelineEvent(this, "stop"));
            releaseFrame(this.id);
            return this;
        },
        reset: function() {
            this.setValue(this.beginVal);
        },
        timeUp: function() {
            if (this.repeatOption) {
                this.time = 0;
                if (this.rollback) {
                    if (this.rollbacking) {
                        this.decreaseRepeat();
                        this.rollbacking = false;
                    } else {
                        this.rollbacking = true;
                        this.fire("rollback", new TimelineEvent(this, "rollback"));
                    }
                } else {
                    this.decreaseRepeat();
                }
                if (!this.repeatOption) {
                    this.finish();
                } else {
                    this.fire("repeat", new TimelineEvent(this, "repeat"));
                }
            } else {
                this.finish();
            }
        },
        finish: function() {
            this.setValue(this.finishVal);
            this.status = "finished";
            this.fire("finish", new TimelineEvent(this, "finish"));
            releaseFrame(this.id);
        },
        decreaseRepeat: function() {
            if (this.repeatOption !== true) {
                this.repeatOption--;
            }
        },
        repeat: function(repeat, rollback) {
            this.repeatOption = repeat;
            this.rollback = rollback;
            return this;
        }
    });
    return Timeline;
});
define("animate/translateanimator", [ "animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/matrix", "core/utils", "graphic/vector", "core/config", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    var Animator = require("animate/animator");
    var Matrix = require("graphic/matrix");
    var TranslateAnimator = require("core/class").createClass("TranslateAnimator", {
        base: Animator,
        constructor: function(x, y) {
            this.callBase({
                x: 0,
                y: 0
            }, {
                x: x,
                y: y
            }, function(target, value, timeline) {
                var delta = timeline.getDelta();
                target.translate(delta.x, delta.y);
            });
        }
    });
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        fxTranslate: function(x, y, duration, easing, delay, callback) {
            return this.animate(new TranslateAnimator(x, y), duration, easing, delay, callback);
        }
    });
    return TranslateAnimator;
});
define("core/browser", [], function(require, exports, module) {
    var browser = function() {
        var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser = {
            ie: /(msie\s|trident.*rv:)([\w.]+)/.test(agent),
            opera: !!opera && opera.version,
            webkit: agent.indexOf(" applewebkit/") > -1,
            mac: agent.indexOf("macintosh") > -1,
            quirks: document.compatMode == "BackCompat"
        };
        browser.gecko = navigator.product == "Gecko" && !browser.webkit && !browser.opera && !browser.ie;
        var version = 0;
        // Internet Explorer 6.0+
        if (browser.ie) {
            version = (agent.match(/(msie\s|trident.*rv:)([\w.]+)/)[2] || 0) * 1;
            browser.ie11Compat = document.documentMode == 11;
            browser.ie9Compat = document.documentMode == 9;
        }
        // Gecko.
        if (browser.gecko) {
            var geckoRelease = agent.match(/rv:([\d\.]+)/);
            if (geckoRelease) {
                geckoRelease = geckoRelease[1].split(".");
                version = geckoRelease[0] * 1e4 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1;
            }
        }
        if (/chrome\/(\d+\.\d)/i.test(agent)) {
            browser.chrome = +RegExp["$1"];
        }
        if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) {
            browser.safari = +(RegExp["$1"] || RegExp["$2"]);
        }
        // Opera 9.50+
        if (browser.opera) version = parseFloat(opera.version());
        // WebKit 522+ (Safari 3+)
        if (browser.webkit) version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]);
        browser.version = version;
        browser.isCompatible = !browser.mobile && (browser.ie && version >= 6 || browser.gecko && version >= 10801 || browser.opera && version >= 9.5 || browser.air && version >= 1 || browser.webkit && version >= 522 || false);
        return browser;
    }();
    return browser;
});
/**
 * @description 创建一个类
 * @param {String}    fullClassName  类全名，包括命名空间。
 * @param {Plain}     defines        要创建的类的特性
 *     defines.constructor  {Function}       类的构造函数，实例化的时候会被调用。
 *     defines.base         {String}         基类的名称。名称要使用全名。（因为base是javascript未来保留字，所以不用base）
 *     defines.mixin        {Array<String>}  要混合到新类的类集合
 *     defines.<method>     {Function}       其他类方法
 *
 * TODO:
 *     Mixin 构造函数调用支持
 */
define("core/class", [ "core/config" ], function(require, exports) {
    // just to bind context
    Function.prototype.bind = Function.prototype.bind || function(thisObj) {
        var args = Array.prototype.slice.call(arguments, 1);
        return this.apply(thisObj, args);
    };
    var config = require("core/config");
    // 方便调试查看
    if (config.debug) {
        var origin = Object.prototype.toString;
        Object.prototype.toString = function() {
            return this.__KityClassName || origin.call(this);
        };
    }
    // 所有类的基类
    function Class() {}
    Class.__KityClassName = "Class";
    function getCallerClass(instance, caller) {
        var currentClass = instance.constructor;
    }
    // 提供 base 调用支持
    Class.prototype.base = function(name) {
        var caller = arguments.callee.caller;
        var method = caller.__KityMethodClass.__KityBaseClass.prototype[name];
        return method.apply(this, Array.prototype.slice.call(arguments, 1));
    };
    // 直接调用 base 类的同名方法
    Class.prototype.callBase = function() {
        var caller = arguments.callee.caller;
        var method = caller.__KityMethodClass.__KityBaseClass.prototype[caller.__KityMethodName];
        return method.apply(this, arguments);
    };
    Class.prototype.mixin = function(name) {
        var caller = arguments.callee.caller;
        var mixins = caller.__KityMethodClass.__KityMixins;
        if (!mixins) {
            return this;
        }
        var method = mixins[name];
        return method.apply(this, Array.prototype.slice.call(arguments, 1));
    };
    Class.prototype.callMixin = function() {
        var caller = arguments.callee.caller;
        var methodName = caller.__KityMethodName;
        var mixins = caller.__KityMethodClass.__KityMixins;
        if (!mixins) {
            return this;
        }
        var method = mixins[methodName];
        if (methodName == "constructor") {
            for (var i = 0, l = method.length; i < l; i++) {
                method[i].call(this);
            }
            return this;
        } else {
            return method.apply(this, arguments);
        }
    };
    Class.prototype.pipe = function(fn) {
        if (typeof fn == "function") {
            fn.call(this, this);
        }
        return this;
    };
    Class.prototype.getType = function() {
        return this.__KityClassName;
    };
    // 检查基类是否调用了父类的构造函数
    // 该检查是弱检查，假如调用的代码被注释了，同样能检查成功（这个特性可用于知道建议调用，但是出于某些原因不想调用的情况）
    function checkBaseConstructorCall(targetClass, classname) {
        var code = targetClass.toString();
        if (!/this\.callBase/.test(code)) {
            throw new Error(classname + " : 类构造函数没有调用父类的构造函数！为了安全，请调用父类的构造函数");
        }
    }
    function checkMixinConstructorCall(targetClass, classname) {
        var code = targetClass.toString();
        if (!/this\.callMixin/.test(code)) {
            throw new Error(classname + " : 类构造函数没有调用父类的构造函数！为了安全，请调用父类的构造函数");
        }
    }
    var KITY_INHERIT_FLAG = "__KITY_INHERIT_FLAG_" + +new Date();
    function inherit(constructor, BaseClass, classname) {
        var KityClass = eval("(function " + classname + "( __inherit__flag ) {" + "if( __inherit__flag != KITY_INHERIT_FLAG ) {" + "KityClass.__KityConstructor.apply(this, arguments);" + "}" + "this.__KityClassName = KityClass.__KityClassName;" + "})");
        KityClass.__KityConstructor = constructor;
        KityClass.prototype = new BaseClass(KITY_INHERIT_FLAG);
        for (var methodName in BaseClass.prototype) {
            if (BaseClass.prototype.hasOwnProperty(methodName) && methodName.indexOf("__Kity") !== 0) {
                KityClass.prototype[methodName] = BaseClass.prototype[methodName];
            }
        }
        KityClass.prototype.constructor = KityClass;
        return KityClass;
    }
    function mixin(NewClass, mixins) {
        if (false === mixins instanceof Array) {
            return NewClass;
        }
        var i, length = mixins.length, proto, method;
        NewClass.__KityMixins = {
            constructor: []
        };
        for (i = 0; i < length; i++) {
            proto = mixins[i].prototype;
            for (method in proto) {
                if (false === proto.hasOwnProperty(method) || method.indexOf("__Kity") === 0) {
                    continue;
                }
                if (method === "constructor") {
                    // constructor 特殊处理
                    NewClass.__KityMixins.constructor.push(proto[method]);
                } else {
                    NewClass.prototype[method] = NewClass.__KityMixins[method] = proto[method];
                }
            }
        }
        return NewClass;
    }
    function extend(BaseClass, extension) {
        if (extension.__KityClassName) {
            extension = extension.prototype;
        }
        for (var methodName in extension) {
            if (extension.hasOwnProperty(methodName) && methodName.indexOf("__Kity") && methodName != "constructor") {
                var method = BaseClass.prototype[methodName] = extension[methodName];
                method.__KityMethodClass = BaseClass;
                method.__KityMethodName = methodName;
            }
        }
        return BaseClass;
    }
    exports.createClass = function(classname, defines) {
        var constructor, NewClass, BaseClass;
        if (arguments.length === 1) {
            defines = arguments[0];
            classname = "AnonymousClass";
        }
        BaseClass = defines.base || Class;
        if (defines.hasOwnProperty("constructor")) {
            constructor = defines.constructor;
            if (BaseClass != Class) {
                checkBaseConstructorCall(constructor, classname);
            }
        } else {
            constructor = function() {
                this.callBase.apply(this, arguments);
                this.callMixin.apply(this, arguments);
            };
        }
        NewClass = inherit(constructor, BaseClass, classname);
        NewClass = mixin(NewClass, defines.mixins);
        NewClass.__KityClassName = constructor.__KityClassName = classname;
        NewClass.__KityBaseClass = constructor.__KityBaseClass = BaseClass;
        NewClass.__KityMethodName = constructor.__KityMethodName = "constructor";
        NewClass.__KityMethodClass = constructor.__KityMethodClass = NewClass;
        // 下面这些不需要拷贝到原型链上
        delete defines.mixins;
        delete defines.constructor;
        delete defines.base;
        NewClass = extend(NewClass, defines);
        return NewClass;
    };
    exports.extendClass = extend;
});
define("core/config", [], function(require, exports, module) {
    return {
        debug: true,
        version: "1.0.0"
    };
});
define("core/utils", [], function(require, exports, module) {
    var utils = {
        each: function(obj, iterator, context) {
            if (obj === null) {
                return;
            }
            if (obj.length === +obj.length) {
                for (var i = 0, l = obj.length; i < l; i++) {
                    if (iterator.call(context, obj[i], i, obj) === false) {
                        return false;
                    }
                }
            } else {
                for (var key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        if (iterator.call(context, obj[key], key, obj) === false) {
                            return false;
                        }
                    }
                }
            }
        },
        extend: function(t, s) {
            var a = arguments, notCover = this.isBoolean(a[a.length - 1]) ? a[a.length - 1] : false, len = this.isBoolean(a[a.length - 1]) ? a.length - 1 : a.length;
            for (var i = 1; i < len; i++) {
                var x = a[i];
                for (var k in x) {
                    if (!notCover || !t.hasOwnProperty(k)) {
                        t[k] = x[k];
                    }
                }
            }
            return t;
        },
        clone: function(obj) {
            var cloned = {};
            for (var m in obj) {
                if (obj.hasOwnProperty(m)) {
                    cloned[m] = obj[m];
                }
            }
            return cloned;
        },
        getValue: function(value, defaultValue) {
            return value !== undefined ? value : defaultValue;
        }
    };
    utils.each([ "String", "Function", "Array", "Number", "RegExp", "Object", "Boolean" ], function(v) {
        utils["is" + v] = function(obj) {
            return Object.prototype.toString.apply(obj) == "[object " + v + "]";
        };
    });
    return utils;
});
/**
 * 颜色矩阵运算效果封装
 */
define("filter/effect/colormatrixeffect", [ "filter/effect/effect", "graphic/svg", "core/class", "core/utils", "core/config" ], function(require, exports, module) {
    var Effect = require("filter/effect/effect"), Utils = require("core/utils");
    var ColorMatrixEffect = require("core/class").createClass("ColorMatrixEffect", {
        base: Effect,
        constructor: function(type, input) {
            this.callBase(Effect.NAME_COLOR_MATRIX);
            this.set("type", Utils.getValue(type, ColorMatrixEffect.TYPE_MATRIX));
            this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC));
        }
    });
    Utils.extend(ColorMatrixEffect, {
        // 类型常量
        TYPE_MATRIX: "matrix",
        TYPE_SATURATE: "saturate",
        TYPE_HUE_ROTATE: "hueRotate",
        TYPE_LUMINANCE_TO_ALPHA: "luminanceToAlpha",
        // 矩阵常量
        MATRIX_ORIGINAL: "10000010000010000010".split("").join(" "),
        MATRIX_EMPTY: "00000000000000000000".split("").join(" ")
    });
    return ColorMatrixEffect;
});
/**
 * 高斯模糊效果封装
 */
define("filter/effect/compositeeffect", [ "filter/effect/effect", "graphic/svg", "core/class", "core/utils", "core/config" ], function(require, exports, module) {
    var Effect = require("filter/effect/effect"), Utils = require("core/utils");
    var CompositeEffect = require("core/class").createClass("CompositeEffect", {
        base: Effect,
        constructor: function(operator, input, input2) {
            this.callBase(Effect.NAME_COMPOSITE);
            this.set("operator", Utils.getValue(operator, CompositeEffect.OPERATOR_OVER));
            if (input) {
                this.set("in", input);
            }
            if (input2) {
                this.set("in2", input2);
            }
        }
    });
    Utils.extend(CompositeEffect, {
        // operator 常量
        OPERATOR_OVER: "over",
        OPERATOR_IN: "in",
        OPERATOR_OUT: "out",
        OPERATOR_ATOP: "atop",
        OPERATOR_XOR: "xor",
        OPERATOR_ARITHMETIC: "arithmetic"
    });
    return CompositeEffect;
});
/**
 * 像素级别的矩阵卷积运算效果封装
 */
define("filter/effect/convolvematrixeffect", [ "filter/effect/effect", "graphic/svg", "core/class", "core/utils", "core/config" ], function(require, exports, module) {
    var Effect = require("filter/effect/effect"), Utils = require("core/utils");
    var ConvolveMatrixEffect = require("core/class").createClass("ConvolveMatrixEffect", {
        base: Effect,
        constructor: function(edgeMode, input) {
            this.callBase(Effect.NAME_CONVOLVE_MATRIX);
            this.set("edgeMode", Utils.getValue(edgeMode, ConvolveMatrixEffect.MODE_DUPLICATE));
            this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC));
        }
    });
    Utils.extend(ConvolveMatrixEffect, {
        MODE_DUPLICATE: "duplicate",
        MODE_WRAP: "wrap",
        MODE_NONE: "none"
    });
    return ConvolveMatrixEffect;
});
/*
 * 效果类
 * 该类型的对象不存储任何内部属性， 所有操作都是针对该类对象所维护的节点进行的
 */
define("filter/effect/effect", [ "graphic/svg", "core/class", "core/config", "core/utils" ], function(require, exports, module) {
    var svg = require("graphic/svg"), Effect = require("core/class").createClass("Effect", {
        constructor: function(type) {
            this.node = svg.createNode(type);
        },
        getId: function() {
            return this.node.id;
        },
        setId: function(id) {
            this.node.id = id;
            return this;
        },
        set: function(key, value) {
            this.node.setAttribute(key, value);
            return this;
        },
        get: function(key) {
            return this.node.getAttribute(key);
        },
        getNode: function() {
            return this.node;
        },
        // 返回该效果的result
        toString: function() {
            return this.node.getAttribute("result") || "";
        }
    });
    require("core/utils").extend(Effect, {
        // 特效名称常量
        NAME_GAUSSIAN_BLUR: "feGaussianBlur",
        NAME_OFFSET: "feOffset",
        NAME_COMPOSITE: "feComposite",
        NAME_COLOR_MATRIX: "feColorMatrix",
        NAME_CONVOLVE_MATRIX: "feConvolveMatrix",
        // 输入常量
        INPUT_SOURCE_GRAPHIC: "SourceGraphic",
        INPUT_SOURCE_ALPHA: "SourceAlpha",
        INPUT_BACKGROUND_IMAGE: "BackgroundImage",
        INPUT_BACKGROUND_ALPHA: "BackgroundAlpha",
        INPUT_FILL_PAINT: "FillPaint",
        INPUT_STROKE_PAINT: "StrokePaint"
    });
    return Effect;
});
/**
 * 高斯模糊效果封装
 */
define("filter/effect/gaussianblureffect", [ "filter/effect/effect", "graphic/svg", "core/class", "core/utils", "core/config" ], function(require, exports, module) {
    var Effect = require("filter/effect/effect"), Utils = require("core/utils");
    return require("core/class").createClass("GaussianblurEffect", {
        base: Effect,
        constructor: function(stdDeviation, input) {
            this.callBase(Effect.NAME_GAUSSIAN_BLUR);
            this.set("stdDeviation", Utils.getValue(stdDeviation, 1));
            this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC));
        }
    });
});
/**
 * 偏移效果封装
 */
define("filter/effect/offseteffect", [ "filter/effect/effect", "graphic/svg", "core/class", "core/utils", "core/config" ], function(require, exports, module) {
    var Effect = require("filter/effect/effect"), Utils = require("core/utils");
    return require("core/class").createClass("OffsetEffect", {
        base: Effect,
        constructor: function(dx, dy, input) {
            this.callBase(Effect.NAME_OFFSET);
            this.set("dx", Utils.getValue(dx, 0));
            this.set("dy", Utils.getValue(dy, 0));
            this.set("in", Utils.getValue(input, Effect.INPUT_SOURCE_GRAPHIC));
        }
    });
});
/*
 * Effect所用的container
 */
define("filter/effectcontainer", [ "core/class", "core/config", "graphic/container" ], function(require, exports, module) {
    return require("core/class").createClass("EffectContainer", {
        base: require("graphic/container"),
        addEffect: function(point, pos) {
            return this.addItem.apply(this, arguments);
        },
        prependEffect: function() {
            return this.prependItem.apply(this, arguments);
        },
        appendEffect: function() {
            return this.appendItem.apply(this, arguments);
        },
        removeEffect: function(pos) {
            return this.removeItem.apply(this, arguments);
        },
        addEffects: function() {
            return this.addItems.apply(this, arguments);
        },
        setEffects: function() {
            return this.setItems.apply(this, arguments);
        },
        getEffect: function() {
            return this.getItem.apply(this, arguments);
        },
        getEffects: function() {
            return this.getItems.apply(this, arguments);
        },
        getFirstEffect: function() {
            return this.getFirstItem.apply(this, arguments);
        },
        getLastEffect: function() {
            return this.getLastItem.apply(this, arguments);
        },
        itemAddedHandler: function(effectItem, pos) {
            var count = this.getEffects().length, nextEffectItem = this.getItem(pos + 1);
            // 最后一个节点， 直接追加
            if (count === pos + 1) {
                this.node.appendChild(effectItem.getNode());
                return;
            }
            this.node.insertBefore(effectItem.getNode(), nextEffectItem.getNode());
        }
    });
});
/**
 * Filter 基类
 */
define("filter/filter", [ "graphic/svg", "core/class", "core/config", "filter/effectcontainer", "graphic/container", "graphic/shape", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    var svg = require("graphic/svg");
    var Class = require("core/class");
    var Filter = Class.createClass("Filter", {
        mixins: [ require("filter/effectcontainer") ],
        constructor: function(x, y, width, height) {
            this.node = svg.createNode("filter");
            if (x !== undefined) {
                this.set("x", x);
            }
            if (y !== undefined) {
                this.set("y", y);
            }
            if (width !== undefined) {
                this.set("width", width);
            }
            if (height !== undefined) {
                this.set("height", height);
            }
        },
        getId: function() {
            return this.id;
        },
        setId: function(id) {
            this.node.id = id;
            return this;
        },
        set: function(key, value) {
            this.node.setAttribute(key, value);
            return this;
        },
        get: function(key) {
            return this.node.getAttribute(key);
        },
        getNode: function() {
            return this.node;
        }
    });
    var Shape = require("graphic/shape");
    Class.extendClass(Shape, {
        applyFilter: function(filter) {
            var filterId = filter.get("id");
            if (filterId) {
                this.node.setAttribute("filter", "url(#" + filterId + ")");
            }
            return this;
        }
    });
    return Filter;
});
/*
 * 高斯模糊滤镜
 */
define("filter/gaussianblurfilter", [ "filter/effect/gaussianblureffect", "filter/effect/effect", "core/utils", "core/class", "core/config", "filter/filter", "graphic/svg", "filter/effectcontainer", "graphic/shape" ], function(require, exports, module) {
    var GaussianblurEffect = require("filter/effect/gaussianblureffect");
    return require("core/class").createClass("GaussianblurFilter", {
        base: require("filter/filter"),
        constructor: function(stdDeviation) {
            this.callBase();
            this.addEffect(new GaussianblurEffect(stdDeviation));
        }
    });
});
/*
 * 投影滤镜
 */
define("filter/projectionfilter", [ "filter/effect/gaussianblureffect", "filter/effect/effect", "core/utils", "core/class", "graphic/svg", "filter/effect/colormatrixeffect", "graphic/color", "graphic/standardcolor", "filter/effect/compositeeffect", "filter/effect/offseteffect", "core/config", "filter/filter", "filter/effectcontainer", "graphic/shape" ], function(require, exports, module) {
    var GaussianblurEffect = require("filter/effect/gaussianblureffect"), Effect = require("filter/effect/effect"), ColorMatrixEffect = require("filter/effect/colormatrixeffect"), Color = require("graphic/color"), Utils = require("core/utils"), CompositeEffect = require("filter/effect/compositeeffect"), OffsetEffect = require("filter/effect/offseteffect");
    return require("core/class").createClass("ProjectionFilter", {
        base: require("filter/filter"),
        constructor: function(stdDeviation, dx, dy) {
            this.callBase();
            this.gaussianblurEffect = new GaussianblurEffect(stdDeviation, Effect.INPUT_SOURCE_ALPHA);
            this.gaussianblurEffect.set("result", "gaussianblur");
            this.addEffect(this.gaussianblurEffect);
            this.offsetEffect = new OffsetEffect(dx, dy, this.gaussianblurEffect);
            this.offsetEffect.set("result", "offsetBlur");
            this.addEffect(this.offsetEffect);
            this.colorMatrixEffect = new ColorMatrixEffect(ColorMatrixEffect.TYPE_MATRIX, this.offsetEffect);
            this.colorMatrixEffect.set("values", ColorMatrixEffect.MATRIX_ORIGINAL);
            this.colorMatrixEffect.set("result", "colorOffsetBlur");
            this.addEffect(this.colorMatrixEffect);
            this.compositeEffect = new CompositeEffect(CompositeEffect.OPERATOR_OVER, Effect.INPUT_SOURCE_GRAPHIC, this.colorMatrixEffect);
            this.addEffect(this.compositeEffect);
        },
        // 设置投影颜色
        setColor: function(color) {
            var matrix = null, originMatrix = null, colorValue = [];
            if (Utils.isString(color)) {
                color = Color.parse(color);
            }
            if (!color) {
                return this;
            }
            matrix = ColorMatrixEffect.MATRIX_EMPTY.split(" ");
            colorValue.push(color.get("r"));
            colorValue.push(color.get("g"));
            colorValue.push(color.get("b"));
            // rgb 分量更改
            for (var i = 0, len = colorValue.length; i < len; i++) {
                matrix[i * 5 + 3] = colorValue[i] / 255;
            }
            // alpha 分量更改
            matrix[18] = color.get("a");
            this.colorMatrixEffect.set("values", matrix.join(" "));
            return this;
        },
        // 设置投影透明度
        setOpacity: function(opacity) {
            var matrix = this.colorMatrixEffect.get("values").split(" ");
            matrix[18] = opacity;
            this.colorMatrixEffect.set("values", matrix.join(" "));
            return this;
        },
        // 设置阴影偏移量
        setOffset: function(dx, dy) {
            this.setOffsetX(dx);
            this.setOffsetY(dy);
        },
        setOffsetX: function(dx) {
            this.offsetEffect.set("dx", dx);
        },
        setOffsetY: function(dy) {
            this.offsetEffect.set("dy", dy);
        },
        setDeviation: function(deviation) {
            this.gaussianblurEffect.set("stdDeviation", deviation);
        }
    });
});
/**
 * 贝塞尔曲线
 */
define("graphic/bezier", [ "core/class", "core/config", "graphic/pointcontainer", "graphic/container", "graphic/path", "core/utils", "graphic/shape", "graphic/svg" ], function(require, exports, module) {
    return require("core/class").createClass("Bezier", {
        mixins: [ require("graphic/pointcontainer") ],
        base: require("graphic/path"),
        constructor: function(bezierPoints) {
            this.callBase();
            bezierPoints = bezierPoints || [];
            this.changeable = true;
            this.setBezierPoints(bezierPoints);
        },
        getBezierPoints: function() {
            return this.getPoints();
        },
        setBezierPoints: function(bezierPoints) {
            return this.setPoints(bezierPoints);
        },
        //当点集合发生变化时采取的动作
        onContainerChanged: function() {
            if (this.changeable) {
                this.update();
            }
        },
        update: function() {
            var drawer = null, bezierPoints = this.getBezierPoints();
            //单独的一个点不画任何图形
            if (bezierPoints.length < 2) {
                return;
            }
            drawer = this.getDrawer();
            drawer.clear();
            var vertex = bezierPoints[0].getVertex(), forward = null, backward = null;
            drawer.moveTo(vertex.x, vertex.y);
            for (var i = 1, len = bezierPoints.length; i < len; i++) {
                vertex = bezierPoints[i].getVertex();
                backward = bezierPoints[i].getBackward();
                forward = bezierPoints[i - 1].getForward();
                drawer.bezierTo(forward.x, forward.y, backward.x, backward.y, vertex.x, vertex.y);
            }
            return this;
        }
    });
});
/**
 * 贝塞尔点
 */
define("graphic/bezierpoint", [ "graphic/shapepoint", "core/class", "graphic/point", "graphic/vector", "core/config" ], function(require, exports, module) {
    var ShapePoint = require("graphic/shapepoint");
    var Vector = require("graphic/vector");
    var BezierPoint = require("core/class").createClass("BezierPoint", {
        constructor: function(x, y, isSmooth) {
            //顶点
            this.vertex = new ShapePoint(x, y);
            //控制点
            this.forward = new ShapePoint(x, y);
            this.backward = new ShapePoint(x, y);
            //是否平滑
            this.setSmooth(isSmooth === undefined || isSmooth);
            this.setSymReflaction(true);
        },
        clone: function() {
            var newPoint = new BezierPoint(), tmp = null;
            tmp = this.getVertex();
            newPoint.setVertex(tmp.x, tmp.y);
            tmp = this.getForward();
            newPoint.setForward(tmp.x, tmp.y);
            tmp = this.getBackward();
            newPoint.setBackward(tmp.x, tmp.y);
            newPoint.setSmooth(newPoint.isSmooth());
            return newPoint;
        },
        setVertex: function(x, y) {
            this.vertex.setPoint(x, y);
            this.update();
            return this;
        },
        moveTo: function(x, y) {
            var oldForward = this.forward.getPoint(), oldBackward = this.backward.getPoint(), oldVertex = this.vertex.getPoint(), //移动距离
            distance = {
                left: x - oldVertex.x,
                top: y - oldVertex.y
            };
            // 更新
            this.forward.setPoint(oldForward.x + distance.left, oldForward.y + distance.top);
            this.backward.setPoint(oldBackward.x + distance.left, oldBackward.y + distance.top);
            this.vertex.setPoint(x, y);
            this.update();
        },
        setForward: function(x, y) {
            this.forward.setPoint(x, y);
            //更新后置点
            if (this.smooth) {
                this.updateAnother(this.forward, this.backward);
            }
            this.update();
            return this;
        },
        setBackward: function(x, y) {
            this.backward.setPoint(x, y);
            //更新前置点
            if (this.smooth) {
                this.updateAnother(this.backward, this.forward);
            }
            this.update();
            return this;
        },
        setSymReflaction: function(value) {
            this.symReflaction = value;
        },
        isSymReflaction: function() {
            return this.symReflaction;
        },
        updateAnother: function(p, q) {
            var v = this.getVertex(), pv = Vector.fromPoints(p.getPoint(), v), vq = Vector.fromPoints(v, q.getPoint());
            vq = Vector.normalize(pv, this.isSymReflaction() ? pv.length() : vq.length());
            q.setPoint(v.x + vq.x, v.y + vq.y);
        },
        setSmooth: function(isSmooth) {
            this.smooth = !!isSmooth;
            return this;
        },
        getVertex: function() {
            return this.vertex.getPoint();
        },
        getForward: function() {
            return this.forward.getPoint();
        },
        getBackward: function() {
            return this.backward.getPoint();
        },
        isSmooth: function() {
            return this.smooth;
        },
        update: function() {
            if (!this.container) {
                return this;
            }
            //新增参数 this， 把当前引起变化的点传递过去， 以便有需要的地方可以获取到引起变化的源
            this.container.update && this.container.update(this);
        }
    });
    return BezierPoint;
});
define("graphic/circle", [ "core/class", "core/config", "graphic/ellipse", "core/utils", "graphic/path" ], function(require, exports, module) {
    return require("core/class").createClass("Circle", {
        base: require("graphic/ellipse"),
        constructor: function(radius, cx, cy) {
            this.callBase(radius, radius, cx, cy);
        },
        getRadius: function() {
            return this.getRadiusX();
        },
        setRadius: function(radius) {
            return this.callBase(radius, radius);
        }
    });
});
define("graphic/clip", [ "core/class", "core/config", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/shapecontainer", "graphic/container" ], function(require, exports, module) {
    var Class = require("core/class");
    var Shape = require("graphic/shape");
    var Clip = Class.createClass("Clip", {
        base: Shape,
        mixins: [ require("graphic/shapecontainer") ],
        constructor: function() {
            this.callBase("clipPath");
        },
        clip: function(shape) {
            shape.getNode().setAttribute("clip-path", "url(#" + this.getId() + ")");
            return this;
        }
    });
    Class.extendClass(Shape, {
        clipWith: function(clip) {
            clip.clip(this);
            return this;
        }
    });
    return Clip;
});
define("graphic/color", [ "core/utils", "graphic/standardcolor", "core/class", "core/config" ], function(require, exports, module) {
    var Utils = require("core/utils"), StandardColor = require("graphic/standardcolor"), ColorUtils = {}, Color = require("core/class").createClass("Color", {
        constructor: function() {
            var colorValue = null;
            //parse构造
            if (typeof arguments[0] === "string") {
                colorValue = ColorUtils.parseToValue(arguments[0]);
                //解析失败
                if (colorValue === null) {
                    colorValue = {
                        r: 0,
                        g: 0,
                        b: 0,
                        h: 0,
                        s: 0,
                        l: 0,
                        a: 1
                    };
                }
            } else {
                colorValue = {
                    r: arguments[0] | 0,
                    g: arguments[1] | 0,
                    b: arguments[2] | 0,
                    //alpha 默认为1
                    a: parseFloat(arguments[3]) || 1
                };
                colorValue = ColorUtils.overflowFormat(colorValue);
                //获取hsl分量
                colorValue = Utils.extend(colorValue, ColorUtils.rgbValueToHslValue(colorValue));
            }
            this._color = colorValue;
        },
        set: function(name, value) {
            var values = null;
            //设置的值非法
            if (!Color._MAX_VALUE[name]) {
                throw new Error("Color set(): Illegal parameter");
            }
            if (name !== "a") {
                value = Math.floor(value);
            }
            if (name == "h") {
                value = (value + 360) % 360;
            }
            this._color[name] = Math.max(Color._MIN_VALUE[name], Math.min(Color._MAX_VALUE[name], value));
            if ("rgb".indexOf(name) !== -1) {
                this._color = Utils.extend(this._color, ColorUtils.rgbValueToHslValue(this._color));
            } else if ("hsl".indexOf(name) !== -1) {
                this._color = Utils.extend(this._color, ColorUtils.hslValueToRGBValue(this._color));
            }
            return this;
        },
        inc: function(name, value) {
            value = this.get(name) + value;
            if (name == "h") {
                value = (value + 360) % 360;
            } else {
                value = Math.min(Color._MAX_VALUE[name], value);
                value = Math.max(Color._MIN_VALUE[name], value);
            }
            return this.clone().set(name, value);
        },
        dec: function(name, value) {
            return this.inc(name, -value);
        },
        clone: function() {
            return new Color(this.toRGBA());
        },
        get: function(name) {
            if (!Color._MAX_VALUE[name]) {
                return null;
            }
            return this._color[name];
        },
        getValues: function() {
            return Utils.clone(this._color);
        },
        toRGB: function() {
            return ColorUtils.toString(this._color, "rgb");
        },
        toRGBA: function() {
            return ColorUtils.toString(this._color, "rgba");
        },
        toHEX: function() {
            return ColorUtils.toString(this._color, "hex");
        },
        toHSL: function() {
            return ColorUtils.toString(this._color, "hsl");
        },
        toHSLA: function() {
            return ColorUtils.toString(this._color, "hsla");
        },
        //默认实现是调用toRGB或者toRGBA
        toString: function() {
            if (this._color.a === 1) {
                return this.toRGB();
            }
            return this.toRGBA();
        }
    });
    //Color 静态方法
    Utils.extend(Color, {
        //各分量可表示的最大值
        _MAX_VALUE: {
            r: 255,
            g: 255,
            b: 255,
            h: 360,
            s: 100,
            l: 100,
            a: 1
        },
        //各分量最小值
        _MIN_VALUE: {
            r: 0,
            g: 0,
            b: 0,
            h: 0,
            s: 0,
            l: 0,
            a: 0
        },
        //分量常量
        R: "r",
        G: "g",
        B: "b",
        H: "h",
        S: "s",
        L: "l",
        A: "a",
        parse: function(valStr) {
            var rgbValue = ColorUtils.parseToValue(valStr);
            //解析失败， 返回一个默认color实例
            if (rgbValue === null) {
                return new Color();
            }
            return new Color(rgbValue.r, rgbValue.g, rgbValue.b, rgbValue.a);
        },
        createHSL: function(h, s, l) {
            return Color.createHSLA(h, s, l, 1);
        },
        createHSLA: function(h, s, l, a) {
            var colorValue = null;
            s += "%";
            l += "%";
            colorValue = [ "hsla(" + h, s, l, a + ")" ];
            return Color.parse(colorValue.join(", "));
        },
        createRGB: function(r, g, b) {
            return Color.createRGBA(r, g, b, 1);
        },
        createRGBA: function(r, g, b, a) {
            return new Color(r, g, b, a);
        }
    });
    //内部工具对象
    Utils.extend(ColorUtils, {
        parseToValue: function(valStr) {
            var rgbaValue = {};
            /* 优先检测在调色板中是否有对应的颜色 */
            valStr = StandardColor.EXTEND_STANDARD[valStr] || StandardColor.COLOR_STANDARD[valStr] || valStr;
            /* 颜色转换 */
            //hex格式
            if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(valStr)) {
                rgbaValue = ColorUtils.hexToValue(valStr);
            } else if (/^(rgba?)/i.test(valStr)) {
                rgbaValue = ColorUtils.rgbaToValue(valStr);
            } else if (/^(hsla?)/i.test(valStr)) {
                rgbaValue = ColorUtils.hslaToValue(valStr);
            } else {
                return null;
            }
            return ColorUtils.overflowFormat(rgbaValue);
        },
        hexToValue: function(hexStr) {
            var result = {}, keys = [ "r", "g", "b" ];
            if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hexStr)) {
                hexStr = RegExp.$1.split("");
                Utils.each(keys, function(key, index) {
                    if (hexStr.length === 3) {
                        result[key] = ColorUtils.toNumber(hexStr[index] + hexStr[index]);
                    } else {
                        result[key] = ColorUtils.toNumber(hexStr[index * 2] + hexStr[index * 2 + 1]);
                    }
                });
                //转换出hsl值
                result = Utils.extend(result, ColorUtils.rgbValueToHslValue(result));
                result.a = 1;
                return result;
            }
            return null;
        },
        rgbaToValue: function(rgbaStr) {
            var result = {}, hasAlpha = false, keys = [ "r", "g", "b" ];
            if (/^(rgba?)/i.test(rgbaStr)) {
                hasAlpha = RegExp.$1.length === 4;
                rgbaStr = rgbaStr.replace(/^rgba?/i, "").replace(/\s+/g, "").replace(/[^0-9,.]/g, "").split(",");
                Utils.each(keys, function(key, index) {
                    result[key] = rgbaStr[index] | 0;
                });
                //转换出hsl值
                result = Utils.extend(result, ColorUtils.rgbValueToHslValue(result));
                result.a = hasAlpha ? parseFloat(rgbaStr[3]) : 1;
                return result;
            }
            return null;
        },
        hslaToValue: function(hslaStr) {
            var result = {}, hasAlpha = false;
            if (/^(hsla?)/i.test(hslaStr)) {
                hasAlpha = RegExp.$1.length === 4;
                hslaStr = hslaStr.replace(/^hsla?/i, "").replace(/\s+/g, "").replace(/[^0-9,.]/g, "").split(",");
                //记录hsl值
                result.h = hslaStr[0] | 0;
                result.s = hslaStr[1] | 0;
                result.l = hslaStr[2] | 0;
                //转换出rgb值
                result = Utils.extend(result, ColorUtils.hslValueToRGBValue(result));
                //hsl值转换为rgb值
                result = ColorUtils.hslValueToRGBValue(result);
                result.a = hasAlpha ? parseFloat(hslaStr[3]) : 1;
                return result;
            }
            return null;
        },
        //hsl值对象转换为rgb值对象
        hslValueToRGBValue: function(hslValue) {
            var q = null, p = null, result = {};
            hslValue = Utils.extend({}, hslValue);
            hslValue.h = hslValue.h / 360;
            hslValue.s = hslValue.s / 100;
            hslValue.l = hslValue.l / 100;
            //分量计算
            if (hslValue.s === 0) {
                result.r = result.g = result.b = hslValue.l;
            } else {
                if (hslValue.l < .5) {
                    q = hslValue.l * (1 + hslValue.s);
                } else {
                    q = hslValue.l + hslValue.s - hslValue.l * hslValue.s;
                }
                p = 2 * hslValue.l - q;
                result.r = trans(p, q, hslValue.h + 1 / 3);
                result.g = trans(p, q, hslValue.h);
                result.b = trans(p, q, hslValue.h - 1 / 3);
            }
            result.r = Math.min(Math.round(result.r * 255), 255);
            result.g = Math.min(Math.round(result.g * 255), 255);
            result.b = Math.min(Math.round(result.b * 255), 255);
            return result;
            function trans(v1, v2, vH) {
                if (vH < 0) {
                    vH += 1;
                } else if (vH > 1) {
                    vH -= 1;
                }
                if (6 * vH < 1) {
                    return v1 + (v2 - v1) * 6 * vH;
                } else if (2 * vH < 1) {
                    return v2;
                } else if (3 * vH < 2) {
                    return v1 + (v2 - v1) * (2 / 3 - vH) * 6;
                }
                return v1;
            }
        },
        //rgb值对象转换为hsl值对象
        rgbValueToHslValue: function(rgbValue) {
            var max = null, min = null, result = {};
            rgbValue = Utils.extend({}, rgbValue);
            rgbValue.r = rgbValue.r / 255;
            rgbValue.g = rgbValue.g / 255;
            rgbValue.b = rgbValue.b / 255;
            max = Math.max(rgbValue.r, rgbValue.g, rgbValue.b);
            min = Math.min(rgbValue.r, rgbValue.g, rgbValue.b);
            //h分量计算
            if (max === min) {
                result.h = 0;
            } else if (max === rgbValue.r) {
                if (rgbValue.g >= rgbValue.b) {
                    result.h = 60 * (rgbValue.g - rgbValue.b) / (max - min);
                } else {
                    result.h = 60 * (rgbValue.g - rgbValue.b) / (max - min) + 360;
                }
            } else if (max === rgbValue.g) {
                result.h = 60 * (rgbValue.b - rgbValue.r) / (max - min) + 120;
            } else if (max === rgbValue.b) {
                result.h = 60 * (rgbValue.r - rgbValue.g) / (max - min) + 240;
            }
            //l分量计算
            result.l = (max + min) / 2;
            //s分量计算
            if (result.l === 0 || max === min) {
                result.s = 0;
            } else if (result.l > 0 && result.l <= .5) {
                result.s = (max - min) / (max + min);
            } else {
                result.s = (max - min) / (2 - max - min);
            }
            //格式化hsl结果
            result.h = Math.round(result.h);
            result.s = Math.round(result.s * 100);
            result.l = Math.round(result.l * 100);
            return result;
        },
        toString: function(colorValue, type) {
            var vals = [];
            colorValue = Utils.extend({}, colorValue);
            if (type.indexOf("hsl") !== -1) {
                colorValue.s += "%";
                colorValue.l += "%";
            }
            if (type !== "hex") {
                Utils.each(type.split(""), function(key) {
                    vals.push(colorValue[key]);
                });
                return (type + "(" + vals.join(", ") + ")").toLowerCase();
            } else {
                vals.push(ColorUtils.toHexValue(+colorValue.r));
                vals.push(ColorUtils.toHexValue(+colorValue.g));
                vals.push(ColorUtils.toHexValue(+colorValue.b));
                return ("#" + vals.join("")).toLowerCase();
            }
        },
        //16进制的2个数字转化为10进制， 如果转化失败， 返回0
        toNumber: function(value) {
            return Number("0x" + value) | 0;
        },
        toHexValue: function(value) {
            var result = value.toString(16);
            return result.length === 1 ? "0" + result : result;
        },
        //溢出控制
        overflowFormat: function(value) {
            var tmpValue = Utils.extend({}, value), keys = "rgba";
            Utils.each(keys.split(""), function(key) {
                if (!tmpValue.hasOwnProperty(key)) {
                    return;
                }
                //上溢出
                tmpValue[key] = Math.min(Color._MAX_VALUE[key], tmpValue[key]);
                //下溢出
                tmpValue[key] = Math.max(Color._MIN_VALUE[key], tmpValue[key]);
            });
            return tmpValue;
        }
    });
    return Color;
});
define("graphic/container", [ "core/class", "core/config" ], function(require, exports, module) {
    function itemRemove() {
        this.container.removeItem(this);
        return this;
    }
    return require("core/class").createClass("Container", {
        getItems: function() {
            return this.items || (this.items = []);
        },
        getItem: function(index) {
            return this.getItems()[index];
        },
        getFirstItem: function() {
            return this.getItem(0);
        },
        getLastItem: function() {
            return this.getItem(this.getItems().length - 1);
        },
        indexOf: function(item) {
            return this.getItems().indexOf(item);
        },
        eachItem: function(fn) {
            var items = this.getItems(), length = items.length, i;
            for (i = 0; i < length; i++) {
                fn.call(this, i, items[i]);
            }
            return this;
        },
        addItem: function(item, pos, noEvent) {
            var items = this.getItems(), length = items.length;
            if (~items.indexOf(item)) {
                return this;
            }
            if (!(pos >= 0 && pos < length)) {
                pos = length;
            }
            items.splice(pos, 0, item);
            if (typeof item === "object") {
                item.container = this;
                item.remove = itemRemove;
            }
            this.handleAdd(item, pos);
            if (!noEvent) {
                this.onContainerChanged("add", [ item ]);
            }
            return this;
        },
        addItems: function(items) {
            for (var i = 0, l = items.length; i < l; i++) {
                this.addItem(items[i], -1, true);
            }
            this.onContainerChanged("add", items);
            return this;
        },
        setItems: function(items) {
            // TODO: Optimize
            return this.clear().addItems(items);
        },
        appendItem: function(item) {
            return this.addItem(item);
        },
        prependItem: function(item) {
            return this.addItem(item, 0);
        },
        removeItem: function(pos, noEvent) {
            if (typeof pos !== "number") {
                return this.removeItem(this.indexOf(pos));
            }
            var items = this.getItems(), length = items.length, item = items[pos];
            if (item === undefined) {
                return this;
            }
            items.splice(pos, 1);
            if (item.container) {
                delete item.container;
            }
            if (item.remove) {
                delete item.remove;
            }
            this.handleRemove(item, pos);
            if (!noEvent) {
                this.onContainerChanged("remove", [ item ]);
            }
            return this;
        },
        clear: function() {
            var removed = [];
            var item;
            while (item = this.getFirstItem()) {
                removed.push(item);
                this.removeItem(0, true);
            }
            this.onContainerChanged("remove", removed);
            return this;
        },
        onContainerChanged: function(type, items) {},
        handleAdd: function(item, index) {},
        handleRemove: function(item, index) {}
    });
});
/*
 * 曲线
 * */
define("graphic/curve", [ "core/utils", "core/class", "core/config", "graphic/path", "graphic/shape", "graphic/svg", "graphic/pointcontainer", "graphic/container" ], function(require, exports, module) {
    var Utils = require("core/utils"), CurveUtil = {
        /*
         * 获取由两个以上的点组成的曲线的平移线
         * @param points 曲线上的点的集合， 集合中的点的数量必须大于2
         * @return 平移线数组
         */
        getCurvePanLines: function(points, smoothFactor) {
            //计算原始点的中点坐标
            var centerPoints = CurveUtil.getCenterPoints(points), //注意：计算中点连线的中点坐标， 得出平移线
            panLines = CurveUtil.getPanLine(points.length, centerPoints);
            //平移线移动到顶点
            return CurveUtil.getMovedPanLines(points, panLines, smoothFactor);
        },
        /*
         * 计算给定点集合的连线的中点
         * @param points
         */
        getCenterPoints: function(points) {
            var centerPoints = {}, key = null;
            for (var i = 0, j = 0, len = points.length; i < len; i++) {
                //j是下一个点的索引
                j = i === len - 1 ? 0 : i + 1;
                key = i + "," + j;
                //计算中点坐标
                centerPoints[key] = {
                    x: (points[i].getX() + points[j].getX()) / 2,
                    y: (points[i].getY() + points[j].getY()) / 2
                };
            }
            return centerPoints;
        },
        /*
         * 对getCenterPoints()接口获取到的数据做处理， 计算出各个顶点对应的平移线数据
         * @param length 集合中点的个数
         * @param points 点集合， 该集合应该是getCenterPoints()接口返回的数据
         */
        getPanLine: function(length, points) {
            var result = {}, //顶点索引
            pointIndex = null;
            for (var i = 0, j; i < length; i++) {
                var point1 = null, point2 = null;
                //计算当前点
                j = (i + 1) % length;
                //保存当前处理的顶点索引
                pointIndex = j;
                point1 = points[i + "," + j];
                //计算下一个点
                i = j;
                j = (i + 1) % length;
                point2 = points[i + "," + j];
                result[pointIndex] = {
                    points: [ {
                        x: point1.x,
                        y: point1.y
                    }, {
                        x: point2.x,
                        y: point2.y
                    } ],
                    center: {
                        x: (point1.x + point2.x) / 2,
                        y: (point1.y + point2.y) / 2
                    }
                };
                //还原i值
                i = (pointIndex + length - 1) % length;
            }
            return result;
        },
        /*
         * 计算平移线移动到顶点后的位置
         * @param points 顶点集合
         * @param panLines 平移线集合
         */
        getMovedPanLines: function(points, panLines, smoothFactor) {
            var result = {};
            Utils.each(points, function(point, index) {
                //当前平移线
                var currentPanLine = panLines[index], //平移线中点
                center = currentPanLine.center, //移动距离
                distance = {
                    x: center.x - point.getX(),
                    y: center.y - point.getY()
                };
                var currentResult = result[index] = {
                    points: [],
                    center: {
                        x: point.getX(),
                        y: point.getY()
                    }
                };
                //计算控制点到顶点的距离， 并且应用平滑系数到距离上
                Utils.each(currentPanLine.points, function(controlPoint, index) {
                    var moved = {
                        x: controlPoint.x - distance.x,
                        y: controlPoint.y - distance.y
                    };
                    var vertex = currentResult.center;
                    var dx = moved.x - vertex.x;
                    var dy = moved.y - vertex.y;
                    moved.x = vertex.x + smoothFactor * dx;
                    moved.y = vertex.y + smoothFactor * dy;
                    currentResult.points.push(moved);
                });
            });
            return result;
        }
    };
    return require("core/class").createClass("Curve", {
        base: require("graphic/path"),
        mixins: [ require("graphic/pointcontainer") ],
        constructor: function(points, isColse) {
            this.callBase();
            this.setPoints(points || []);
            this.closeState = !!isColse;
            this.changeable = true;
            this.smoothFactor = 1;
            this.update();
        },
        //当点集合发生变化时采取的动作
        onContainerChanged: function() {
            if (this.changeable) {
                this.update();
            }
        },
        setSmoothFactor: function(factor) {
            this.smoothFactor = factor < 0 ? 0 : factor;
            this.update();
            return this;
        },
        getSmoothFactor: function() {
            return this.smoothFactor;
        },
        update: function() {
            var points = this.getPoints(), withControlPoints = null, drawer = this.getDrawer(), curPoint = null, curControlPoint = null, prevControlPoint = null;
            drawer.clear();
            if (points.length === 0) {
                return this;
            } else {
                drawer.moveTo(points[0].getX(), points[0].getY());
            }
            if (points.length === 1) {
                return this;
            }
            if (points.length === 2) {
                drawer.lineTo(points[1].getX(), points[1].getY());
                return this;
            }
            //获取已转换过后的带控制点的所有点
            withControlPoints = CurveUtil.getCurvePanLines(points, this.getSmoothFactor());
            for (var i = 1, len = points.length; i < len; i++) {
                //当前顶点
                curPoint = withControlPoints[i].center;
                //当前控制点
                if (this.closeState || i != len - 1) {
                    curControlPoint = withControlPoints[i].points[0];
                } else {
                    //非闭合状态下最后一个点的处理
                    curControlPoint = withControlPoints[i].center;
                }
                if (this.closeState || i != 1) {
                    prevControlPoint = withControlPoints[i - 1].points[1];
                } else {
                    //非闭合状态下第一个点的处理
                    prevControlPoint = withControlPoints[i - 1].center;
                }
                drawer.bezierTo(prevControlPoint.x, prevControlPoint.y, curControlPoint.x, curControlPoint.y, curPoint.x, curPoint.y);
            }
            //处理闭合
            if (this.closeState) {
                curPoint = withControlPoints[0].center;
                curControlPoint = withControlPoints[0].points[0];
                prevControlPoint = withControlPoints[points.length - 1].points[1];
                drawer.bezierTo(prevControlPoint.x, prevControlPoint.y, curControlPoint.x, curControlPoint.y, curPoint.x, curPoint.y);
            }
            return this;
        },
        close: function() {
            this.closeState = true;
            return this.update();
        },
        open: function() {
            this.closeState = false;
            return this.update();
        },
        isClose: function() {
            return !!this.closeState;
        }
    });
});
define("graphic/data", [ "core/class", "core/config" ], function(require, exports, module) {
    return require("core/class").createClass("Data", {
        constructor: function() {
            this._data = {};
        },
        setData: function(name, value) {
            this._data[name] = value;
            return this;
        },
        getData: function(name) {
            return this._data[name];
        },
        removeData: function(name) {
            delete this._data[name];
            return this;
        }
    });
});
define("graphic/defbrush", [ "graphic/svg", "core/class", "core/config" ], function(require, exports, module) {
    var svg = require("graphic/svg");
    return require("core/class").createClass("GradientBrush", {
        constructor: function(nodeType) {
            this.callBase();
            this.node = svg.createNode(nodeType);
        },
        fill: function(path) {
            var pathNode = path.node;
            pathNode.setAttribute("fill", "url(#" + this.node.id + ")");
            return this;
        }
    });
});
define("graphic/ellipse", [ "core/utils", "core/class", "core/config", "graphic/path", "graphic/shape", "graphic/svg" ], function(require, exports, module) {
    var Utils = require("core/utils");
    return require("core/class").createClass("Ellipse", {
        base: require("graphic/path"),
        constructor: function(rx, ry, cx, cy) {
            this.callBase();
            this.rx = rx || 0;
            this.ry = ry || 0;
            this.cx = cx || 0;
            this.cy = cy || 0;
            this.update();
        },
        update: function() {
            var rx = this.rx, ry = this.ry;
            x1 = this.cx + rx, x2 = this.cx - rx, y = this.cy;
            var drawer = this.getDrawer();
            drawer.clear();
            drawer.moveTo(x1, y);
            drawer.arcTo(rx, ry, 0, 1, 1, x2, y);
            drawer.arcTo(rx, ry, 0, 1, 1, x1, y);
            return this;
        },
        getRadius: function() {
            return {
                x: this.rx,
                y: this.ry
            };
        },
        getRadiusX: function() {
            return this.rx;
        },
        getRadiusY: function() {
            return this.ry;
        },
        getCenter: function() {
            return {
                x: this.cx,
                y: this.cy
            };
        },
        getCenterX: function() {
            return this.cx;
        },
        getCenterY: function() {
            return this.cy;
        },
        setRadius: function(rx, ry) {
            this.rx = rx;
            this.ry = ry;
            return this.update();
        },
        setRadiusX: function(rx) {
            this.rx = rx;
            return this.update();
        },
        setRadiusY: function(ry) {
            this.ry = ry;
            return this.update();
        },
        setCenter: function(cx, cy) {
            this.cx = cx;
            this.cy = cy;
            return this.update();
        },
        setCenterX: function(cx) {
            this.cx = cx;
            return this.update();
        },
        setCenterY: function(cy) {
            this.cy = cy;
            return this.update();
        }
    });
});
/*
 * kity event 实现
 */
define("graphic/eventhandler", [ "core/utils", "graphic/shapeevent", "graphic/matrix", "core/class", "core/config" ], function(require, exports, module) {
    // polyfill
    (function() {
        function CustomEvent(event, params) {
            params = params || {
                bubbles: false,
                cancelable: false,
                detail: undefined
            };
            var evt = document.createEvent("CustomEvent");
            evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
            return evt;
        }
        CustomEvent.prototype = window.Event.prototype;
        window.CustomEvent = CustomEvent;
    })();
    var Utils = require("core/utils"), ShapeEvent = require("graphic/shapeevent");
    // 内部处理器缓存
    var INNER_HANDLER_CACHE = {}, // 用户处理器缓存
    USER_HANDLER_CACHE = {}, guid = 0;
    // 添加事件统一入口
    function _addEvent(type, handler, isOnce) {
        isOnce = !!isOnce;
        if (Utils.isString(type)) {
            type = type.match(/\S+/g);
        }
        Utils.each(type, function(currentType) {
            listen.call(this, this.node, currentType, handler, isOnce);
        }, this);
        return this;
    }
    // 移除事件统一入口
    function _removeEvent(type, handler) {
        var userHandlerList = null, eventId = this._EVNET_UID, isRemoveAll = handler === undefined;
        try {
            userHandlerList = USER_HANDLER_CACHE[eventId][type];
        } catch (e) {
            return;
        }
        //移除指定的监听器
        if (!isRemoveAll) {
            isRemoveAll = true;
            Utils.each(userHandlerList, function(fn, index) {
                if (fn === handler) {
                    // 不能结束， 需要查找完整个list， 避免丢失移除多次绑定同一个处理器的情况
                    delete userHandlerList[index];
                } else {
                    isRemoveAll = false;
                }
            });
        }
        //删除所有监听器
        if (isRemoveAll) {
            deleteDomEvent(this.node, type, INNER_HANDLER_CACHE[eventId][type]);
            delete USER_HANDLER_CACHE[eventId][type];
            delete INNER_HANDLER_CACHE[eventId][type];
        }
        return this;
    }
    // 执行绑定, 该方法context为shape或者mixin了eventhandler的对象
    function listen(node, type, handler, isOnce) {
        var eid = this._EVNET_UID, targetObject = this;
        // 初始化内部监听器
        if (!INNER_HANDLER_CACHE[eid]) {
            INNER_HANDLER_CACHE[eid] = {};
        }
        if (!INNER_HANDLER_CACHE[eid][type]) {
            // 内部监听器
            INNER_HANDLER_CACHE[eid][type] = function(e) {
                e = new ShapeEvent(e || window.event);
                Utils.each(USER_HANDLER_CACHE[eid][type], function(fn) {
                    var result;
                    if (fn) {
                        result = fn.call(targetObject, e);
                        //once 绑定， 执行完后删除
                        if (isOnce) {
                            targetObject.off(type, fn);
                        }
                    }
                    // 如果用户handler里return了false， 则该节点上的此后的同类型事件将不再执行
                    return result;
                }, targetObject);
            };
        }
        // 初始化用户监听器列表
        if (!USER_HANDLER_CACHE[eid]) {
            USER_HANDLER_CACHE[eid] = {};
        }
        if (!USER_HANDLER_CACHE[eid][type]) {
            USER_HANDLER_CACHE[eid][type] = [ handler ];
            // 绑定对应类型的事件
            // dom对象利用dom event进行处理， 非dom对象， 由消息分发机制处理
            if (!!node) {
                bindDomEvent(node, type, INNER_HANDLER_CACHE[eid][type]);
            }
        } else {
            USER_HANDLER_CACHE[eid][type].push(handler);
        }
    }
    // 绑定dom事件
    function bindDomEvent(node, type, handler) {
        if (node.addEventListener) {
            node.addEventListener(type, handler, false);
        } else {
            node.attachEvent("on" + type, handler);
        }
    }
    // 删除dom事件
    function deleteDomEvent(node, type, handler) {
        if (node.removeEventListener) {
            node.removeEventListener(type, handler, false);
        } else {
            node.detachEvent(type, handler);
        }
    }
    // 触发dom事件
    function triggerDomEvent(node, type, params) {
        var event = new CustomEvent(type, {
            bubbles: true,
            cancelable: true
        });
        event.__kity_param = params;
        node.dispatchEvent(event);
    }
    // 发送消息
    function sendMessage(messageObj, type, msg) {
        var event = null, handler = null;
        try {
            handler = INNER_HANDLER_CACHE[messageObj._EVNET_UID][type];
            if (!handler) {
                return;
            }
        } catch (exception) {
            return;
        }
        event = Utils.extend({
            type: type,
            target: messageObj
        }, msg || {});
        handler.call(messageObj, event);
    }
    // 对外接口
    return require("core/class").createClass("EventHandler", {
        constructor: function() {
            this._EVNET_UID = ++guid;
        },
        addEventListener: function(type, handler) {
            return _addEvent.call(this, type, handler, false);
        },
        addOnceEventListener: function(type, handler) {
            return _addEvent.call(this, type, handler, true);
        },
        removeEventListener: function(type, handler) {
            return _removeEvent.call(this, type, handler);
        },
        on: function(type, handler) {
            return this.addEventListener.apply(this, arguments);
        },
        once: function(type, handler) {
            return this.addOnceEventListener.apply(this, arguments);
        },
        off: function() {
            return this.removeEventListener.apply(this, arguments);
        },
        fire: function(type, params) {
            return this.trigger.apply(this, arguments);
        },
        trigger: function(type, params) {
            if (this.node) {
                triggerDomEvent(this.node, type, params);
            } else {
                sendMessage(this, type, params);
            }
            return this;
        }
    });
});
define("graphic/gradientbrush", [ "graphic/svg", "graphic/defbrush", "core/class", "graphic/color", "core/utils", "graphic/standardcolor", "core/config" ], function(require, exports, module) {
    var svg = require("graphic/svg");
    var DefBrush = require("graphic/defbrush");
    var Color = require("graphic/color");
    return require("core/class").createClass("GradientBrush", {
        base: DefBrush,
        constructor: function(gradientNodeType) {
            this.callBase(gradientNodeType);
            this.stops = [];
        },
        addStop: function(offset, color, opacity) {
            var gstop = svg.createNode("stop");
            if (!(color instanceof Color)) {
                color = Color.parse(color);
            }
            if (opacity === undefined) {
                opacity = color.get("a");
            }
            gstop.setAttribute("offset", offset);
            gstop.setAttribute("stop-color", color.toRGB());
            if (opacity < 1) {
                gstop.setAttribute("stop-opacity", opacity);
            }
            this.node.appendChild(gstop);
            return this;
        }
    });
});
define("graphic/group", [ "graphic/shapecontainer", "graphic/container", "core/utils", "core/class", "graphic/shape", "core/config", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    var ShapeContainer = require("graphic/shapecontainer");
    return require("core/class").createClass("Group", {
        mixins: [ ShapeContainer ],
        base: require("graphic/shape"),
        constructor: function() {
            this.callBase("g");
        }
    });
});
define("graphic/image", [ "core/class", "core/config", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    return require("core/class").createClass("Image", {
        base: require("graphic/shape"),
        constructor: function(url, width, height, x, y) {
            this.callBase("image");
            this.url = url;
            this.width = width || 0;
            this.height = height || 0;
            this.x = x || 0;
            this.y = y || 0;
            this.update();
        },
        update: function() {
            this.node.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", this.url);
            this.node.setAttribute("x", this.x);
            this.node.setAttribute("y", this.y);
            this.node.setAttribute("width", this.width);
            this.node.setAttribute("height", this.height);
            return this;
        },
        setUrl: function(url) {
            this.url = url === "" ? null : url;
            return this.update();
        },
        getUrl: function() {
            return this.url;
        },
        setWidth: function(width) {
            this.width = width;
            return this.update();
        },
        getWidth: function() {
            return this.width;
        },
        setHeight: function(height) {
            this.height = height;
            return this.update();
        },
        getHeight: function() {
            return this.height;
        },
        setX: function(x) {
            this.x = x;
            return this.update();
        },
        getX: function() {
            return this.x;
        },
        setY: function(y) {
            this.y = y;
            return this.update();
        },
        getY: function() {
            return this.y;
        }
    });
});
define("graphic/line", [ "core/class", "core/config", "graphic/path", "core/utils", "graphic/shape", "graphic/svg" ], function(require, exports, module) {
    return require("core/class").createClass("Line", {
        base: require("graphic/path"),
        constructor: function(x1, y1, x2, y2) {
            this.callBase();
            this.point1 = {
                x: x1 || 0,
                y: y1 || 0
            };
            this.point2 = {
                x: x2 || 0,
                y: y2 || 0
            };
            this.update();
        },
        setPoint1: function(x, y) {
            this.point1.x = x;
            this.point1.y = y;
            return this.update();
        },
        setPoint2: function(x, y) {
            this.point2.x = x;
            this.point2.y = y;
            return this.update();
        },
        getPoint1: function() {
            return {
                x: this.point1.x,
                y: this.point1.y
            };
        },
        getPoint2: function() {
            return {
                x: this.point2.x,
                y: this.point2.y
            };
        },
        update: function() {
            var drawer = this.getDrawer();
            drawer.clear();
            drawer.moveTo(this.point1.x, this.point1.y);
            drawer.lineTo(this.point2.x, this.point2.y);
            return this;
        }
    });
});
define("graphic/lineargradientbrush", [ "graphic/svg", "graphic/gradientbrush", "graphic/defbrush", "graphic/color", "core/class", "core/config" ], function(require, exports, module) {
    var className = "LinearGradientBrush";
    var svg = require("graphic/svg");
    var GradientBrush = require("graphic/gradientbrush");
    return require("core/class").createClass(className, {
        base: GradientBrush,
        constructor: function(builder) {
            this.callBase("linearGradient");
            this.setStartPosition(0, 0);
            this.setEndPosition(1, 0);
            if (typeof builder == "function") {
                builder.call(this, this);
            }
        },
        setStartPosition: function(px, py) {
            this.node.setAttribute("x1", px);
            this.node.setAttribute("y1", py);
            return this;
        },
        setEndPosition: function(px, py) {
            this.node.setAttribute("x2", px);
            this.node.setAttribute("y2", py);
            return this;
        },
        getStartPosition: function() {
            return {
                x: +this.node.getAttribute("x1"),
                y: +this.node.getAttribute("y1")
            };
        },
        getEndPosition: function() {
            return {
                x: +this.node.getAttribute("x2"),
                y: +this.node.getAttribute("y2")
            };
        }
    });
});
/**
 * 蒙板
 */
define("graphic/mask", [ "core/class", "core/config", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/shapecontainer", "graphic/container" ], function(require, exports, module) {
    var Class = require("core/class");
    var Shape = require("graphic/shape");
    var Mask = Class.createClass("Mask", {
        base: Shape,
        mixins: [ require("graphic/shapecontainer") ],
        constructor: function() {
            this.callBase("mask");
        },
        mask: function(shape) {
            shape.getNode().setAttribute("mask", "url(#" + this.getId() + ")");
            return this;
        }
    });
    Class.extendClass(Shape, {
        maskWith: function(mask) {
            mask.mask(this);
            return this;
        }
    });
    return Mask;
});
define("graphic/matrix", [ "core/utils", "graphic/vector", "core/class", "core/config" ], function(require, exports, module) {
    var utils = require("core/utils");
    var mPattern = /matrix\((.+)\)/i;
    var Vector = require("graphic/vector");
    // 注意，合并的结果是先执行m2，再执行m1的结果
    function mergeMatrixData(m2, m1) {
        return {
            a: m1.a * m2.a + m1.c * m2.b,
            b: m1.b * m2.a + m1.d * m2.b,
            c: m1.a * m2.c + m1.c * m2.d,
            d: m1.b * m2.c + m1.d * m2.d,
            e: m1.a * m2.e + m1.c * m2.f + m1.e,
            f: m1.b * m2.e + m1.d * m2.f + m1.f
        };
    }
    function d2r(deg) {
        return deg * Math.PI / 180;
    }
    var Matrix = require("core/class").createClass("Matrix", {
        constructor: function() {
            if (arguments.length) {
                this.setMatrix.apply(this, arguments);
            } else {
                this.setMatrix(1, 0, 0, 1, 0, 0);
            }
        },
        translate: function(x, y) {
            this.m = mergeMatrixData(this.m, {
                a: 1,
                c: 0,
                e: x,
                b: 0,
                d: 1,
                f: y
            });
            return this;
        },
        rotate: function(deg) {
            var rad = d2r(deg);
            var sin = Math.sin(rad), cos = Math.cos(rad);
            this.m = mergeMatrixData(this.m, {
                a: cos,
                c: -sin,
                e: 0,
                b: sin,
                d: cos,
                f: 0
            });
            return this;
        },
        scale: function(sx, sy) {
            if (sy === undefined) {
                sy = sx;
            }
            this.m = mergeMatrixData(this.m, {
                a: sx,
                c: 0,
                e: 0,
                b: 0,
                d: sy,
                f: 0
            });
            return this;
        },
        skew: function(degX, degY) {
            if (degY === undefined) {
                degY = degX;
            }
            var tx = Math.tan(d2r(degX)), ty = Math.tan(d2r(degY));
            this.m = mergeMatrixData(this.m, {
                a: 1,
                c: tx,
                e: 0,
                b: ty,
                d: 1,
                f: 0
            });
            return this;
        },
        setMatrix: function(a, b, c, d, e, f) {
            if (arguments.length === 1) {
                this.m = utils.clone(arguments[0]);
            } else {
                this.m = {
                    a: a,
                    b: b,
                    c: c,
                    d: d,
                    e: e,
                    f: f
                };
            }
            return this;
        },
        getMatrix: function() {
            return utils.clone(this.m);
        },
        getTranslate: function() {
            var m = this.m;
            return {
                x: m.e / m.a,
                y: m.f / m.d
            };
        },
        mergeMatrix: function(matrix) {
            return new Matrix(mergeMatrixData(this.m, matrix.m));
        },
        merge: function(matrix) {
            return this.mergeMatrix(matrix);
        },
        toString: function() {
            var m = this.m;
            return "matrix(" + [ m.a, m.b, m.c, m.d, m.e, m.f ].join(", ") + ")";
        },
        transformPoint: function(x, y) {
            return Matrix.transformPoint(x, y, this.m);
        },
        transformBox: function(box) {
            return Matrix.transformBox(box, this.m);
        }
    });
    Matrix.parse = function(str) {
        var match;
        var f = parseFloat;
        if (match = mPattern.exec(str)) {
            var values = match[1].split(",");
            if (values.length != 6) {
                values = match[1].split(" ");
            }
            return new Matrix({
                a: f(values[0]),
                b: f(values[1]),
                c: f(values[2]),
                d: f(values[3]),
                e: f(values[4]),
                f: f(values[5])
            });
        }
        return new Matrix();
    };
    Matrix.transformPoint = function(x, y, m) {
        return new Vector(m.a * x + m.c * y + m.e, m.b * x + m.d * y + m.f);
    };
    Matrix.transformBox = function(box, matrix) {
        var xMin = Number.MAX_VALUE, xMax = -Number.MAX_VALUE, yMin = Number.MAX_VALUE, yMax = -Number.MAX_VALUE;
        var bps = [ [ box.x, box.y ], [ box.x + box.width, box.y ], [ box.x, box.y + box.height ], [ box.x + box.width, box.y + box.height ] ];
        var bp, rp, rps = [];
        while (bp = bps.pop()) {
            rp = Matrix.transformPoint(bp[0], bp[1], matrix);
            rps.push(rp);
            xMin = Math.min(xMin, rp.x);
            xMax = Math.max(xMax, rp.x);
            yMin = Math.min(yMin, rp.y);
            yMax = Math.max(yMax, rp.y);
        }
        return {
            x: xMin,
            y: yMin,
            width: xMax - xMin,
            height: yMax - yMin,
            closurePoints: rps,
            left: xMin,
            right: xMax,
            top: yMin,
            bottom: yMax
        };
    };
    return Matrix;
});
/**
 * 调色板
 */
define("graphic/palette", [ "graphic/standardcolor", "graphic/color", "core/utils", "core/class", "core/config" ], function(require, exports, module) {
    //标准color
    var StandardColor = require("graphic/standardcolor"), Color = require("graphic/color"), Utils = require("core/utils");
    var Palette = require("core/class").createClass("Palette", {
        constructor: function() {
            this.color = {};
        },
        /*
         * 获取颜色名称所对应的颜色值的Color对象
         * @param name 需要获取的颜色名称
         * @return 对应颜色名称的color对象， 如果未找到对应的名称， 则返回null
         */
        get: function(name) {
            var colorValue = this.color[name] || StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || "";
            if (colorValue) {
                return new Color(colorValue);
            }
            return null;
        },
        /*
         * 获取给定名称的颜色的hex值表示
         * @param name 需要获取的颜色名称
         * @return 如果找到对应的名称， 则返回该名称所对应的hex格式的值， 否则， 返回一个空字符串
         */
        getColorValue: function(name) {
            return this.color[name] || StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || "";
        },
        /*
         * 向调色板实例添加自己独有的颜色名称，对已存在的颜色名称， 将会覆盖掉
         * @param name 新添加的颜色名称
         * @param value 新添加的颜色名称所对应的值， 可以是一个合法的颜色字符串或者是一个color对象
         * @return 新添加的颜色的值
         */
        add: function(name, value) {
            if (typeof value === "string") {
                this.color[name] = new Color(value).toRGBA();
            } else {
                this.color[name] = value.toRGBA();
            }
            return value;
        },
        /*
         * 删除调色板实例上用户自己添加的颜色， 该方法不能删除内置的颜色
         * @param name 需要删除的颜色名称
         * @return 删除是否成功的bool值
         */
        remove: function(name) {
            if (this.color.hasOwnProperty(name)) {
                delete this.color[name];
                return true;
            }
            return false;
        }
    });
    Utils.extend(Palette, {
        getColor: function(name) {
            var colorValue = StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name];
            if (colorValue) {
                return new Color(colorValue);
            }
            return null;
        },
        /*
         * 通过给定的名字获取标准的颜色值表示， 返回的值以hex的方式提供
         * @param name 需要获取的标准颜色名称
         * @return 名字所对应的颜色值的hex表示， 如果未找到对应名称的值， 则返回一个空字符串
         */
        getColorValue: function(name) {
            return StandardColor.EXTEND_STANDARD[name] || StandardColor.COLOR_STANDARD[name] || "";
        },
        /*
         * 向调色板添加颜色名称，新添加的颜色对所有的调色板对象都可见
         * 对已存在的颜色名称， 将会覆盖掉
         * @param name 新添加的颜色名称
         * @param value 新添加的颜色名称所对于的值， 应该是一个hex格式的颜色字符串， 如： ”#ff0000“
         * @return 新添加的颜色的值
         */
        addColor: function(name, value) {
            if (typeof value === "string") {
                StandardColor.EXTEND_STANDARD[name] = new Color(value).toRGBA();
            } else {
                StandardColor.EXTEND_STANDARD[name] = value.toRGBA();
            }
            return value;
        },
        /*
         * 删除用户自己添加的颜色， 该方法不能删除内置的颜色， 该方法不会影响调色板实例自由的颜色
         * @param name 需要删除的颜色名称
         * @return 删除是否成功的bool值
         */
        removeColor: function(name) {
            if (StandardColor.EXTEND_STANDARD.hasOwnProperty(name)) {
                delete StandardColor.EXTEND_STANDARD[name];
                return true;
            }
            return false;
        }
    });
    return Palette;
});
define("graphic/paper", [ "core/class", "core/config", "core/utils", "graphic/svg", "graphic/container", "graphic/shapecontainer", "graphic/shape", "graphic/viewbox", "graphic/eventhandler", "graphic/shapeevent", "graphic/styled", "graphic/matrix", "graphic/vector", "graphic/data", "graphic/pen" ], function(require, exports, module) {
    var Class = require("core/class");
    var utils = require("core/utils");
    var svg = require("graphic/svg");
    var Container = require("graphic/container");
    var ShapeContainer = require("graphic/shapecontainer");
    var ViewBox = require("graphic/viewbox");
    var EventHandler = require("graphic/eventhandler");
    var Styled = require("graphic/styled");
    var Matrix = require("graphic/matrix");
    var Paper = Class.createClass("Paper", {
        mixins: [ ShapeContainer, EventHandler, Styled, ViewBox ],
        constructor: function(container) {
            this.callBase();
            this.node = this.createSVGNode();
            this.node.paper = this;
            this.node.appendChild(this.resourceNode = svg.createNode("defs"));
            this.node.appendChild(this.shapeNode = svg.createNode("g"));
            this.resources = new Container();
            this.setWidth("100%").setHeight("100%");
            if (container) {
                this.renderTo(container);
            }
            this.callMixin();
        },
        renderTo: function(container) {
            if (utils.isString(container)) {
                container = document.getElementById(container);
            }
            this.container = container;
            container.appendChild(this.node);
        },
        createSVGNode: function() {
            var node = svg.createNode("svg");
            node.setAttribute("xmlns", "http://www.w3.org/2000/svg");
            node.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
            return node;
        },
        getNode: function() {
            return this.node;
        },
        getContainer: function() {
            return this.container;
        },
        getWidth: function() {
            return +this.node.getAttribute("width");
        },
        setWidth: function(width) {
            this.node.setAttribute("width", width);
            return this;
        },
        getHeight: function() {
            return +this.node.getAttribute("height");
        },
        setHeight: function(height) {
            this.node.setAttribute("height", height);
            return this;
        },
        setViewPort: function(cx, cy, zoom) {
            var viewport, box;
            if (arguments.length == 1) {
                viewport = arguments[0];
                cx = viewport.center.x;
                cy = viewport.center.y;
                zoom = viewport.zoom;
            }
            zoom = zoom || 1;
            box = this.getViewBox();
            var matrix = new Matrix();
            var dx = box.x + box.width / 2 - cx, dy = box.y + box.height / 2 - cy;
            matrix.translate(-cx, -cy);
            matrix.scale(zoom);
            matrix.translate(cx, cy);
            matrix.translate(dx, dy)
            this.shapeNode.setAttribute("transform", matrix);
            this.viewport = {
                center: {
                    x: cx,
                    y: cy
                },
                offset: {
                    x: dx,
                    y: dy
                },
                zoom: zoom
            };
            return this;
        },
        getViewPort: function() {
            if (!this.viewport) {
                var box = this.getViewBox();
                this.viewport = {
                    zoom: 1,
                    center: {
                        x: box.x + box.width / 2,
                        y: box.y + box.height / 2
                    },
                    offset: {
                        x: 0,
                        y: 0
                    }
                };
            }
            return this.viewport;
        },
        addResource: function(resource) {
            this.resources.appendItem(resource);
            if (resource.node) {
                this.resourceNode.appendChild(resource.node);
            }
            return this;
        },
        removeResource: function(resource) {
            if (resource.remove) {
                resource.remove();
            }
            if (resource.node) {
                this.resourceNode.removeChild(resource.node);
            }
            return this;
        },
        getPaper: function() {
            return this;
        }
    });
    var Shape = require("graphic/shape");
    Class.extendClass(Shape, {
        getPaper: function() {
            var parent = this.container;
            while (parent && parent instanceof Paper === false) {
                parent = parent.container;
            }
            return parent;
        }
    });
    return Paper;
});
define("graphic/path", [ "core/utils", "core/class", "core/config", "graphic/shape", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    var Utils = require("core/utils");
    var createClass = require("core/class").createClass;
    var Shape = require("graphic/shape");
    var svg = require("graphic/svg");
    var config = require("core/config");
    var PathDrawer = createClass("PathDrawer", {
        constructor: function(path) {
            this.path = path;
            this.__clear = false;
        },
        appendData: function(data) {
            var originData = this.path.getPathData();
            if (this.__clear) {
                originData = "";
                this.__clear = false;
            }
            if (originData) {
                this.path.setPathData(originData + " " + data.join(" "));
            } else {
                this.path.setPathData(data.join(" "));
            }
            return this;
        },
        moveTo: function(x, y) {
            return this.appendData([ "M", x, y ]);
        },
        moveBy: function(dx, dy) {
            return this.appendData([ "m", dx, dy ]);
        },
        lineTo: function(x, y) {
            return this.appendData([ "L", x, y ]);
        },
        lineBy: function(dx, dy) {
            return this.appendData([ "l", dx, dy ]);
        },
        arcTo: function(rx, ry, xr, laf, sf, x, y) {
            return this.appendData([ "A", rx, ry, xr, laf, sf, x, y ]);
        },
        arcBy: function(rx, ry, xr, laf, sf, dx, dy) {
            return this.appendData([ "a", rx, ry, xr, laf, sf, dx, dy ]);
        },
        carcTo: function(r, x, y, laf, sf) {
            return this.arcTo(r, r, 0, laf || 0, sf || 0, x, y);
        },
        carcBy: function(r, dx, dy, laf, sf) {
            return this.arcBy(r, r, 0, laf || 0, sf || 0, dx, dy);
        },
        bezierTo: function(x1, y1, x2, y2, x, y) {
            return this.appendData([ "C", x1, y1, x2, y2, x, y ]);
        },
        bezierBy: function(dx1, dy1, dx2, dy2, dx, dy) {
            return this.appendData([ "c", dx1, dy1, dx2, dy2, dx, dy ]);
        },
        close: function() {
            return this.appendData([ "z" ]);
        },
        clear: function() {
            this.__clear = true;
            this.path.setPathData("M 0 0");
            return this;
        }
    });
    function flatten(arr) {
        var result = [], length = arr.length;
        for (var i = 0; i < length; i++) {
            if (arr[i] instanceof Array) {
                result = result.concat(flatten(arr[i]));
            } else {
                result.push(arr[i]);
            }
        }
        return result;
    }
    return createClass("Path", {
        base: Shape,
        constructor: function(data) {
            this.callBase("path");
            if (data) {
                this.setPathData(data);
            }
            this.node.setAttribute("fill", svg.defaults.fill);
            this.node.setAttribute("stroke", svg.defaults.stroke);
        },
        setPathData: function(data) {
            if (!data) {
                return;
            }
            // add support for path segment
            if (data instanceof Array) {
                data = flatten(data).join(" ");
            }
            this.pathdata = data;
            var path = this;
            if (config.debug) {
                path.node.setAttribute("d", data);
                this.trigger("shapeupdate", {
                    type: "pathdata"
                });
            } else {
                // lazy dump data attribute
                clearTimeout(this.lazyDumpId);
                this.lazyDumpId = setTimeout(function() {
                    path.node.setAttribute("d", data);
                    this.trigger("shapeupdate", {
                        type: "pathdata"
                    });
                });
            }
            return this;
        },
        getPathData: function() {
            return this.pathdata || "";
        },
        getDrawer: function() {
            return new PathDrawer(this);
        },
        isClosed: function() {
            var data = this.getPathData();
            return !!~data.indexOf("z") || !!~data.indexOf("Z");
        }
    });
});
define("graphic/patternbrush", [ "graphic/defbrush", "graphic/svg", "core/class", "graphic/shapecontainer", "graphic/container", "core/utils", "graphic/shape", "core/config" ], function(require, exports, module) {
    var DefBrush = require("graphic/defbrush");
    var ShapeContainer = require("graphic/shapecontainer");
    var svg = require("graphic/svg");
    return require("core/class").createClass("PatternBrush", {
        base: DefBrush,
        mixins: [ ShapeContainer ],
        constructor: function() {
            this.callBase("pattern");
            this.node.setAttribute("patternUnits", "userSpaceOnUse");
        },
        setX: function(x) {
            this.x = x;
            this.node.setAttribute("x", x);
            return this;
        },
        setY: function(y) {
            this.y = y;
            this.node.setAttribute("y", y);
            return this;
        },
        setWidth: function(width) {
            this.width = width;
            this.node.setAttribute("width", width);
            return this;
        },
        setHeight: function(height) {
            this.height = height;
            this.node.setAttribute("height", height);
            return this;
        },
        getWidth: function() {
            return this.width;
        },
        getHeight: function() {
            return this.height;
        }
    });
});
define("graphic/pen", [ "graphic/color", "core/utils", "graphic/standardcolor", "core/class", "core/config" ], function(require, exports, module) {
    var Color = require("graphic/color");
    return require("core/class").createClass("Pen", {
        constructor: function(color, width) {
            this.color = color instanceof Color ? color : new Color(color);
            this.width = width || 1;
            this.linecap = null;
            this.linejoin = null;
            this.dashArray = null;
            this.opacity = this.color.get("a");
        },
        getColor: function() {
            return this.color;
        },
        setColor: function(color) {
            if (typeof color == "string") {
                color = new Color(color);
            }
            this.color = color;
            this.opacity = this.color.get("a");
            return this;
        },
        getWidth: function() {
            return this.width;
        },
        setWidth: function(width) {
            this.width = width;
            return this;
        },
        getOpacity: function() {
            return this.opacity;
        },
        setOpacity: function(opacity) {
            this.opacity = opacity;
        },
        getLineCap: function() {
            return this.linecap;
        },
        setLineCap: function(linecap) {
            this.linecap = linecap;
            return this;
        },
        getLineJoin: function() {
            return this.linejoin;
        },
        setLineJoin: function(linejoin) {
            this.linejoin = linejoin;
            return this;
        },
        getDashArray: function() {
            return this.dashArray;
        },
        setDashArray: function(dashArray) {
            this.dashArray = dashArray;
            return this;
        },
        stroke: function(shape) {
            var node = shape.node;
            node.setAttribute("stroke", this.getColor().toString());
            node.setAttribute("stroke-width", this.getWidth());
            if (this.getOpacity() < 1) {
                node.setAttribute("stroke-opacity", this.getOpacity());
            }
            if (this.getLineCap()) {
                node.setAttribute("stroke-linecap", this.getLineCap());
            }
            if (this.getLineJoin()) {
                node.setAttribute("stroke-linejoin", this.getLineJoin());
            }
            if (this.getDashArray()) {
                node.setAttribute("stroke-dasharray", this.getDashArray());
            }
        }
    });
});
/*
 * 点对象抽象
 */
define("graphic/point", [ "core/class", "core/config" ], function(require, exports, module) {
    return require("core/class").createClass("Point", {
        constructor: function(x, y) {
            this.px = x || 0;
            this.py = y || 0;
        },
        setPoint: function(x, y) {
            this.px = x;
            this.py = y;
            return this;
        },
        getPoint: function() {
            return {
                x: this.px,
                y: this.py
            };
        },
        setX: function(x) {
            this.px = x;
            return this;
        },
        getX: function() {
            return this.px;
        },
        setY: function(y) {
            this.py = y;
            return this;
        },
        getY: function() {
            return this.py;
        }
    });
});
/**
 * 点集合容器
 */
define("graphic/pointcontainer", [ "core/class", "core/config", "graphic/container" ], function(require, exports, module) {
    return require("core/class").createClass("PointContainer", {
        base: require("graphic/container"),
        constructor: function() {
            this.callBase();
        },
        addPoint: function(point, pos) {
            return this.addItem.apply(this, arguments);
        },
        prependPoint: function() {
            return this.prependItem.apply(this, arguments);
        },
        appendPoint: function() {
            return this.appendItem.apply(this, arguments);
        },
        removePoint: function(pos) {
            return this.removeItem.apply(this, arguments);
        },
        addPoints: function() {
            return this.addItems.apply(this, arguments);
        },
        setPoints: function() {
            return this.setItems.apply(this, arguments);
        },
        getPoint: function() {
            return this.getItem.apply(this, arguments);
        },
        getPoints: function() {
            return this.getItems.apply(this, arguments);
        },
        getFirstPoint: function() {
            return this.getFirstItem.apply(this, arguments);
        },
        getLastPoint: function() {
            return this.getLastItem.apply(this, arguments);
        }
    });
});
/*
 * 通过点来决定图形的公共父类
 */
define("graphic/poly", [ "core/utils", "core/class", "core/config", "graphic/path", "graphic/shape", "graphic/svg", "graphic/pointcontainer", "graphic/container" ], function(require, exports, module) {
    var Utils = require("core/utils");
    return require("core/class").createClass("Poly", {
        base: require("graphic/path"),
        mixins: [ require("graphic/pointcontainer") ],
        constructor: function(points, closeable) {
            this.callBase();
            //是否可闭合
            this.closeable = !!closeable;
            this.setPoints(points || []);
            this.changeable = true;
            this.update();
        },
        //当点集合发生变化时采取的动作
        onContainerChanged: function() {
            if (this.changeable) {
                this.update();
            }
        },
        update: function() {
            var drawer = this.getDrawer(), points = this.getPoints();
            drawer.clear();
            if (!points.length) {
                return this;
            }
            drawer.moveTo(points[0].getX(), points[0].getY());
            for (var i = 1, point, len = points.length; i < len; i++) {
                point = points[i];
                drawer.lineTo(point.getX(), point.getY());
            }
            if (this.closeable && points.length > 2) {
                drawer.close();
            }
            return this;
        }
    });
});
define("graphic/polygon", [ "core/class", "core/config", "graphic/poly", "core/utils", "graphic/path", "graphic/pointcontainer" ], function(require, exports, module) {
    return require("core/class").createClass("Polygon", {
        base: require("graphic/poly"),
        constructor: function(points) {
            this.callBase(points, true);
        }
    });
});
define("graphic/polyline", [ "core/class", "core/config", "graphic/poly", "core/utils", "graphic/path", "graphic/pointcontainer" ], function(require, exports, module) {
    return require("core/class").createClass("Polyline", {
        base: require("graphic/poly"),
        constructor: function(points) {
            this.callBase(points);
        }
    });
});
define("graphic/radialgradientbrush", [ "graphic/gradientbrush", "graphic/svg", "graphic/defbrush", "graphic/color", "core/class", "core/config" ], function(require, exports, module) {
    var GradientBrush = require("graphic/gradientbrush");
    return require("core/class").createClass("RadialGradientBrush", {
        base: GradientBrush,
        constructor: function(builder) {
            this.callBase("radialGradient");
            this.setCenter(.5, .5);
            this.setFocal(.5, .5);
            this.setRadius(.5);
            if (typeof builder == "function") {
                builder.call(this, this);
            }
        },
        setCenter: function(cx, cy) {
            this.node.setAttribute("cx", cx);
            this.node.setAttribute("cy", cy);
            return this;
        },
        getCenter: function() {
            return {
                x: +this.node.getAttribute("cx"),
                y: +this.node.getAttribute("cy")
            };
        },
        setFocal: function(fx, fy) {
            this.node.setAttribute("fx", fx);
            this.node.setAttribute("fy", fy);
            return this;
        },
        getFocal: function() {
            return {
                x: +this.node.getAttribute("fx"),
                y: +this.node.getAttribute("fy")
            };
        },
        setRadius: function(r) {
            this.node.setAttribute("r", r);
            return this;
        },
        getRadius: function() {
            return +this.node.getAttribute("r");
        }
    });
});
define("graphic/rect", [ "core/utils", "core/class", "core/config", "graphic/path", "graphic/shape", "graphic/svg" ], function(require, exports, module) {
    var RectUtils = {}, Utils = require("core/utils");
    Utils.extend(RectUtils, {
        //根据传递进来的width、height和radius属性，
        //获取最适合的radius值
        formatRadius: function(width, height, radius) {
            var minValue = Math.floor(Math.min(width / 2, height / 2));
            return Math.min(minValue, radius);
        },
        getPathData: function(x, y, width, height, radius) {
            var pathData = null;
            //直角
            if (radius === 0) {
                pathData = [ "M " + x + "," + y, " h " + width, " v " + height, " h " + -width, " Z" ];
            } else {
                width -= 2 * radius;
                height -= 2 * radius;
                pathData = [ "M " + (x + radius) + "," + y, " h " + width, " a " + radius + " " + radius + " 0 0 1 " + radius + " " + radius, " v " + height, " a " + radius + " " + radius + " 0 0 1 " + -radius + " " + radius, " h " + -width, " a " + radius + " " + radius + " 0 0 1 " + -radius + " " + -radius, " v " + -height, " a " + radius + " " + radius + " 0 0 1 " + radius + " " + -radius, " Z" ];
            }
            return pathData.join("");
        }
    });
    return require("core/class").createClass("Rect", {
        base: require("graphic/path"),
        constructor: function(width, height, x, y, radius) {
            this.callBase();
            this.x = x || 0;
            this.y = y || 0;
            this.width = width || 0;
            this.height = height || 0;
            this.radius = RectUtils.formatRadius(this.width, this.height, radius || 0);
            this.update();
        },
        update: function() {
            var pathData = RectUtils.getPathData(this.x, this.y, this.width, this.height, this.radius);
            this.setPathData(pathData);
            return this;
        },
        setWidth: function(width) {
            this.width = width;
            return this.update();
        },
        setHeight: function(height) {
            this.height = height;
            return this.update();
        },
        setSize: function(width, height) {
            this.width = width;
            this.height = height;
            return this.update();
        },
        getRadius: function() {
            return this.radius;
        },
        setRadius: function(radius) {
            this.radius = radius;
            return this.update();
        },
        getPosition: function() {
            return {
                x: this.x,
                y: this.y
            };
        },
        setPosition: function(x, y) {
            this.x = x;
            this.y = y;
            return this.update();
        },
        getWidth: function() {
            return this.width;
        },
        getHeight: function() {
            return this.height;
        },
        getPositionX: function() {
            return this.x;
        },
        getPositionY: function() {
            return this.y;
        },
        setPositionX: function(x) {
            this.x = x;
            return this.update();
        },
        setPositionY: function(y) {
            this.y = y;
            return this.update();
        }
    });
});
define("graphic/shape", [ "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/shapeevent", "core/class", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/vector", "graphic/pen", "graphic/color", "core/config" ], function(require, exports, module) {
    var svg = require("graphic/svg");
    var utils = require("core/utils");
    var EventHandler = require("graphic/eventhandler");
    var Styled = require("graphic/styled");
    var Data = require("graphic/data");
    var Matrix = require("graphic/matrix");
    var Pen = require("graphic/pen");
    return require("core/class").createClass("Shape", {
        mixins: [ EventHandler, Styled, Data ],
        constructor: function(tagName) {
            this.node = svg.createNode(tagName);
            this.node.shape = this;
            this.callMixin();
        },
        getId: function() {
            return this.node.id;
        },
        setId: function(id) {
            this.node.id = id;
            return this;
        },
        getNode: function() {
            return this.node;
        },
        getBoundaryBox: function() {
            var box;
            try {
                box = this.node.getBBox();
            } catch (e) {
                box = {
                    x: this.node.clientLeft,
                    y: this.node.clientTop,
                    width: this.node.clientWidth,
                    height: this.node.clientHeight
                };
            }
            return box;
        },
        getRenderBox: function(refer) {
            function isAncestorOf(container, shape) {
                var parent = shape.container;
                while (parent && parent != container) {
                    parent = parent.container;
                }
                return !!parent;
            }
            if (refer === undefined) {
                refer = this;
            } else if (refer === "top") {
                refer = this.getPaper() || this;
            } else if (!isAncestorOf(refer, this)) {
                refer = this;
            }
            var box = this.getBoundaryBox();
            var current = this;
            var matrix = current.getTransform();
            while (current != refer) {
                current = current.container;
                if (current.getTransform) {
                    matrix = matrix.merge(current.getTransform());
                }
            }
            return matrix.transformBox(box);
        },
        getWidth: function() {
            return this.getRenderBox().width;
        },
        getHeight: function() {
            return this.getRenderBox().height;
        },
        getSize: function() {
            var box = this.getRenderBox();
            delete box.x;
            delete box.y;
            return box;
        },
        setOpacity: function(value) {
            this.node.setAttribute("opacity", value);
            return this;
        },
        getOpacity: function() {
            var opacity = this.node.getAttribute("opacity");
            return opacity ? +opacity : 1;
        },
        getTransform: function() {
            return Matrix.parse(this.node.getAttribute("transform"));
        },
        setTransform: function(matrix) {
            this.node.setAttribute("transform", matrix.toString());
            this.trigger("shapeupdate", {
                type: "transform"
            });
            return this;
        },
        resetTransform: function() {
            this.node.removeAttribute("transform");
            this.trigger("shapeupdate", {
                type: "transform"
            });
            return this;
        },
        mergeTransform: function(matrix) {
            return this.setTransform(this.getTransform().mergeMatrix(matrix));
        },
        getAnchor: function() {
            if (this.anchor && this.anchor.x !== undefined) {
                return this.anchor;
            }
            var anchor = anchor || "center";
            var rbox = this.getRenderBox();
            var value = {
                x: rbox.x + rbox.width / 2,
                y: rbox.y + rbox.height / 2
            };
            if (~anchor.indexOf("left")) {
                value.x = rbox.x;
            }
            if (~anchor.indexOf("right")) {
                value.x = rbox.x + rbox.width;
            }
            if (~anchor.indexOf("top")) {
                value.y = rbox.y;
            }
            if (~anchor.indexOf("bottom")) {
                value.y = rbox.y + rbox.height;
            }
            return value;
        },
        setAnchor: function(ax, ay) {
            if (arguments.length === 1) {
                this.anchor = ax;
            } else {
                this.anchor = {
                    x: ax,
                    y: ay
                };
            }
            return this;
        },
        resetAnchor: function() {
            delete this.anchor;
            return this;
        },
        translate: function(dx, dy) {
            if (dy === undefined) {
                dy = 0;
            }
            return this.mergeTransform(new Matrix().translate(dx, dy));
        },
        rotate: function(deg) {
            var a = this.getAnchor();
            return this.mergeTransform(new Matrix().translate(-a.x, -a.y).rotate(deg).translate(a.x, a.y));
        },
        scale: function(sx, sy) {
            var a = this.getAnchor();
            if (sy === undefined) {
                sy = sx;
            }
            return this.mergeTransform(new Matrix().translate(-a.x, -a.y).scale(sx, sy).translate(a.x, a.y));
        },
        skew: function(sx, sy) {
            var a = this.getAnchor();
            if (sy === undefined) {
                sy = sx;
            }
            return this.mergeTransform(new Matrix().translate(-a.x, -a.y).skew(sx, sy).translate(a.x, a.y));
        },
        stroke: function(pen, width) {
            if (pen && pen.stroke) {
                pen.stroke(this);
            } else {
                // 字符串或重写了 toString 的对象
                this.node.setAttribute("stroke", pen.toString());
                if (width) {
                    this.node.setAttribute("stroke-width", width);
                }
            }
            return this;
        },
        fill: function(brush) {
            if (brush && brush.fill) {
                brush.fill(this);
            } else {
                // 字符串或重写了 toString 的对象
                this.node.setAttribute("fill", brush.toString());
            }
            return this;
        },
        setAttr: function(a, v) {
            var me = this;
            if (utils.isObject(a)) {
                utils.each(a, function(val, key) {
                    me.setAttr(key, val);
                });
            }
            if (v === undefined || v === null || v === "") {
                this.node.removeAttribute(a);
            } else {
                this.node.setAttribute(a, v);
            }
        },
        getAttr: function(a) {
            return this.node.getAttribute(a);
        }
    });
});
define("graphic/shapecontainer", [ "graphic/container", "core/class", "core/utils", "core/config", "graphic/shape", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    var Container = require("graphic/container");
    var utils = require("core/utils");
    var ShapeContainer = require("core/class").createClass("ShapeContainer", {
        base: Container,
        isShapeContainer: true,
        /* private */
        handleAdd: function(shape, index) {
            var parent = this.getShapeNode();
            parent.insertBefore(shape.node, parent.childNodes[index] || null);
            shape.trigger("add", {
                container: this
            });
            if (shape.notifyTreeModification) {
                shape.notifyTreeModification("treeadd", this);
            }
        },
        /* private */
        handleRemove: function(shape, index) {
            var parent = this.getShapeNode();
            parent.removeChild(shape.node);
            shape.trigger("remove", {
                container: this
            });
            if (shape.notifyTreeModification) {
                shape.notifyTreeModification("treeremove", this);
            }
        },
        /* private */
        notifyTreeModification: function(type, container) {
            this.eachItem(function(index, shape) {
                if (shape instanceof ShapeContainer) {
                    shape.notifyTreeModification(type, container);
                }
                shape.trigger(type, {
                    container: container
                });
            });
        },
        /* public */
        getShape: function(index) {
            return this.getItem(index);
        },
        /* public */
        addShape: function(shape, index) {
            return this.addItem(shape, index);
        },
        appendShape: function(shape) {
            return this.addShape(shape);
        },
        prependShape: function(shape) {
            return this.addShape(shape, 0);
        },
        replaceShape: function(replacer, origin) {
            var index = this.indexOf(origin);
            if (index === -1) {
                return;
            }
            this.removeShape(index);
            this.addShape(replacer, index);
            return this;
        },
        addShapeBefore: function(shape, refer) {
            var index = this.indexOf(refer);
            return this.addShape(shape, index);
        },
        addShapeAfter: function(shape, refer) {
            var index = this.indexOf(refer);
            return this.addShape(shape, index === -1 ? undefined : index + 1);
        },
        /* public */
        addShapes: function(shapes) {
            return this.addItems(shapes);
        },
        /* public */
        removeShape: function(index) {
            return this.removeItem(index);
        },
        getShapes: function() {
            return this.getItems();
        },
        getShapesByType: function(name) {
            var shapes = [];
            function getShapes(shape) {
                if (name.toLowerCase() == shape.getType().toLowerCase()) {
                    shapes.push(shape);
                }
                if (shape.isShapeContainer) {
                    utils.each(shape.getShapes(), function(n) {
                        getShapes(n);
                    });
                }
            }
            getShapes(this);
            return shapes;
        },
        /* public */
        getShapeById: function(id) {
            return this.getShapeNode().getElementById(id).shape;
        },
        arrangeShape: function(shape, index) {
            return this.removeShape(shape).addShape(shape, index);
        },
        /* protected */
        getShapeNode: function() {
            return this.shapeNode || this.node;
        }
    });
    var Shape = require("graphic/shape");
    require("core/class").extendClass(Shape, {
        bringTo: function(index) {
            this.container.arrangeShape(this, index);
            return this;
        },
        bringFront: function() {
            return this.bringTo(this.container.indexOf(this) + 1);
        },
        bringBack: function() {
            return this.bringTo(this.container.indexOf(this) - 1);
        },
        bringTop: function() {
            this.container.removeShape(this).addShape(this);
            return this;
        },
        bringRear: function() {
            return this.bringTo(0);
        },
        bringRefer: function(referShape, offset) {
            if (referShape.container) {
                if (this.remove) {
                    this.remove();
                }
                referShape.container.addShape(this, referShape.container.indexOf(referShape) + (offset || 0));
            }
            return this;
        },
        bringAbove: function(referShape) {
            return this.bringRefer(referShape);
        },
        bringBelow: function(referShape) {
            return this.bringRefer(referShape, 1);
        },
        replaceBy: function(newShape) {
            if (this.container) {
                newShape.bringAbove(this);
                this.remove();
            }
            return this;
        }
    });
    return ShapeContainer;
});
/*
 * 图形事件包装类
 * */
define("graphic/shapeevent", [ "graphic/matrix", "core/utils", "graphic/vector", "core/class", "core/config" ], function(require, exprots, module) {
    var Matrix = require("graphic/matrix"), Utils = require("core/utils");
    return require("core/class").createClass("ShapeEvent", {
        constructor: function(event) {
            var target = null;
            // dom 事件封装对象
            if (!Utils.isObject(event.target)) {
                this.type = event.type;
                target = event.target;
                // use标签有特殊属性， 需要区别对待
                if (target.correspondingUseElement) {
                    target = target.correspondingUseElement;
                }
                this.originEvent = event;
                this.targetShape = target.shape || target.paper || event.currentTarget && (event.currentTarget.shape || event.currentTarget.paper);
                if (event.__kity_param) {
                    Utils.extend(this, event.__kity_param);
                }
            } else {
                Utils.extend(this, event);
            }
        },
        preventDefault: function() {
            var evt = this.originEvent;
            if (!evt) {
                return true;
            }
            if (evt.preventDefault) {
                evt.preventDefault();
                return evt.cancelable;
            } else {
                evt.returnValue = false;
                return true;
            }
        },
        //当前鼠标事件在用户坐标系中点击的点的坐标位置
        getPosition: function(touch_index) {
            if (!this.originEvent) {
                return null;
            }
            var eventClient = this.originEvent.touches ? this.originEvent.touches[touch_index || 0] : this.originEvent;
            var clientX = eventClient.clientX, clientY = eventClient.clientY, paper = this.targetShape.getPaper(), //转换过后的点
            transPoint = Matrix.transformPoint(clientX, clientY, paper.node.getScreenCTM().inverse());
            var viewport = paper.getViewPort();
            return {
                x: transPoint.x / viewport.zoom - viewport.offset.x,
                y: transPoint.y / viewport.zoom - viewport.offset.y
            };
        },
        stopPropagation: function() {
            var evt = this.originEvent;
            if (!evt) {
                return true;
            }
            if (evt.stopPropagation) {
                evt.stopPropagation();
            } else {
                evt.cancelBubble = false;
            }
        }
    });
});
/*
 * 图形上的点抽象
 */
define("graphic/shapepoint", [ "core/class", "core/config", "graphic/point" ], function(require, exports, module) {
    return require("core/class").createClass("ShapePoint", {
        base: require("graphic/point"),
        constructor: function(px, py) {
            this.callBase(px, py);
        },
        setX: function(x) {
            this.callBase(x);
            this.update();
            return this;
        },
        setY: function(y) {
            this.callBase(y);
            this.update();
            return this;
        },
        setPoint: function(x, y) {
            this.callBase(x, y);
            this.update();
            return this;
        },
        update: function() {
            if (this.container && this.container.update) {
                this.container.update();
            }
            return this;
        }
    });
});
/**
 * 标准颜色映射
 */
define("graphic/standardcolor", [], {
    COLOR_STANDARD: {
        aliceblue: "#f0f8ff",
        antiquewhite: "#faebd7",
        aqua: "#00ffff",
        aquamarine: "#7fffd4",
        azure: "#f0ffff",
        beige: "#f5f5dc",
        bisque: "#ffe4c4",
        black: "#000000",
        blanchedalmond: "#ffebcd",
        blue: "#0000ff",
        blueviolet: "#8a2be2",
        brown: "#a52a2a",
        burlywood: "#deb887",
        cadetblue: "#5f9ea0",
        chartreuse: "#7fff00",
        chocolate: "#d2691e",
        coral: "#ff7f50",
        cornflowerblue: "#6495ed",
        cornsilk: "#fff8dc",
        crimson: "#dc143c",
        cyan: "#00ffff",
        darkblue: "#00008b",
        darkcyan: "#008b8b",
        darkgoldenrod: "#b8860b",
        darkgray: "#a9a9a9",
        darkgreen: "#006400",
        darkgrey: "#a9a9a9",
        darkkhaki: "#bdb76b",
        darkmagenta: "#8b008b",
        darkolivegreen: "#556b2f",
        darkorange: "#ff8c00",
        darkorchid: "#9932cc",
        darkred: "#8b0000",
        darksalmon: "#e9967a",
        darkseagreen: "#8fbc8f",
        darkslateblue: "#483d8b",
        darkslategray: "#2f4f4f",
        darkslategrey: "#2f4f4f",
        darkturquoise: "#00ced1",
        darkviolet: "#9400d3",
        deeppink: "#ff1493",
        deepskyblue: "#00bfff",
        dimgray: "#696969",
        dimgrey: "#696969",
        dodgerblue: "#1e90ff",
        firebrick: "#b22222",
        floralwhite: "#fffaf0",
        forestgreen: "#228b22",
        fuchsia: "#ff00ff",
        gainsboro: "#dcdcdc",
        ghostwhite: "#f8f8ff",
        gold: "#ffd700",
        goldenrod: "#daa520",
        gray: "#808080",
        green: "#008000",
        greenyellow: "#adff2f",
        grey: "#808080",
        honeydew: "#f0fff0",
        hotpink: "#ff69b4",
        indianred: "#cd5c5c",
        indigo: "#4b0082",
        ivory: "#fffff0",
        khaki: "#f0e68c",
        lavender: "#e6e6fa",
        lavenderblush: "#fff0f5",
        lawngreen: "#7cfc00",
        lemonchiffon: "#fffacd",
        lightblue: "#add8e6",
        lightcoral: "#f08080",
        lightcyan: "#e0ffff",
        lightgoldenrodyellow: "#fafad2",
        lightgray: "#d3d3d3",
        lightgreen: "#90ee90",
        lightgrey: "#d3d3d3",
        lightpink: "#ffb6c1",
        lightsalmon: "#ffa07a",
        lightseagreen: "#20b2aa",
        lightskyblue: "#87cefa",
        lightslategray: "#778899",
        lightslategrey: "#778899",
        lightsteelblue: "#b0c4de",
        lightyellow: "#ffffe0",
        lime: "#00ff00",
        limegreen: "#32cd32",
        linen: "#faf0e6",
        magenta: "#ff00ff",
        maroon: "#800000",
        mediumaquamarine: "#66cdaa",
        mediumblue: "#0000cd",
        mediumorchid: "#ba55d3",
        mediumpurple: "#9370db",
        mediumseagreen: "#3cb371",
        mediumslateblue: "#7b68ee",
        mediumspringgreen: "#00fa9a",
        mediumturquoise: "#48d1cc",
        mediumvioletred: "#c71585",
        midnightblue: "#191970",
        mintcream: "#f5fffa",
        mistyrose: "#ffe4e1",
        moccasin: "#ffe4b5",
        navajowhite: "#ffdead",
        navy: "#000080",
        oldlace: "#fdf5e6",
        olive: "#808000",
        olivedrab: "#6b8e23",
        orange: "#ffa500",
        orangered: "#ff4500",
        orchid: "#da70d6",
        palegoldenrod: "#eee8aa",
        palegreen: "#98fb98",
        paleturquoise: "#afeeee",
        palevioletred: "#db7093",
        papayawhip: "#ffefd5",
        peachpuff: "#ffdab9",
        peru: "#cd853f",
        pink: "#ffc0cb",
        plum: "#dda0dd",
        powderblue: "#b0e0e6",
        purple: "#800080",
        red: "#ff0000",
        rosybrown: "#bc8f8f",
        royalblue: "#4169e1",
        saddlebrown: "#8b4513",
        salmon: "#fa8072",
        sandybrown: "#f4a460",
        seagreen: "#2e8b57",
        seashell: "#fff5ee",
        sienna: "#a0522d",
        silver: "#c0c0c0",
        skyblue: "#87ceeb",
        slateblue: "#6a5acd",
        slategray: "#708090",
        slategrey: "#708090",
        snow: "#fffafa",
        springgreen: "#00ff7f",
        steelblue: "#4682b4",
        tan: "#d2b48c",
        teal: "#008080",
        thistle: "#d8bfd8",
        tomato: "#ff6347",
        turquoise: "#40e0d0",
        violet: "#ee82ee",
        wheat: "#f5deb3",
        white: "#ffffff",
        whitesmoke: "#f5f5f5",
        yellow: "#ffff00"
    },
    //标准扩展
    EXTEND_STANDARD: {}
});
define("graphic/styled", [ "core/class", "core/config" ], function(require, exports, module) {
    // polyfill for ie
    var ClassList = require("core/class").createClass("ClassList", {
        constructor: function(node) {
            this._node = node;
            this._list = node.className.toString().split(" ");
        },
        _update: function() {
            this._node.className = this._list.join(" ");
        },
        add: function(name) {
            this._list.push(name);
            this._update();
        },
        remove: function(name) {
            var index = this._list.indexOf(name);
            if (~index) {
                this._list.splice(index, 1);
            }
            this._update();
        },
        contains: function(name) {
            return ~this._list.indexOf(name);
        }
    });
    function getClassList(node) {
        if (!node.classList) {
            node.classList = new ClassList(node);
        }
        return node.classList;
    }
    return require("core/class").createClass("Styled", {
        addClass: function(name) {
            getClassList(this.node).add(name);
            return this;
        },
        removeClass: function(name) {
            getClassList(this.node).remove(name);
            return this;
        },
        hasClass: function(name) {
            return getClassList(this.node).contains(name);
        },
        setStyle: function(styles) {
            if (arguments.length == 2) {
                this.node.style[arguments[0]] = arguments[1];
                return this;
            }
            for (var name in styles) {
                if (styles.hasOwnProperty(name)) {
                    this.node.style[name] = styles[name];
                }
            }
            return this;
        }
    });
});
define("graphic/svg", [], function(require, exports, module) {
    var doc = document;
    var id = 0;
    var svg = {
        createNode: function(name) {
            var node = doc.createElementNS(svg.ns, name);
            node.id = "kity_" + name + "_" + id++;
            return node;
        },
        defaults: {
            stroke: "none",
            fill: "none"
        },
        xlink: "http://www.w3.org/1999/xlink",
        ns: "http://www.w3.org/2000/svg"
    };
    return svg;
});
define("graphic/text", [ "graphic/textcontent", "graphic/shape", "core/class", "graphic/shapecontainer", "graphic/container", "core/utils", "graphic/svg", "core/config" ], function(require, exports, module) {
    var TextContent = require("graphic/textcontent");
    var ShapeContainer = require("graphic/shapecontainer");
    var svg = require("graphic/svg");
    return require("core/class").createClass("Text", {
        base: TextContent,
        mixins: [ ShapeContainer ],
        constructor: function(content) {
            this.callBase("text");
            if (content !== undefined) {
                this.setContent(content);
            }
        },
        setX: function(x) {
            this.node.setAttribute("x", x);
            return this;
        },
        setPosition: function(x, y) {
            return this.setX(x).setY(y);
        },
        setY: function(y) {
            this.node.setAttribute("y", y);
            return this;
        },
        getX: function() {
            return +this.node.getAttribute("x");
        },
        getY: function() {
            return +this.node.getAttribute("y");
        },
        setTextAnchor: function(anchor) {
            if (anchor == "center") {
                anchor = "middle";
            }
            this.node.setAttribute("text-anchor", anchor);
            // text path
            if (this.shapeNode != this.node) {
                this.shapeNode.setAttribute("startOffset", {
                    start: "0",
                    middle: "50%",
                    end: "100%"
                }[anchor]);
            }
            return this;
        },
        getTextAnchor: function() {
            return this.node.getAttribute("text-anchor") || "start";
        },
        addSpan: function(span) {
            this.addShape(span);
            return this;
        },
        setPath: function(path) {
            var textpath = this.shapeNode;
            if (this.shapeNode == this.node) {
                // 当前还不是 textpath
                textpath = this.shapeNode = svg.createNode("textPath");
                while (this.node.firstChild) {
                    this.shapeNode.appendChild(this.node.firstChild);
                }
                this.node.appendChild(textpath);
            }
            textpath.setAttributeNS(svg.xlink, "xlink:href", "#" + path.node.id);
            this.setAnchor(this.getAnchor());
            return this;
        }
    });
});
define("graphic/textcontent", [ "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "core/class", "core/config" ], function(require, exports, module) {
    var Shape = require("graphic/shape");
    return require("core/class").createClass("TextContent", {
        base: Shape,
        constructor: function(nodeType) {
            // call shape constructor
            this.callBase(nodeType);
            this.shapeNode = this.shapeNode || this.node;
        },
        clearContent: function() {
            while (this.shapeNode.firstChild) {
                this.shapeNode.removeChild(this.shapeNode.firstChild);
            }
            return this;
        },
        setContent: function(content) {
            this.shapeNode.textContent = content;
            return this;
        },
        getContent: function() {
            return this.shapeNode.textContent;
        },
        appendContent: function(content) {
            this.shapeNode.textContent += content;
            return this;
        },
        setSize: function(value) {
            this.fontsize = value;
            this.node.setAttribute("font-size", value);
            return this;
        },
        getSize: function() {
            return this.fontsize;
        },
        getExtentOfChar: function(index) {
            return this.node.getExtentOfChar(index);
        },
        getRotationOfChar: function(index) {
            return this.node.getRotationOfChar(index);
        },
        getCharNumAtPosition: function(x, y) {
            return this.node.getCharNumAtPosition(this.node.viewportElement.createSVGPoint(x, y));
        }
    });
});
define("graphic/textspan", [ "graphic/textcontent", "graphic/shape", "core/class", "graphic/styled", "core/config" ], function(require, exports, module) {
    var TextContent = require("graphic/textcontent");
    var Styled = require("graphic/styled");
    return require("core/class").createClass("TextSpan", {
        base: TextContent,
        mixins: [ Styled ],
        constructor: function(content) {
            this.callBase("tspan");
            this.setContent(content);
        }
    });
});
/*
 * USE 功能
 */
define("graphic/use", [ "graphic/svg", "core/class", "core/config", "graphic/shape", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen" ], function(require, exports, module) {
    var Svg = require("graphic/svg");
    var Class = require("core/class");
    var Use = Class.createClass("Use", {
        base: require("graphic/shape"),
        constructor: function(shape) {
            var shapeId = null;
            this.callBase("use");
            shapeId = shape.getId();
            if (shapeId) {
                this.node.setAttributeNS(Svg.xlink, "xlink:href", "#" + shapeId);
            }
            // by techird
            // 作为 Use 的图形，如果没有 fill 和 stroke，移除默认的 'none' 值，用于 Use 覆盖
            if (shape.node.getAttribute("fill") === "none") {
                shape.node.removeAttribute("fill");
            }
            if (shape.node.getAttribute("stroke") === "none") {
                shape.node.removeAttribute("stroke");
            }
        }
    });
    var Shape = require("graphic/shape");
    Class.extendClass(Shape, {
        // fast-use
        use: function() {
            return new Use(this);
        }
    });
    return Use;
});
define("graphic/vector", [ "core/class", "core/config" ], function(require, exports, module) {
    var Vector = require("core/class").createClass("Vector", {
        constructor: function(x, y) {
            this.x = x || 0;
            this.y = y || 0;
        },
        length: function() {
            return Math.sqrt(Vector.square(this));
        }
    });
    Vector.add = function(p, q) {
        return new Vector(p.x + q.x, p.y + q.y);
    };
    Vector.square = function(p) {
        return p.x * p.x + p.y * p.y;
    };
    Vector.normalize = function(p, l) {
        if (l === undefined) {
            l = 1;
        }
        var factor = l / p.length();
        return new Vector(p.x * factor, p.y * factor);
    };
    Vector.verticalVector = function(p) {
        return new Vector(p.y, -p.x);
    };
    Vector.verticalNormalize = function(p) {
        return Vector.normalize(Vector.verticalVector(p));
    };
    Vector.multipy = function(p, s) {
        return new Vector(p.x * s, p.y * s);
    };
    Vector.reverse = function(p) {
        return Vector.multipy(p, -1);
    };
    Vector.dot = function(p, q) {
        return p.x * q.x + p.y * q.y;
    };
    Vector.minus = function(p, q) {
        return new Vector(p.x - q.x, p.y - q.y);
    };
    // p 在 q 上的投影
    Vector.projection = function(p, q) {
        var factor = Vector.dot(p, q) / Vector.square(q);
        return Vector.multipy(q, factor);
    };
    // from p1 to p2
    Vector.fromPoints = function(p1, p2) {
        return new Vector(p2.x - p1.x, p2.y - p1.y);
    };
    Vector.fromPolar = function(d, a, isRad) {
        if (isRad !== true) {
            a = a * Math.PI / 180;
        }
        return new Vector(d * Math.cos(a), d * Math.sin(a));
    };
    return Vector;
});
define("graphic/view", [ "graphic/shapecontainer", "graphic/container", "core/utils", "core/class", "graphic/shape", "graphic/viewbox", "core/config", "graphic/view" ], function(require, exports, module) {
    var ShapeContainer = require("graphic/shapecontainer");
    var ViewBox = require("graphic/viewbox");
    return require("core/class").createClass("View", {
        mixins: [ ShapeContainer, ViewBox ],
        base: require("graphic/view"),
        constructor: function() {
            this.callBase("view");
        }
    });
});
define("graphic/viewbox", [ "core/class", "core/config" ], function(require, exports, module) {
    return require("core/class").createClass("ViewBox", {
        getViewBox: function() {
            var attr = this.node.getAttribute("viewBox");
            if (attr === null) {
                // firefox:
                // 1. viewBox 没有设置过的时候获得的是 null
                // 2. svg 标签没有指定绝对大小的时候 clientWidth 和 clientHeigt 为 0，需要在父容器上查找
                // TODO: 第 2 条取得的不准确（假如有 padding 之类的）
                return {
                    x: 0,
                    y: 0,
                    width: this.node.clientWidth || this.node.parentNode.clientWidth,
                    height: this.node.clientHeight || this.node.parentNode.clientHeight
                };
            } else {
                attr = attr.split(" ");
                return {
                    x: +attr[0],
                    y: +attr[1],
                    width: +attr[2],
                    height: +attr[3]
                };
            }
        },
        setViewBox: function(x, y, width, height) {
            this.node.setAttribute("viewBox", [ x, y, width, height ].join(" "));
            return this;
        }
    });
});

/**
 * 模块暴露
 */

( function ( global ) {

    define( 'kity.start', function ( require ) {

        var kity = global.kity = require( 'core/class' );

        require( 'core/utils' ).extend( kity, {

            // core
            Utils: require( "core/utils" ),
            Browser:require("core/browser"),
            // shape
            Bezier: require( 'graphic/bezier' ),
            BezierPoint: require( 'graphic/bezierpoint' ),
            Circle: require( 'graphic/circle' ),
            Clip: require( 'graphic/clip' ),
            Color: require( 'graphic/color' ),
            Curve: require( 'graphic/curve' ),
            Ellipse: require( 'graphic/ellipse' ),
            GradientBrush: require( 'graphic/gradientbrush' ),
            Group: require( 'graphic/group' ),
            Image: require( 'graphic/image' ),
            Line: require( 'graphic/line' ),
            LinearGradientBrush: require( 'graphic/lineargradientbrush' ),
            Mask: require( 'graphic/mask' ),
            Matrix: require( 'graphic/matrix' ),
            Palette: require( 'graphic/palette' ),
            Paper: require( 'graphic/paper' ),
            Path: require( 'graphic/path' ),
            PatternBrush: require( 'graphic/patternbrush' ),
            Pen: require( 'graphic/pen' ),
            Point: require( 'graphic/point' ),
            Polygon: require( 'graphic/polygon' ),
            Polyline: require( 'graphic/polyline' ),
            RadialGradientBrush: require( 'graphic/radialgradientbrush' ),
            Rect: require( 'graphic/rect' ),
            Shape: require( 'graphic/shape' ),
            ShapePoint: require( 'graphic/shapepoint' ),
            Text: require( 'graphic/text' ),
            TextSpan: require( 'graphic/textspan' ),
            Use: require( 'graphic/use' ),
            Vector: require( 'graphic/vector' ),

            // animate
            Animator: require( 'animate/animator' ),
            Easing: require( 'animate/easing' ),
            OpacityAnimator: require( 'animate/opacityanimator' ),
            RotateAnimator: require( 'animate/rotateanimator' ),
            ScaleAnimator: require( 'animate/scaleanimator' ),
            Timeline: require( 'animate/timeline' ),
            TranslateAnimator: require( 'animate/translateanimator' ),

            // filter
            Filter: require( 'filter/filter' ),
            GaussianblurFilter: require( 'filter/gaussianblurfilter' ),
            ProjectionFilter: require( 'filter/projectionfilter' ),

            // effect
            ColorMatrixEffect: require( 'filter/effect/colormatrixeffect' ),
            CompositeEffect: require( 'filter/effect/compositeeffect' ),
            ConvolveMatrixEffect: require( 'filter/effect/convolvematrixeffect' ),
            Effect: require( 'filter/effect/effect' ),
            GaussianblurEffect: require( 'filter/effect/gaussianblureffect' ),
            OffsetEffect: require( 'filter/effect/offseteffect' )

        } );

    } );

    // build环境中才含有use
    try {
        use( 'kity.start' );
    } catch ( e ) {
    }

} )( this );
})();
