text: /*!
   * ====================================================
   * kity - v2.0.0 - 2014-06-16
   * https://github.com/fex-team/kity
   * GitHub: https://github.com/fex-team/kity.git 
   * Copyright (c) 2014 Baidu FEX; Licensed BSD
   * ====================================================
   */
  
  (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/eventhandler", "animate/frame", "core/utils", "core/class", "animate/easing", "graphic/shape", "graphic/svg", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require) {
          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.beginValue = opt.beginValue;
                      this.finishValue = opt.finishValue;
                      this.setter = opt.setter;
                  } else {
                      this.beginValue = beginValue;
                      this.finishValue = 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.finishValue, this.beginValue, 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;
              },
              timeline: function () {
                  return this._KityAnimateQueue[0].t;
              },
              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;
                      s = p / 4;
                  } else 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;
                      s = p / 4;
                  } else 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/frame", [], function (require, exports) {
          // 原生动画帧方法 polyfill
          var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (fn) {
              return setTimeout(fn, 1e3 / 60);
          };
          // 等待执行的帧的集合，这些帧的方法将在下个动画帧同步执行
          var pendingFrames = [];
  
          /**
           * 添加一个帧到等待集合中
           *
           * 如果添加的帧是序列的第一个，至少有一个帧需要被执行，则下一个动画帧需要执行
           */
          function pushFrame(frame) {
              if (pendingFrames.push(frame) === 1) {
                  requestAnimationFrame(executePendingFrames);
              }
          }
  
          /**
           * 执行所有等待帧
           */
          function executePendingFrames() {
              var frames = pendingFrames;
              pendingFrames = [];
              while (frames.length) {
                  executeFrame(frames.pop());
              }
          }
  
          /**
           * 请求一个帧，执行指定的动作。动作回调提供一些有用的信息
           *
           * @param {Function} action
           *
           *     要执行的动作，该动作回调有一个参数 frame，其中：
           *
           *     frame.time
           *         动作执行时的时间戳（ms）
           *
           *     frame.index
           *         当前执行的帧的编号（首帧为 0）
           *
           *     frame.dur
           *         上一帧至今经过的时间，单位 ms
           *
           *     frame.elapsed
           *         从首帧开始到当前帧经过的时间
           *
           *     frame.action
           *         指向当前的帧处理函数
           *
           *     frame.next()
           *         表示下一帧继续执行。如果不调用该方法，将不会执行下一帧。
           *
           */
          function requestFrame(action) {
              var frame = initFrame(action);
              pushFrame(frame);
              return frame;
          }
  
          /**
           * 释放一个已经请求过的帧，如果该帧在等待集合里，将移除，下个动画帧不会执行释放的帧
           */
          function releaseFrame(frame) {
              var index = pendingFrames.indexOf(frame);
              if (~index) {
                  pendingFrames.splice(index, 1);
              }
          }
  
          /**
           * 初始化一个帧，主要用于后续计算
           */
          function initFrame(action) {
              var frame = {
                  index: 0,
                  time: +new Date(),
                  elapsed: 0,
                  action: action,
                  next: function () {
                      pushFrame(frame);
                  }
              };
              return frame;
          }
  
          /**
           * 执行一个帧动作
           */
          function executeFrame(frame) {
              // 当前帧时间错
              var time = +new Date();
              // 当上一帧到当前帧经过的时间
              var dur = time - frame.time;
              //
              // http://stackoverflow.com/questions/13133434/requestanimationframe-detect-stop
              // 浏览器最小化或切换标签，requestAnimationFrame 不会执行。
              // 检测时间超过 200 ms（频率小于 5Hz ） 判定为计时器暂停，重置为一帧长度
              //
              if (dur > 200) {
                  dur = 1e3 / 60;
              }
              frame.dur = dur;
              frame.elapsed += dur;
              frame.time = time;
              frame.action.call(null, frame);
              frame.index++;
          }
  
          // 暴露
          exports.requestFrame = requestFrame;
          exports.releaseFrame = releaseFrame;
      });
      define("animate/motionanimator", ["animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/geometry", "core/utils", "graphic/point", "graphic/vector", "graphic/matrix", "graphic/path", "graphic/svg"], function (require) {
          var Animator = require("animate/animator");
          var g = require("graphic/geometry");
          var Path = require("graphic/path");
          var MotionAnimator = require("core/class").createClass("MotionAnimator", {
              base: Animator,
              constructor: function (path) {
                  var me = this;
                  this.callBase({
                      beginValue: 0,
                      finishValue: 1,
                      setter: function (target, value) {
                          var path = me.motionPath instanceof Path ? me.motionPath.getPathData() : me.motionPath;
                          var point = g.pointAtPath(path, value);
                          target.setTranslate(point.x, point.y);
                          target.setRotate(point.tan.getAngle());
                      }
                  });
                  this.updatePath(path);
              },
              updatePath: function (path) {
                  this.motionPath = path;
              }
          });
          require("core/class").extendClass(Path, {
              motion: function (path, duration, easing, delay, callback) {
                  return this.animate(new MotionAnimator(path), duration, easing, delay, callback);
              }
          });
          return MotionAnimator;
      });
      define("animate/opacityanimator", ["animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require) {
          var Animator = require("animate/animator");
          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/pathanimator", ["animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/geometry", "core/utils", "graphic/point", "graphic/vector", "graphic/matrix", "graphic/path", "graphic/svg"], function (require) {
          var Animator = require("animate/animator");
          var g = require("graphic/geometry");
          var PathAnimator = require("core/class").createClass("OpacityAnimator", {
              base: Animator,
              constructor: function (path) {
                  this.callBase({
                      beginValue: function (target) {
                          this.beginPath = target.getPathData();
                          return 0;
                      },
                      finishValue: 1,
                      setter: function (target, value) {
                          target.setPathData(g.pathTween(this.beginPath, path, value));
                      }
                  });
              }
          });
          var Path = require("graphic/path");
          require("core/class").extendClass(Path, {
              fxPath: function (path, duration, easing, delay, callback) {
                  return this.animate(new PathAnimator(path), duration, easing, delay, callback);
              }
          });
          return PathAnimator;
      });
      define("animate/rotateanimator", ["animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require) {
          var Animator = require("animate/animator");
          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/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require) {
          var Animator = require("animate/animator");
          var ScaleAnimator = require("core/class").createClass("ScaleAnimator", {
              base: Animator,
              constructor: function (sx, sy) {
                  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/eventhandler", "core/utils", "graphic/shapeevent", "core/class", "animate/frame"], function (require) {
          var EventHandler = require("graphic/eventhandler");
          var frame = require("animate/frame");
          var utils = require("core/utils");
  
          function getPercentValue(b, f, p) {
              return utils.paralle(b, f, function (b, f) {
                  return b + (f - b) * p;
              });
          }
  
          function getDelta(v1, v2) {
              return utils.paralle(v1, v2, function (v1, v2) {
                  return v2 - v1;
              });
          }
  
          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 Timeline = require("core/class").createClass("Timeline", {
              mixins: [EventHandler],
              constructor: function (animator, target, duration, easing) {
                  this.callMixin();
                  this.target = target;
                  this.time = 0;
                  this.duration = duration;
                  this.easing = easing;
                  this.animator = animator;
                  this.beginValue = animator.beginValue;
                  this.finishValue = animator.finishValue;
                  this.setter = animator.setter;
                  this.status = "ready";
              },
              nextFrame: function (frame) {
                  if (this.status != "playing") {
                      return;
                  }
                  this.time += frame.dur;
                  this.setValue(this.getValue());
                  if (this.time >= this.duration) {
                      this.timeUp();
                  }
                  frame.next();
              },
              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.beginValue;
                  var f = this.finishValue;
                  var p = this.getValueProportion();
                  return getPercentValue(b, f, p);
              },
              setValue: function (value) {
                  this.lastValue = this.currentValue;
                  this.currentValue = value;
                  this.setter.call(this.target, this.target, value, this);
              },
              getDelta: function () {
                  this.lastValue = this.lastValue === undefined ? this.beginValue : this.lastValue;
                  return getDelta(this.lastValue, this.currentValue);
              },
              play: function () {
                  var lastStatus = this.status;
                  this.status = "playing";
                  switch (lastStatus) {
                      case "ready":
                          if (utils.isFunction(this.beginValue)) {
                              this.beginValue = this.beginValue.call(this.target, this.target);
                          }
                          if (utils.isFunction(this.finishValue)) {
                              this.finishValue = this.finishValue.call(this.target, this.target);
                          }
                          this.time = 0;
                          this.frame = frame.requestFrame(this.nextFrame.bind(this));
                          break;
  
                      case "finished":
                      case "stoped":
                          this.time = 0;
                          this.frame = frame.requestFrame(this.nextFrame.bind(this));
                          break;
  
                      case "paused":
                          this.frame.next();
                  }
                  this.fire("play", new TimelineEvent(this, "play", {
                      lastStatus: lastStatus
                  }));
                  return this;
              },
              pause: function () {
                  this.status = "paused";
                  this.fire("pause", new TimelineEvent(this, "pause"));
                  frame.releaseFrame(this.frame);
                  return this;
              },
              stop: function () {
                  this.status = "stoped";
                  this.setValue(this.finishValue);
                  this.rollbacking = false;
                  this.fire("stop", new TimelineEvent(this, "stop"));
                  frame.releaseFrame(this.frame);
                  return this;
              },
              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.finishValue);
                  this.status = "finished";
                  this.fire("finish", new TimelineEvent(this, "finish"));
                  frame.releaseFrame(this.frame);
              },
              decreaseRepeat: function () {
                  if (this.repeatOption !== true) {
                      this.repeatOption--;
                  }
              },
              repeat: function (repeat, rollback) {
                  this.repeatOption = repeat;
                  this.rollback = rollback;
                  return this;
              }
          });
          Timeline.requestFrame = frame.requestFrame;
          Timeline.releaseFrame = frame.releaseFrame;
          return Timeline;
      });
      define("animate/translateanimator", ["animate/animator", "animate/timeline", "animate/easing", "core/class", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require) {
          var Animator = require("animate/animator");
          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 () {
          var browser = function () {
              var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser;
              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", [], 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);
          };
  
          // 所有类的基类
          function Class() {
          }
  
          Class.__KityClassName = "Class";
          // 提供 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;
          };
          Class.prototype.getClass = function () {
              return this.constructor;
          };
          // 检查基类是否调用了父类的构造函数
          // 该检查是弱检查，假如调用的代码被注释了，同样能检查成功（这个特性可用于知道建议调用，但是出于某些原因不想调用的情况）
          function checkBaseConstructorCall(targetClass, classname) {
              var code = targetClass.toString();
              if (!/this\.callBase/.test(code)) {
                  throw new Error(classname + " : 类构造函数没有调用父类的构造函数！为了安全，请调用父类的构造函数");
              }
          }
  
          var KITY_INHERIT_FLAG = "__KITY_INHERIT_FLAG_" + +new Date();
  
          function inherit(constructor, BaseClass, classname) {
              var KityClass = function (__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;
          }
  
          Class.prototype._accessProperty = function () {
              return this._propertyRawData || (this._propertyRawData = {});
          };
          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/utils", [], function () {
          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) {
                  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;
              },
              deepExtend: 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)) {
                              if (this.isObject(t[k]) && this.isObject(x[k])) {
                                  this.deepExtend(t[k], x[k], notCover);
                              } else {
                                  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;
              },
              copy: function (obj) {
                  if (typeof obj !== "object") return obj;
                  if (typeof obj === "function") return null;
                  return JSON.parse(JSON.stringify(obj));
              },
              queryPath: function (path, obj) {
                  var arr = path.split(".");
                  var i = 0, tmp = obj, l = arr.length;
                  while (i < l) {
                      if (arr[i] in tmp) {
                          tmp = tmp[arr[i]];
                          i++;
                          if (i >= l || tmp === undefined) {
                              return tmp;
                          }
                      } else {
                          return undefined;
                      }
                  }
              },
              getValue: function (value, defaultValue) {
                  return value !== undefined ? value : defaultValue;
              },
              flatten: function (arr) {
                  var result = [], length = arr.length, i;
                  for (i = 0; i < length; i++) {
                      if (arr[i] instanceof Array) {
                          result = result.concat(utils.flatten(arr[i]));
                      } else {
                          result.push(arr[i]);
                      }
                  }
                  return result;
              },
              /**
               * 平行地对 v1 和 v2 进行指定的操作
               *
               *    如果 v1 是数字，那么直接进行 op 操作
               *    如果 v1 是对象，那么返回一个对象，其元素是 v1 和 v2 同名的每个元素平行地进行 op 操作的结果
               *    如果 v1 是数组，那么返回一个数组，其元素是 v1 和 v2 同索引的每个元素平行地进行 op 操作的结果
               *
               * @param  {Number|Object|Array} v1
               * @param  {Number|Object|Array} v2
               * @param  {Function} op
               * @return {Number|Object|Array}
               */
              paralle: function (v1, v2, op) {
                  var Class, field, index, name, value;
                  // 数组
                  if (v1 instanceof Array) {
                      value = [];
                      for (index = 0; index < v1.length; index++) {
                          value.push(utils.paralle(v1[index], v2[index], op));
                      }
                      return value;
                  }
                  // 对象
                  if (v1 instanceof Object) {
                      // 如果值是一个支持原始表示的实例，获取其原始表示
                      Class = v1.getClass && v1.getClass();
                      if (Class && Class.parse) {
                          v1 = v1.valueOf();
                          v2 = v2.valueOf();
                          value = utils.paralle(v1, v2, op);
                          value = Class.parse(value);
                      } else {
                          value = {};
                          for (name in v1) {
                              if (v1.hasOwnProperty(name) && v2.hasOwnProperty(name)) {
                                  value[name] = utils.paralle(v1[name], v2[name], op);
                              }
                          }
                      }
                      return value;
                  }
                  // 是否数字
                  if (false === isNaN(parseFloat(v1))) {
                      return op(v1, v2);
                  }
                  return value;
              },
              /**
               * 创建 op 操作的一个平行化版本
               */
              parallelize: function (op) {
                  return function (v1, v2) {
                      return utils.paralle(v1, v2, op);
                  };
              }
          };
          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"], 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"], 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"], 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/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"], 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"], 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", "graphic/container"], function (require) {
          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);
              },
              handleAdd: 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", "filter/effectcontainer", "graphic/container", "graphic/shape", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], 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", "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", "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", "graphic/pointcontainer", "graphic/container", "graphic/path", "core/utils", "graphic/shape", "graphic/svg", "graphic/geometry"], 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", "graphic/matrix"], 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， 把当前引起变化的点传递过去， 以便有需要的地方可以获取到引起变化的源
                  if (this.container.update) this.container.update(this);
              }
          });
          return BezierPoint;
      });
      define("graphic/box", ["core/class"], function (require, exports, module) {
          var Box = require("core/class").createClass("Box", {
              constructor: function (x, y, width, height) {
                  var box = arguments[0];
                  if (box && typeof box === "object") {
                      x = box.x;
                      y = box.y;
                      width = box.width;
                      height = box.height;
                  }
                  if (width < 0) {
                      x -= width = -width;
                  }
                  if (height < 0) {
                      y -= height = -height;
                  }
                  this.x = x;
                  this.y = y;
                  this.width = width;
                  this.height = height;
              },
              getLeft: function () {
                  return this.x;
              },
              getRight: function () {
                  return this.x + this.width;
              },
              getTop: function () {
                  return this.y;
              },
              getBottom: function () {
                  return this.y + this.height;
              },
              getRangeX: function () {
                  return [this.x, this.x + this.width];
              },
              getRangeY: function () {
                  return [this.y, this.y + this.height];
              },
              merge: function (another) {
                  var xMin = Math.min(this.x, another.x), xMax = Math.max(this.x + this.width, another.x + another.width),
                      yMin = Math.min(this.y, another.y),
                      yMax = Math.max(this.y + this.height, another.y + another.height);
                  return new Box(xMin, yMin, xMax - xMin, yMax - yMin);
              },
              valueOf: function () {
                  return [this.x, this.y, this.width, this.height];
              },
              toString: function () {
                  return this.valueOf().join(" ");
              }
          });
          return Box;
      });
      define("graphic/circle", ["core/class", "graphic/ellipse", "core/utils", "graphic/point", "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", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box", "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"], 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);
                  },
                  valueOf: function () {
                      return this.getValues();
                  },
                  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;
                  if (Utils.isString(valStr)) {
                      rgbValue = ColorUtils.parseToValue(valStr);
                  }
                  if (Utils.isObject(valStr) && "r" in valStr) {
                      rgbValue = 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) {
                  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;
                  }
  
                  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;
              },
              //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"], 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) {
                  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", "graphic/path", "graphic/shape", "graphic/svg", "graphic/geometry", "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].x + points[j].y) / 2,
                          y: (points[i].x + points[j].y) / 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.x,
                              y: center.y - point.y
                          };
                      var currentResult = result[index] = {
                          points: [],
                          center: {
                              x: point.x,
                              y: point.y
                          }
                      };
                      //计算控制点到顶点的距离， 并且应用平滑系数到距离上
                      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]);
                  }
                  if (points.length === 1) {
                      return this;
                  }
                  if (points.length === 2) {
                      drawer.lineTo(points[1]);
                      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"], 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", ["core/class", "graphic/resource", "graphic/svg"], function (require, exports, module) {
          return require("core/class").createClass("GradientBrush", {
              base: require("graphic/resource"),
              constructor: function (nodeType) {
                  this.callBase(nodeType);
              }
          });
      });
      define("graphic/ellipse", ["core/utils", "graphic/point", "core/class", "graphic/path", "graphic/shape", "graphic/svg", "graphic/geometry"], function (require, exports, module) {
          var Utils = require("core/utils"), Point = require("graphic/point");
          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 new Point(this.cx, 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) {
                  if (arguments.length == 1) {
                      var p = Point.parse(arguments[0]);
                      cx = p.x;
                      cy = p.y;
                  }
                  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", "graphic/point", "core/class"], 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._kityParam = 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/geometry", ["core/utils", "graphic/point", "core/class", "graphic/vector", "graphic/matrix", "graphic/box"], function (require) {
          var utils = require("core/utils");
          var Point = require("graphic/point");
          var Vector = require("graphic/vector");
          var Matrix = require("graphic/matrix");
          var g = {};
          var pathCommand = /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?\s*)+)/gi,
              pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/gi, paramCounts = {
                  a: 7,
                  c: 6,
                  h: 1,
                  l: 2,
                  m: 2,
                  q: 4,
                  s: 4,
                  t: 2,
                  v: 1,
                  z: 0
              };
  
          function pathClone(path) {
              var result, i, j, segment, segmentCopy;
              result = [];
              for (i = 0; i < path.length; i++) {
                  segment = path[i];
                  result.push(segmentCopy = []);
                  for (j = 0; j < segment.length; j++) {
                      segmentCopy.push(segment[j]);
                  }
              }
              if (path.isUniform) result.isUniform = true;
              if (path.isAbsolute) result.isAbsolute = true;
              if (path.isCurve) result.isCurve = true;
              return result;
          }
  
          // 缓存函数
          // from raphael.js
          function cacher(f, scope, postprocessor) {
              function repush(array, item) {
                  for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
                      return array.push(array.splice(i, 1)[0]);
                  }
              }
  
              function newf() {
                  var arg = Array.prototype.slice.call(arguments, 0), args = arg.join("␀"),
                      cache = newf.cache = newf.cache || {}, count = newf.count = newf.count || [];
                  if (cache.hasOwnProperty(args)) {
                      repush(count, args);
                      return postprocessor ? postprocessor(cache[args]) : cache[args];
                  }
                  if (count.length >= 1e3) {
                      delete cache[count.shift()];
                  }
                  count.push(args);
                  cache[args] = f.apply(scope, arg);
                  return postprocessor ? postprocessor(cache[args]) : cache[args];
              }
  
              return newf;
          }
  
          /**
           *
           * kity.g.pathToString(pathSegment)
           *
           * 返回表示 PathSegment 的字符串
           *
           * @param  {Array} pathSegment
           *     要表示的 Path Segment
           *
           * @return {String} 表示该 Path 的字符串
           *
           * @example
           *
           *     var pathSegment = [['M', 0, 0], ['L', 10, 10]]
           *     var pathString = kity.g.pathToString(pathSegment);
           *     // 返回 'M0,0L10,10'
           */
          g.pathToString = function (pathSegment) {
              pathSegment = pathSegment || this;
              if (typeof pathSegment == "string") return pathSegment;
              if (pathSegment instanceof Array) {
                  pathSegment = utils.flatten(pathSegment);
                  return pathSegment.join(",").replace(/,?([achlmqrstvxz]),?/gi, "$1");
              }
          };
          /**
           * kity.g.parsePathString(pathString)
           *
           * 解析 Path 字符串成 PathSegment
           *
           * @copyright rapheal.js
           *
           * @example
           *
           *     var seg = kity.g.parsePathString('M10,12l21-23-21.5,11z');
           *     // 返回: [['M', 10, 12], ['l', 21, -23], ['l', -21.5, 11], ['z']]
           *
           * @param  {String} pathString Path 字符串
           * @return {Array}
           */
          g.parsePathString = cacher(function (pathString) {
              var data = [];
              pathString.replace(pathCommand, function (a, b, c) {
                  var params = [], name = b.toLowerCase();
                  c.replace(pathValues, function (a, b) {
                      if (b) params.push(+b);
                  });
                  if (name == "m" && params.length > 2) {
                      data.push([b].concat(params.splice(0, 2)));
                      name = "l";
                      b = b == "m" ? "l" : "L";
                  }
                  if (name == "r") {
                      data.push([b].concat(params));
                  } else {
                      while (params.length >= paramCounts[name]) {
                          data.push([b].concat(params.splice(0, paramCounts[name])));
                          if (!paramCounts[name]) {
                              break;
                          }
                      }
                  }
              });
              data.isUniform = true;
              data.toString = g.pathToString;
              return data;
          });
          /**
           * kity.g.pathToAbsolute(path)
           *
           * 把路径转换为绝对路径的形式
           *
           * @param {Array|String} path
           *     要转换的 path 路径或者数组
           *
           * @return {Array}
           *     转换后的 Path Segment
           *
           * @example
           *
           *     var path = 'M10,10l50,50';
           *     var absPath = kity.g.pathToAbsolute(path);
           *     // 返回 [['M', 10, 10], ['L', 60, 60]]
           */
          g.pathToAbsolute = cacher(function (path) {
              var pathArray = path.isUniform ? path : g.parsePathString(g.pathToString(path));
              var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0;
              var r, pa, i, j, k, ii, jj, kk;
              if (pathArray[0][0] == "M") {
                  x = +pathArray[0][1];
                  y = +pathArray[0][2];
                  mx = x;
                  my = y;
                  start++;
                  res[0] = ["M", x, y];
              }
              for (r, pa, i = start, ii = pathArray.length; i < ii; i++) {
                  res.push(r = []);
                  pa = pathArray[i];
                  if (pa[0] != pa[0].toUpperCase()) {
                      r[0] = pa[0].toUpperCase();
                      switch (r[0]) {
                          case "A":
                              r[1] = pa[1];
                              r[2] = pa[2];
                              r[3] = pa[3];
                              r[4] = pa[4];
                              r[5] = pa[5];
                              r[6] = +(pa[6] + x);
                              r[7] = +(pa[7] + y);
                              break;
  
                          case "V":
                              r[1] = +pa[1] + y;
                              break;
  
                          case "H":
                              r[1] = +pa[1] + x;
                              break;
  
                          case "M":
                              mx = +pa[1] + x;
                              my = +pa[2] + y;
                              break;
  
                          default:
                              for (j = 1, jj = pa.length; j < jj; j++) {
                                  r[j] = +pa[j] + (j % 2 ? x : y);
                              }
                      }
                  } else {
                      for (k = 0, kk = pa.length; k < kk; k++) {
                          r[k] = pa[k];
                      }
                  }
                  switch (r[0]) {
                      case "Z":
                          x = mx;
                          y = my;
                          break;
  
                      case "H":
                          x = r[1];
                          break;
  
                      case "V":
                          y = r[1];
                          break;
  
                      case "M":
                          mx = r[r.length - 2];
                          my = r[r.length - 1];
                          break;
  
                      default:
                          x = r[r.length - 2];
                          y = r[r.length - 1];
                  }
              }
              res.isUniform = true;
              res.isAbsolute = true;
              res.toString = g.pathToString;
              return res;
          });
  
          // 把圆弧绘制的曲线转化为对应的三次贝塞尔形式
          function a2c(x1, y1, rx, ry, angle, laf, sf, x2, y2, recursive) {
              // copy from raphael.js
              // for more information of where this math came from visit:
              // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
              var math = Math, PI = math.PI, abs = Math.abs, _120 = PI * 120 / 180, rad = PI / 180 * (+angle || 0),
                  res = [], xy, rotate = function (x, y, rad) {
                      var X = x * math.cos(rad) - y * math.sin(rad), Y = x * math.sin(rad) + y * math.cos(rad);
                      return {
                          x: X,
                          y: Y
                      };
                  };
              var cos, sin, h, x, y, rx2, ry2, k, cx, cy, f1, f2, df, f2old, x2old, y2old, c1, s1, c2, s2, t, hx, hy, m1,
                  m2, m3, m4, newres, i, ii;
              if (!recursive) {
                  xy = rotate(x1, y1, -rad);
                  x1 = xy.x;
                  y1 = xy.y;
                  xy = rotate(x2, y2, -rad);
                  x2 = xy.x;
                  y2 = xy.y;
                  cos = math.cos(PI / 180 * angle);
                  sin = math.sin(PI / 180 * angle);
                  x = (x1 - x2) / 2;
                  y = (y1 - y2) / 2;
                  h = x * x / (rx * rx) + y * y / (ry * ry);
                  if (h > 1) {
                      h = math.sqrt(h);
                      rx = h * rx;
                      ry = h * ry;
                  }
                  rx2 = rx * rx;
                  ry2 = ry * ry;
                  k = (laf == sf ? -1 : 1) * math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
                  cx = k * rx * y / ry + (x1 + x2) / 2;
                  cy = k * -ry * x / rx + (y1 + y2) / 2;
                  f1 = math.asin(((y1 - cy) / ry).toFixed(9));
                  f2 = math.asin(((y2 - cy) / ry).toFixed(9));
                  f1 = x1 < cx ? PI - f1 : f1;
                  f2 = x2 < cx ? PI - f2 : f2;
                  if (f1 < 0) f1 = PI * 2 + f1;
                  if (f2 < 0) f2 = PI * 2 + f2;
                  if (sf && f1 > f2) {
                      f1 = f1 - PI * 2;
                  }
                  if (!sf && f2 > f1) {
                      f2 = f2 - PI * 2;
                  }
              } else {
                  f1 = recursive[0];
                  f2 = recursive[1];
                  cx = recursive[2];
                  cy = recursive[3];
              }
              df = f2 - f1;
              if (abs(df) > _120) {
                  f2old = f2;
                  x2old = x2;
                  y2old = y2;
                  f2 = f1 + _120 * (sf && f2 > f1 ? 1 : -1);
                  x2 = cx + rx * math.cos(f2);
                  y2 = cy + ry * math.sin(f2);
                  res = a2c(x2, y2, rx, ry, angle, 0, sf, x2old, y2old, [f2, f2old, cx, cy]);
              }
              df = f2 - f1;
              c1 = math.cos(f1);
              s1 = math.sin(f1);
              c2 = math.cos(f2);
              s2 = math.sin(f2);
              t = math.tan(df / 4);
              hx = 4 / 3 * rx * t;
              hy = 4 / 3 * ry * t;
              m1 = [x1, y1];
              m2 = [x1 + hx * s1, y1 - hy * c1];
              m3 = [x2 + hx * s2, y2 - hy * c2];
              m4 = [x2, y2];
              m2[0] = 2 * m1[0] - m2[0];
              m2[1] = 2 * m1[1] - m2[1];
              if (recursive) {
                  return [m2, m3, m4].concat(res);
              } else {
                  res = [m2, m3, m4].concat(res).join().split(",");
                  newres = [];
                  for (i = 0, ii = res.length; i < ii; i++) {
                      newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
                  }
                  return newres;
              }
          }
  
          // 把二次贝塞尔曲线参数转化为三次贝塞尔曲线参数
          function q2c(x1, y1, ax, ay, x2, y2) {
              // copy from raphael.js
              var _13 = 1 / 3, _23 = 2 / 3;
              return [_13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2];
          }
  
          /**
           * kity.g.pathToCurve(path)
           *
           * 把路径转换为贝塞尔路径
           *
           * @param  {Array|String} path
           *     要转换的 path 路径或数组
           *
           * @return {Array}
           *     转换后的 PathSegment，每一段都是 'C'
           */
          g.pathToCurve = cacher(function (path) {
              var i, command, param;
              var initPoint, currentPoint, endPoint, shouldClose, lastControlPoint, aussumedControlPoint;
              var controlPoint1, controlPoint2;
              var res = [];
              // 处理的路径要求是一个绝对路径
              if (!path.isAbsolute) path = g.pathToAbsolute(path);
              for (i = 0; i < path.length; i++) {
                  command = path[i][0];
                  param = path[i].slice(1);
                  // 画笔移动
                  if (command == "M") {
                      initPoint = lastControlPoint = currentPoint = param;
                      res.push(path[i]);
                      continue;
                  }
                  // 路径闭合
                  if (command == "Z") {
                      shouldClose = true;
                      command = "L";
                      param = initPoint;
                  }
                  // 绘制命令的目的位置
                  endPoint = param.slice(param.length - 2);
                  // 对 'H' 命令的修正
                  if (command == "H") {
                      endPoint = [param[0], currentPoint[1]];
                      command = "L";
                  }
                  // 对 'V' 命令的修正
                  if (command == "V") {
                      endPoint = [currentPoint[0], param[0]];
                      command = "L";
                  }
                  // 对 'S' 命令求出隐含的控制点位置
                  if (command == "S" || command == "T") {
                      // 隐含控制点是上一个控制点关于当前位置的镜像
                      aussumedControlPoint = [currentPoint[0] + (currentPoint[0] - lastControlPoint[0]), currentPoint[1] + (currentPoint[1] - lastControlPoint[1])];
                  }
                  // 针对不同的命令求控制点
                  switch (command) {
                      case "L":
                          controlPoint1 = currentPoint;
                          controlPoint2 = endPoint;
                          break;
  
                      case "C":
                          controlPoint1 = param.slice(0, 2);
                          controlPoint2 = param.slice(2, 4);
                          break;
  
                      case "S":
                          controlPoint1 = aussumedControlPoint.slice();
                          controlPoint2 = param.slice(0, 2);
                          break;
  
                      case "Q":
                          lastControlPoint = param.slice(0, 2);
                          param = q2c.apply(null, currentPoint.concat(param));
                          controlPoint1 = param.slice(0, 2);
                          controlPoint2 = param.slice(2, 4);
                          break;
  
                      case "T":
                          param = q2c.apply(null, currentPoint.concat(aussumedControlPoint).concat(param));
                          controlPoint1 = param.slice(0, 2);
                          controlPoint2 = param.slice(2, 4);
                          break;
  
                      case "A":
                          param = a2c.apply(null, currentPoint.concat(param));
                          controlPoint1 = param.slice(0, 2);
                          controlPoint2 = param.slice(2, 4);
                          break;
                  }
                  // 写入当前一段曲线
                  res.push(["C"].concat(controlPoint1).concat(controlPoint2).concat(endPoint));
                  // 为下次循环准备当前位置
                  currentPoint = endPoint;
                  // 二次贝塞尔曲线自己已经记录了上个控制点的位置，其它的记录控制点 2 的位置
                  if (command != "Q") {
                      lastControlPoint = controlPoint2;
                  }
                  if (shouldClose) {
                      res.push(["Z"]);
                      shouldClose = false;
                  }
              }
              res.isUniform = true;
              res.isAbsolute = true;
              res.isCurve = true;
              res.toString = g.pathToString;
              return res;
          });
  
          /**
           * 将贝塞尔曲线切成两部分
           *
           * @see http://stackoverflow.com/questions/18655135/divide-bezier-curve-into-two-equal-halves
           */
          function cutBezier(bezierArray, t) {
              function __(t) {
                  return function (p, q) {
                      return p + t * (q - p);
                  };
              }
  
              var _ = __(t || .5), ba = bezierArray, ax = ba[0], ay = ba[1], bx = ba[2], by = ba[3], cx = ba[4],
                  cy = ba[5], dx = ba[6], dy = ba[7], ex = _(ax, bx), ey = _(ay, by), fx = _(bx, cx), fy = _(by, cy),
                  gx = _(cx, dx), gy = _(cy, dy), hx = _(ex, fx), hy = _(ey, fy), jx = _(fx, gx), jy = _(fy, gy),
                  kx = _(hx, jx), ky = _(hy, jy);
              return [[ax, ay, ex, ey, hx, hy, kx, ky], [kx, ky, jx, jy, gx, gy, dx, dy]];
          }
  
          /**
           * kity.g.cutBezier(bezierArray, t)
           *
           * 在指定位置把贝塞尔曲线切割为两部分
           *
           * @param {Array} bezierArray
           *     表示贝塞尔曲线的一个数组 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]
           *     p1 和 p2 是贝塞尔曲线的起点和终点，c1 和 c2 是两个控制点
           *
           * @param {Number} t
           *     切割的位置（0 到 1）
           *
           * @return {Array}
           *     切割的两个贝塞尔曲线：[
           *         [p1x1, p1y1, c1x1, c1y1, c2x1, c2y1, p2x1, p2y1],
           *         [p1x2, p1y2, c1x2, c1y2, c2x2, c2y2, p2x2, p2y2]
           *     ]
           *
           */
          g.cutBezier = cacher(cutBezier);
          /**
           * 求一段贝塞尔曲线的子段
           *
           * @param {Array} bezierArray
           *     长度为 8 的数组，表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]
           *
           * @param {Number} t
           *     子段的结束位置（0 到 1）
           *
           * @param {Number} t0
           *     字段的开始位置（0 到 t），可不传，默认为 0
           *
           * @return {Array}
           *     长度为 8 的数组，表示给定贝塞尔曲线的子段
           */
          g.subBezier = function (bezierArray, t, t0) {
              var b2t = cutBezier(bezierArray, t)[0];
              return t0 ? cutBezier(b2t, t0 / t)[1] : b2t;
          };
          /**
           * 求贝塞尔曲线上的一个点
           *
           * @param {Array} bezierArray
           *     长度为 8 的数组，表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]
           *
           * @param {Number} t
           *     所求点的开始位置（0 到 1）
           *
           * @return {Point} p
           *     p.x: x 坐标
           *     p.y: y 坐标
           *     p.tan: 在 t 处的切线方向（类型为 kity.Vector，模为 1）
           */
          g.pointAtBezier = function (bezierArray, t) {
              var b2t = cutBezier(bezierArray, t)[0];
              var p = Point.parse(b2t.slice(6)), c = Point.parse(b2t.slice(4, 2)), v = Vector.fromPoints(c, p);
              if (t === 0) {
                  p.tan = g.pointAtBezier(bezierArray, .01).tan;
              } else {
                  p.tan = v.normalize();
              }
              return p;
          };
          /**
           * 求贝塞尔曲线的长度
           *
           * @param {Array} bezierArray
           *     长度为 8 的数组，表示 [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]
           *
           * @param {Number} tolerate
           *     允许的误差，默认是 0.1
           *
           * @return {Number} 贝塞尔曲线的长度
           */
          g.bezierLength = cacher(function bezierLength(bezierArray, tolerate) {
              // 切割成多少段来计算
              tolerate = Math.max(tolerate || .001, 1e-9);
  
              function len(p, q) {
                  var dx = p[0] - q[0], dy = p[1] - q[1];
                  return Math.sqrt(dx * dx + dy * dy);
              }
  
              var cutted, p, q, m, cuttedLength;
              cutted = cutBezier(bezierArray);
              p = bezierArray.slice(0, 2);
              q = bezierArray.slice(6);
              m = cutted[1].slice(0, 2);
              cuttedLength = len(p, m) + len(m, q);
              if (cuttedLength - len(p, q) < tolerate) return cuttedLength;
              // 递归计算
              return bezierLength(cutted[0], tolerate / 2) + bezierLength(cutted[1], tolerate / 3);
          });
          // 计算一个 pathSegment 中每一段的在整体中所占的长度范围，以及总长度
          // 方法要求每一段都是贝塞尔曲线
          var getBezierPathSegmentRanges = cacher(function (pathSegment) {
              var i, ii, segment, position, bezierLength, segmentRanges, totalLength;
              segmentRanges = [];
              // 总长度
              totalLength = 0;
              for (i = 0, ii = pathSegment.length; i < ii; i++) {
                  segment = pathSegment[i];
                  if (segment[0] == "M") {
                      position = segment.slice(1);
                      segmentRanges.push(null);
                      continue;
                  }
                  if (segment[0] == "Z") {
                      segmentRanges.push(null);
                      continue;
                  }
                  bezierLength = g.bezierLength(position.concat(segment.slice(1)));
                  segmentRanges.push([totalLength, totalLength + bezierLength]);
                  totalLength += bezierLength;
                  // 迭代当前位置
                  position = segment.slice(4);
              }
              segmentRanges.totalLength = totalLength;
              return segmentRanges;
          });
          /**
           * 求一段路径的子路径
           *
           * @param  {Array|String} path
           *     原路径
           *
           * @param  {Number} t1
           *     要求的子路径的结束位置（0 到 1）
           *
           * @param  {Number} t0
           *     要求的子路径的开始位置（0 到 t1），可不传，默认为 0
           *
           * @return {Array}
           *     子路径的 PathSegment
           */
          g.subPath = function (path, t1, t0) {
              var dt;
              t0 = t0 || 0;
              dt = t1 - t0;
              dt = dt - (dt | 0);
              t0 = t0 - (t0 | 0);
              t1 = t0 + dt;
              if (t1 > 1) {
                  return g.subPath(path, 1, t0).concat(g.subPath(path, t1 - 1));
              }
              if (!path.isCurve) {
                  path = g.pathToCurve(path);
              }
              // path 每一段在整体中的长度区间
              var segmentRanges = getBezierPathSegmentRanges(path);
              // path 总长度
              var totalLength = segmentRanges.totalLength;
              // t1 和 t0 位置命中的长度位置
              var t1Length = totalLength * t1, t0Length = totalLength * (t0 || 0);
              // 产生的子路径
              var subPath = [];
              // 迭代变量，a 是一段的长度区间左值，b 是右值，d 是区间长度
              var i, ii, a, b, d;
              var position;
              var bezier, subBezier, stared;
              for (i = 0, ii = path.length; i < ii; i++) {
                  if (path[i][0] == "M") {
                      position = path[i].slice(1);
                      if (stared) {
                          subPath.push(path[i].slice());
                      }
                      continue;
                  }
                  if (path[i][0] == "Z") {
                      // subpath 路径不闭合
                      continue;
                  }
                  a = segmentRanges[i][0];
                  b = segmentRanges[i][1];
                  d = b - a;
                  bezier = position.concat(path[i].slice(1));
                  if (t0Length > b) {
                      // t0 和 t1 都右溢出
                      // -----------------------------------
                      //            t0   t1
                      // |________|
                      //
                      // 需要跳过当前块
                      position = bezier.slice(bezier.length - 2);
                      continue;
                  } else if (t0Length >= a) {
                      // 命中 t0；t1 可能命中或右溢出
                      // -----------------------------------
                      //            t0   t1
                      //     |______|__|
                      //
                      //     or:  |_|____|__|
                      //
                      // 取当前块 t0 到 t1 的部分
                      subBezier = g.subBezier(bezier, Math.min((t1Length - a) / d, 1), (t0Length - a) / d);
                      stared = true;
                      position = subBezier.slice(0, 2);
                      subPath.push(["M"].concat(subBezier.slice(0, 2)));
                      subPath.push(["C"].concat(subBezier.slice(2)));
                  } else if (t1Length >= b) {
                      // t0 左溢出；t1 右溢出，整个块是需要的
                      // -----------------------------------
                      //       t0             t1
                      //          |_________|
                      //
                      // 此时取整个块
                      subPath.push(path[i].slice());
                  } else if (t1Length >= a) {
                      // t0 左溢出；t1 命中，取当前块 t1 之前的部分
                      // -----------------------------------
                      //            t0   t1
                      //              |__|______|
                      // 取当前块 t1 之前的部分
                      subBezier = g.subBezier(bezier, (t1Length - a) / d);
                      subPath.push(["C"].concat(subBezier.slice(2)));
                      stared = false;
                  } else {
                      // 没有可以再要的了
                      break;
                  }
                  position = bezier.slice(bezier.length - 2);
              }
              subPath.isAbsolute = true;
              subPath.isCurve = true;
              subPath.isUniform = true;
              subPath.toString = g.pathToString;
              return subPath;
          };
          /**
           * 求路径上的一个点
           *
           * @param  {Array|String} path
           *     要求点的路径
           *
           * @param  {Number} t
           *     要求的点的位置（0 到 1）
           *
           * @return {Point} p
           *     p.x: x 坐标
           *     p.y: y 坐标
           *     p.tan: 在 t 处的切线方向（类型为 kity.Vector，模为 1）
           */
          g.pointAtPath = function (path, t) {
              if (!path.isCurve) {
                  path = g.pathToCurve(path);
              }
              var subPath = g.subPath(path, t);
              var lastCurve = subPath[subPath.length - 1][0] == "Z" ? subPath[subPath.length - 2] : subPath[subPath.length - 1];
              // 跳过 'C' 命令，只留参数
              lastCurve = lastCurve.slice(1);
              var p = Point.parse(lastCurve.slice(4)), c = Point.parse(lastCurve.slice(2, 4));
              p.tan = Vector.fromPoints(c, p).normalize();
              return p;
          };
          /**
           * 求一段路径的长度
           *
           * @param  {string|Array} path
           *     要求的路径
           *
           * @return {Number}
           *     路径的长度
           */
          g.pathLength = cacher(function (path) {
              if (!path.isCurve) {
                  path = g.pathToCurve(path);
              }
              // path 每一段在整体中的长度区间
              var segmentRanges = getBezierPathSegmentRanges(path);
              return segmentRanges.totalLength;
          });
          /**
           * 求一段路径的关键点
           *
           * @param  {string|Array} path
           *     要求的路径
           *
           * @return {Array}
           *     关键点的集合
           */
          g.pathKeyPoints = cacher(function (path) {
              var i, ii, command, keyPoints;
              if (!path.isCurve) {
                  path = g.pathToCurve(path);
              }
              keyPoints = [];
              for (i = 0, ii = path.length; i < ii; i++) {
                  if (path[i][0] == "z") continue;
                  keyPoints.push(path[i].slice(path[i].length - 2));
              }
              return keyPoints;
          });
          // 对比两个路径的关键位置，在合适的位置切割合适的路径，使得两个路径的段数一致
          // TODO: 使用插值算法，使对应点更合理
          var alignCurve = cacher(function (path1, path2) {
              if (!path1.isCurve) path1 = g.pathToCurve(path1);
              if (!path2.isCurve) path2 = g.pathToCurve(path2);
              var p1 = pathClone(path1);
              var p2 = pathClone(path2);
              p1.i = 0;
              p2.i = 0;
              p1.o = p2;
              p2.o = p1;
  
              function command(p, i) {
                  return p[i || p.i] && p[i || p.i][0];
              }
  
              function param(p, i) {
                  return p[i || p.i] && p[i || p.i].slice(1);
              }
  
              function point(p, i) {
                  var _param = param(p, i);
                  return _param && _param.slice(-2);
              }
  
              function fixZ(p) {
                  if (command(p) == "Z") {
                      p.splice(p.i, 1);
                      return true;
                  }
                  return false;
              }
  
              function fixM(p) {
                  if (command(p) == "M") {
                      p.o.splice(p.o.i, 0, ["M"].concat(point(p.o, p.o.i - 1)));
                      p.i++;
                      p.o.i++;
                      return true;
                  }
                  return false;
              }
  
              function fill(p) {
                  var lastPoint;
                  var i = 1;
                  while (!lastPoint) {
                      lastPoint = point(p, p.length - i++);
                  }
                  p.o.i = p.i;
                  while (p.length < p.o.length) {
                      if (fixZ(p.o)) continue;
                      if (fixM(p.o)) continue;
                      p.push(["C"].concat(lastPoint).concat(lastPoint).concat(lastPoint));
                      p.i++;
                      p.o.i++;
                  }
              }
  
              while (p1.i < p1.length && p2.i < p2.length) {
                  if (fixZ(p1) || fixZ(p2)) continue;
                  if (command(p1) == command(p2)) {
                      p1.i++;
                      p2.i++;
                      continue;
                  }
                  if (fixM(p1) || fixM(p2)) continue;
                  p1.i++;
                  p2.i++;
              }
              if (p1.i == p1.length) fill(p1);
              if (p2.i == p2.length) fill(p2);
              delete p1.i;
              delete p1.o;
              delete p2.i;
              delete p2.o;
              return [p1, p2];
          });
          g.alignCurve = alignCurve;
          /**
           * 获得两个路径的补间结果
           *
           * @param  {string|Array} path1
           *     补间起始路径
           *
           * @param  {string|Array} path2
           *     补间结束路径
           *
           * @param  {Number} t
           *     补间比例，0 返回跟 path1 等效的结果；1 返回跟 path2 等效的结果
           *
           * @return {PathSegment}
           *     补间的结果
           */
          g.pathTween = function (path1, path2, t) {
              if (t === 0) return path1;
              if (t === 1) return path2;
              var aligned = alignCurve(path1, path2);
              var result = [], seg, i, j;
              path1 = aligned[0];
              path2 = aligned[1];
              for (i = 0; i < path1.length; i++) {
                  result.push(seg = []);
                  seg.push(path1[i][0]);
                  for (j = 1; j < path1[i].length; j++) {
                      seg.push(path1[i][j] + t * (path2[i][j] - path1[i][j]));
                  }
              }
              result.isUniform = result.isCurve = result.isAbsolute = true;
              return result;
          };
          /**
           * 变换指定的路径
           *
           * @param  {String|Array} path
           *     需要变换的路径
           *
           * @param  {kity.Matrix} matrix
           *     使用的变换矩阵
           *
           * @return {Array}
           *     变换后的路径
           */
          g.transformPath = cacher(function (path, matrix) {
              var i, ii, j, result, seg, pair;
              if (!path.isCurve) {
                  path = g.pathToCurve(path);
              }
              result = [];
              for (i = 0, ii = path.length; i < ii; i++) {
                  result.push(seg = [path[i][0]]);
                  for (j = 1; j < path[i].length; j += 2) {
                      pair = path[i].slice(j, j + 2);
                      pair = matrix.transformPoint(Point.parse(pair));
                      result.push(pair);
                  }
              }
              return result;
          });
          // entend
          require("core/class").extendClass(Matrix, {
              transformPath: function (path) {
                  return g.transformPath(path, this);
              }
          });
          return g;
      });
      define("graphic/gradientbrush", ["graphic/svg", "graphic/defbrush", "core/class", "graphic/resource", "graphic/color", "core/utils", "graphic/standardcolor"], 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", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], 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/hyperlink", ["graphic/shapecontainer", "graphic/container", "core/utils", "core/class", "graphic/shape", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], function (require, exports, module) {
          var ShapeContainer = require("graphic/shapecontainer");
          return require("core/class").createClass("HyperLink", {
              mixins: [ShapeContainer],
              base: require("graphic/shape"),
              constructor: function (url) {
                  this.callBase("a");
                  this.setHref(url);
              },
              setHref: function (href) {
                  this.node.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", href);
                  return this;
              },
              getHref: function () {
                  return this.node.getAttributeNS("xlink:href");
              },
              setTarget: function (target) {
                  this.node.setAttribute("target", target);
                  return this;
              },
              getTarget: function () {
                  return this.node.getAttribute("target");
              }
          });
      });
      define("graphic/image", ["core/class", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], 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", "graphic/path", "core/utils", "graphic/shape", "graphic/svg", "graphic/geometry"], 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"], 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/marker", ["graphic/point", "core/class", "graphic/resource", "graphic/svg", "graphic/shapecontainer", "graphic/container", "core/utils", "graphic/shape", "graphic/viewbox", "graphic/path", "graphic/geometry"], function (require, exports, module) {
          var Point = require("graphic/point");
          var Marker = require("core/class").createClass("Marker", {
              base: require("graphic/resource"),
              mixins: [require("graphic/shapecontainer"), require("graphic/viewbox")],
              constructor: function () {
                  this.callBase("marker");
                  this.setOrient("auto");
              },
              setRef: function (x, y) {
                  if (arguments.length === 1) {
                      y = x.y;
                      x = x.x;
                  }
                  this.node.setAttribute("refX", x);
                  this.node.setAttribute("refY", y);
                  return this;
              },
              getRef: function () {
                  return new Point(+this.node.getAttribute("refX"), +this.node.getAttribute("refY"));
              },
              setWidth: function (width) {
                  this.node.setAttribute("markerWidth", this.width = width);
                  return this;
              },
              setOrient: function (orient) {
                  this.node.setAttribute("orient", this.orient = orient);
                  return this;
              },
              getOrient: function () {
                  return this.orient;
              },
              getWidth: function () {
                  return +this.width;
              },
              setHeight: function (height) {
                  this.node.setAttribute("markerHeight", this.height = height);
                  return this;
              },
              getHeight: function () {
                  return +this.height;
              }
          });
          var Path = require("graphic/path");
          require("core/class").extendClass(Path, {
              setMarker: function (marker, pos) {
                  pos = pos || "end";
                  if (!marker) {
                      this.node.removeAttribute("marker-" + pos);
                  } else {
                      this.node.setAttribute("marker-" + pos, marker.toString());
                  }
                  return this;
              }
          });
          return Marker;
      });
      /**
       * 蒙板
       */
      define("graphic/mask", ["core/class", "graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box", "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/box", "core/class", "graphic/point"], function (require, exports, module) {
          var utils = require("core/utils");
          var Box = require("graphic/box");
          var mPattern = /matrix\((.+)\)/i;
          var Point = require("graphic/point");
  
          // 注意，合并的结果是先执行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;
              },
              /**
               * 获得反转矩阵
               *
               * 这是我解方程算出来的
               */
              inverse: function () {
                  var m = this.m, a = m.a, b = m.b, c = m.c, d = m.d, e = m.e, f = m.f, k, aa, bb, cc, dd, ee, ff;
                  k = a * d - b * c;
                  aa = d / k;
                  bb = -b / k;
                  cc = -c / k;
                  dd = a / k;
                  ee = (c * f - e * d) / k;
                  ff = (b * e - a * f) / k;
                  return new Matrix(aa, bb, cc, dd, ee, ff);
              },
              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 () {
                  return this.valueOf().join(" ");
              },
              valueOf: function () {
                  var m = this.m;
                  return [m.a, m.b, m.c, m.d, m.e, m.f];
              },
              equals: function (matrix) {
                  var m1 = this.m, m2 = matrix.m;
                  return m1.a == m2.a && m1.b == m2.b && m1.c == m2.c && m1.d == m2.d && m1.e == m2.e && m1.f == m2.f;
              },
              transformPoint: function () {
                  return Matrix.transformPoint.apply(null, [].slice.call(arguments).concat([this.m]));
              },
              transformBox: function (box) {
                  return Matrix.transformBox(box, this.m);
              }
          });
          Matrix.parse = function (str) {
              var match;
              var f = parseFloat;
              if (str instanceof Array) {
                  return new Matrix({
                      a: str[0],
                      b: str[1],
                      c: str[2],
                      d: str[3],
                      e: str[4],
                      f: str[5]
                  });
              }
              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) {
              if (arguments.length === 2) {
                  m = y;
                  y = x.y;
                  x = x.x;
              }
              return new Point(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);
              }
              box = new Box({
                  x: xMin,
                  y: yMin,
                  width: xMax - xMin,
                  height: yMax - yMin
              });
              utils.extend(box, {
                  closurePoints: rps,
                  left: xMin,
                  right: xMax,
                  top: yMin,
                  bottom: yMax,
                  cx: (xMin + xMax) / 2,
                  cy: (yMin + yMax) / 2
              });
              return box;
          };
          // 获得从 node 到 refer 的变换矩阵
          Matrix.getCTM = function (target, refer) {
              var ctm = {
                  a: 1,
                  b: 0,
                  c: 0,
                  d: 1,
                  e: 0,
                  f: 0
              };
              refer = refer || "parent";
              // 根据参照坐标系选区的不一样，返回不同的结果
              switch (refer) {
                  case "screen":
                      // 以浏览器屏幕为参照坐标系
                      ctm = target.node.getScreenCTM();
                      break;
  
                  case "doc":
                  case "paper":
                      // 以文档（Paper）为参照坐标系
                      ctm = target.node.getCTM();
                      break;
  
                  case "view":
                  case "top":
                      // 以顶层绘图容器（视野）为参照坐标系
                      if (target.getPaper()) {
                          ctm = target.node.getTransformToElement(target.getPaper().shapeNode);
                      }
                      break;
  
                  case "parent":
                      // 以父容器为参照坐标系
                      if (target.node.parentNode) {
                          ctm = target.node.getTransformToElement(target.node.parentNode);
                      }
                      break;
  
                  default:
                      // 其他情况，指定参照物
                      if (refer.node) {
                          ctm = target.node.getTransformToElement(refer.shapeNode || refer.node);
                      }
              }
              return ctm ? new Matrix(ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f) : new Matrix();
          };
          return Matrix;
      });
      /**
       * 调色板
       */
      define("graphic/palette", ["graphic/standardcolor", "graphic/color", "core/utils", "core/class"], 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/utils", "graphic/svg", "graphic/container", "graphic/shapecontainer", "graphic/shape", "graphic/viewbox", "graphic/eventhandler", "graphic/shapeevent", "graphic/styled", "graphic/matrix", "graphic/box", "graphic/point", "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.clientWidth;
              },
              setWidth: function (width) {
                  this.node.setAttribute("width", width);
                  return this;
              },
              getHeight: function () {
                  return this.node.clientHeight;
              },
              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(" + 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();
                      return {
                          zoom: 1,
                          center: {
                              x: box.x + box.width / 2,
                              y: box.y + box.height / 2
                          },
                          offset: {
                              x: 0,
                              y: 0
                          }
                      };
                  }
                  return this.viewport;
              },
              getViewPortTransform: function () {
                  var m = this.shapeNode.getCTM();
                  return new Matrix(m.a, m.b, m.c, m.d, m.e, m.f);
              },
              getTransform: function () {
                  return this.getViewPortTransform().reverse();
              },
              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;
              },
              whenPaperReady: function (fn) {
                  var me = this;
  
                  function check() {
                      var paper = me.getPaper();
                      if (paper && fn) {
                          fn.call(me, paper);
                      }
                      return paper;
                  }
  
                  if (!check()) {
                      this.on("add treeadd", function listen() {
                          if (check()) {
                              me.off("add", listen);
                              me.off("treeadd", listen);
                          }
                      });
                  }
                  return this;
              }
          });
          return Paper;
      });
      define("graphic/path", ["core/utils", "core/class", "graphic/shape", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box", "graphic/geometry", "graphic/point", "graphic/vector"], 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 g = require("graphic/geometry");
          var slice = Array.prototype.slice, flatten = Utils.flatten;
          var PathDrawer = createClass("PathDrawer", {
              constructor: function (path) {
                  this.segment = [];
                  this.path = path;
                  this.__clear = false;
              },
              getPath: function () {
                  return this.path;
              },
              redraw: function () {
                  this._transation = this._transation || [];
                  return this.clear();
              },
              done: function () {
                  var transation = this._transation;
                  this._transation = null;
                  this.push(transation);
                  return this;
              },
              clear: function () {
                  if (this._transation) {
                      this._transation = [];
                  } else {
                      this.path.setPathData("M 0 0");
                  }
                  this._clear = true;
                  return this;
              },
              push: function () {
                  var segment = slice.call(arguments);
                  var originData;
                  if (this._transation) {
                      this._transation.push(segment);
                      return this;
                  }
                  if (this._clear) {
                      originData = "";
                      this._clear = false;
                  } else {
                      originData = this.path.getPathData();
                  }
                  originData = originData || "";
                  this.path.setPathData(originData + g.pathToString(segment));
                  return this;
              },
              moveTo: function (x, y) {
                  return this.push("M", slice.call(arguments));
              },
              moveBy: function (dx, dy) {
                  return this.push("m", slice.call(arguments));
              },
              lineTo: function (x, y) {
                  return this.push("L", slice.call(arguments));
              },
              lineBy: function (dx, dy) {
                  return this.push("l", slice.call(arguments));
              },
              arcTo: function (rx, ry, xr, laf, sf, x, y) {
                  return this.push("A", slice.call(arguments));
              },
              arcBy: function (rx, ry, xr, laf, sf, dx, dy) {
                  return this.push("a", arguments);
              },
              carcTo: function (r, laf, sf, x, y) {
                  return this.push("A", [r, r, 0].concat(slice.call(arguments, 1)));
              },
              carcBy: function (r, laf, sf, dx, dy) {
                  return this.push("a", [r, r, 0].concat(slice.call(arguments, 1)));
              },
              bezierTo: function (x1, y1, x2, y2, x, y) {
                  return this.push("C", slice.call(arguments));
              },
              bezierBy: function (dx1, dy1, dx2, dy2, dx, dy) {
                  return this.push("c", slice.call(arguments));
              },
              close: function () {
                  return this.push("z");
              }
          });
          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) {
                  data = data || "M0,0";
                  this.pathdata = g.pathToString(data);
                  this.node.setAttribute("d", this.pathdata);
                  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", "core/class", "graphic/resource", "graphic/shapecontainer", "graphic/container", "core/utils", "graphic/shape", "graphic/svg"], 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"], function (require, exports, module) {
          var Color = require("graphic/color");
          return require("core/class").createClass("Pen", {
              constructor: function (brush, width) {
                  this.brush = brush;
                  this.width = width || 1;
                  this.linecap = null;
                  this.linejoin = null;
                  this.dashArray = null;
                  this.opacity = 1;
              },
              getBrush: function () {
                  return this.brush;
              },
              setBrush: function (brush) {
                  this.brush = brush;
                  return this;
              },
              setColor: function (color) {
                  return this.setBrush(color);
              },
              getColor: function () {
                  return this.brush instanceof Color ? this.brush : null;
              },
              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.brush.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/pie", ["core/class", "graphic/sweep", "graphic/point", "graphic/path"], function (require, exports, module) {
          return require("core/class").createClass({
              base: require("graphic/sweep"),
              constructor: function (radius, angle, angleOffset) {
                  this.callBase([0, radius], angle, angleOffset);
              },
              getRadius: function () {
                  return this.getSectionArray()[1];
              },
              setRadius: function (radius) {
                  this.setSectionArray([0, radius]);
              }
          });
      });
      /*
   * 点对象抽象
   */
      define("graphic/point", ["core/class"], function (require, exports, module) {
          var Point = require("core/class").createClass("Point", {
              constructor: function (x, y) {
                  this.x = x || 0;
                  this.y = y || 0;
              },
              offset: function (dx, dy) {
                  if (arguments.length == 1) {
                      dy = dx.y;
                      dx = dx.x;
                  }
                  return new Point(this.x + dx, this.y + dy);
              },
              valueOf: function () {
                  return [this.x, this.y];
              },
              toString: function () {
                  return this.valueOf().join(" ");
              },
              spof: function () {
                  return new Point((this.x | 0) + .5, (this.y | 0) + .5);
              }
          });
          Point.fromPolar = function (radius, angle, unit) {
              if (unit != "rad") {
                  // deg to rad
                  angle = angle / 180 * Math.PI;
              }
              return new Point(radius * Math.cos(angle), radius * Math.sin(angle));
          };
          Point.parse = function (unknown) {
              if (unknown instanceof Point) {
                  return unknown;
              }
              if (typeof unknown == "string") {
                  return Point.parse(unknown.split(/\s*[\s,]\s*/));
              }
              if ("0" in unknown && "1" in unknown) {
                  return new Point(unknown[0], unknown[1]);
              }
          };
          return Point;
      });
      /**
       * 点集合容器
       */
      define("graphic/pointcontainer", ["core/class", "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", "graphic/path", "graphic/shape", "graphic/svg", "graphic/geometry", "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]);
                  for (var i = 1, point, len = points.length; i < len; i++) {
                      point = points[i];
                      drawer.lineTo(point);
                  }
                  if (this.closeable && points.length > 2) {
                      drawer.close();
                  }
                  return this;
              }
          });
      });
      define("graphic/polygon", ["core/class", "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", "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"], 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", "graphic/point", "core/class", "graphic/path", "graphic/shape", "graphic/svg", "graphic/geometry"], function (require, exports, module) {
          var RectUtils = {}, Utils = require("core/utils"), Point = require("graphic/point");
          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);
              }
          });
          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 x = this.x, y = this.y, w = this.width, h = this.height, r = this.radius;
                  var drawer = this.getDrawer().redraw();
                  if (!r) {
                      // 直角
                      drawer.push("M", x, y);
                      drawer.push("h", w);
                      drawer.push("v", h);
                      drawer.push("h", -w);
                      drawer.push("z");
                  } else {
                      //圆角
                      w -= 2 * r;
                      h -= 2 * r;
                      drawer.push("M", x + r, y);
                      drawer.push("h", w);
                      drawer.push("a", r, r, 0, 0, 1, r, r);
                      drawer.push("v", h);
                      drawer.push("a", r, r, 0, 0, 1, -r, r);
                      drawer.push("h", -w);
                      drawer.push("a", r, r, 0, 0, 1, -r, -r);
                      drawer.push("v", -h);
                      drawer.push("a", r, r, 0, 0, 1, r, -r);
                      drawer.push("z");
                  }
                  drawer.done();
                  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 new Point(this.x, this.y);
              },
              setPosition: function (x, y) {
                  if (arguments.length == 1) {
                      var p = Point.parse(arguments[0]);
                      y = p.y;
                      x = p.x;
                  }
                  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/regularpolygon", ["graphic/point", "core/class", "graphic/path", "core/utils", "graphic/shape", "graphic/svg", "graphic/geometry"], function (require, exports, module) {
          var Point = require("graphic/point");
          return require("core/class").createClass("RegularPolygon", {
              base: require("graphic/path"),
              constructor: function (side, radius, x, y) {
                  this.callBase();
                  this.radius = radius || 0;
                  this.side = Math.max(side || 3, 3);
                  if (arguments.length > 2) {
                      if (arguments.length == 3) {
                          y = x.y;
                          x = x.x;
                      }
                  }
                  this.center = new Point(x, y);
                  this.draw();
              },
              getSide: function () {
                  return this.side;
              },
              setSide: function (side) {
                  this.side = side;
                  return this.draw();
              },
              getRadius: function () {
                  return this.radius;
              },
              setRadius: function (radius) {
                  this.radius = radius;
                  return this.draw();
              },
              draw: function () {
                  var radius = this.radius, side = this.side, step = Math.PI * 2 / side, drawer = this.getDrawer(), i;
                  drawer.clear();
                  drawer.moveTo(Point.fromPolar(radius, Math.PI / 2, "rad").offset(this.center));
                  for (i = 0; i <= side; i++) {
                      drawer.lineTo(Point.fromPolar(radius, step * i + Math.PI / 2, "rad").offset(this.center));
                  }
                  drawer.close();
                  return this;
              }
          });
      });
      define("graphic/resource", ["graphic/svg", "core/class"], function (require, exports, module) {
          var svg = require("graphic/svg");
          return require("core/class").createClass("Resource", {
              constructor: function (nodeType) {
                  this.callBase();
                  this.node = svg.createNode(nodeType);
              },
              toString: function () {
                  return "url(#" + this.node.id + ")";
              }
          });
      });
      define("graphic/ring", ["core/class", "graphic/sweep", "graphic/point", "graphic/path"], function (require, exports, module) {
          return require("core/class").createClass({
              base: require("graphic/sweep"),
              constructor: function (innerRadius, outerRadius) {
                  this.callBase([innerRadius, outerRadius], 360, 0);
              },
              getInnerRadius: function () {
                  return this.getSectionArray()[0];
              },
              getOuterRadius: function () {
                  return this.getSectionArray()[1];
              },
              setInnerRadius: function (value) {
                  this.setSectionArray([value, this.getOuterRadius()]);
              },
              setOuterRadius: function (value) {
                  this.setSectionArray([this.getInnerRadius(), value]);
              }
          });
      });
      define("graphic/shape", ["graphic/svg", "core/utils", "graphic/eventhandler", "graphic/shapeevent", "core/class", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/box", "graphic/point", "graphic/pen", "graphic/color"], 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");
          var slice = Array.prototype.slice;
          var Box = require("graphic/box");
          var Shape = require("core/class").createClass("Shape", {
              mixins: [EventHandler, Styled, Data],
              constructor: function (tagName) {
                  this.node = svg.createNode(tagName);
                  this.node.shape = this;
                  this.transform = {
                      translate: null,
                      rotate: null,
                      scale: null,
                      matrix: null
                  };
                  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 new Box(box);
              },
              getRenderBox: function (refer) {
                  var box = this.getBoundaryBox();
                  var matrix = this.getTransform(refer);
                  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;
              },
              setVisible: function (value) {
                  if (value) {
                      this.node.removeAttribute("display");
                  } else {
                      this.node.setAttribute("display", "none");
                  }
                  return this;
              },
              getVisible: function () {
                  this.node.getAttribute("display");
              },
              hasAncestor: function (node) {
                  var parent = this.container;
                  while (parent) {
                      if (parent === node) {
                          return true;
                      }
                      parent = parent.container;
                  }
                  return false;
              },
              getTransform: function (refer) {
                  return Matrix.getCTM(this, refer);
              },
              clearTransform: function () {
                  this.node.removeAttribute("transform");
                  this.transform = {
                      translate: null,
                      rotate: null,
                      scale: null,
                      matrix: null
                  };
                  this.trigger("shapeupdate", {
                      type: "transform"
                  });
                  return this;
              },
              _applyTransform: function () {
                  var t = this.transform, result = [];
                  if (t.translate) {
                      result.push(["translate(", t.translate, ")"]);
                  }
                  if (t.rotate) {
                      result.push(["rotate(", t.rotate, ")"]);
                  }
                  if (t.scale) {
                      result.push(["scale(", t.scale, ")"]);
                  }
                  if (t.matrix) {
                      result.push(["matrix(", t.matrix, ")"]);
                  }
                  this.node.setAttribute("transform", utils.flatten(result).join(" "));
                  return this;
              },
              setMatrix: function (m) {
                  this.transform.matrix = m;
                  return this._applyTransform();
              },
              setTranslate: function (t) {
                  this.transform.translate = t !== null && slice.call(arguments) || null;
                  return this._applyTransform();
              },
              setRotate: function (r) {
                  this.transform.rotate = r !== null && slice.call(arguments) || null;
                  return this._applyTransform();
              },
              setScale: function (s) {
                  this.transform.scale = s !== null && slice.call(arguments) || null;
                  return this._applyTransform();
              },
              translate: function (dx, dy) {
                  var m = this.transform.matrix || new Matrix();
                  if (dy === undefined) {
                      dy = 0;
                  }
                  this.transform.matrix = m.translate(dx, dy);
                  return this._applyTransform();
              },
              rotate: function (deg) {
                  var m = this.transform.matrix || new Matrix();
                  this.transform.matrix = m.rotate(deg);
                  return this._applyTransform();
              },
              scale: function (sx, sy) {
                  var m = this.transform.matrix || new Matrix();
                  if (sy === undefined) {
                      sy = sx;
                  }
                  this.transform.matrix = m.scale(sx, sy);
                  return this._applyTransform();
              },
              skew: function (sx, sy) {
                  var m = this.transform.matrix || new Matrix();
                  if (sy === undefined) {
                      sy = sx;
                  }
                  this.transform.matrix = m.skew(sx, sy);
                  return this._applyTransform();
              },
              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) {
                  // 字符串或重写了 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);
              }
          });
          return Shape;
      });
      define("graphic/shapecontainer", ["graphic/container", "core/class", "core/utils", "graphic/shape", "graphic/svg", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], 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.notifyTreeModification) {
                          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/box", "graphic/point", "core/class"], function (require, exprots, module) {
          var Matrix = require("graphic/matrix"), Utils = require("core/utils"), Point = require("graphic/point");
          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._kityParam) {
                          Utils.extend(this, event._kityParam);
                      }
                  } 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 (refer, touchIndex) {
                  if (!this.originEvent) {
                      return null;
                  }
                  var eventClient = this.originEvent.touches ? this.originEvent.touches[touchIndex || 0] : this.originEvent;
                  var clientX = eventClient && eventClient.clientX || 0,
                      clientY = eventClient && eventClient.clientY || 0,
                      node = this.targetShape.shapeNode || this.targetShape.node, // 鼠标位置在目标对象上的坐标
                      // 基于屏幕坐标算
                      point = Matrix.transformPoint(clientX, clientY, node.getScreenCTM().inverse());
                  return Matrix.getCTM(this.targetShape, refer || "view").transformPoint(point);
              },
              stopPropagation: function () {
                  var evt = this.originEvent;
                  if (!evt) {
                      return true;
                  }
                  if (evt.stopPropagation) {
                      evt.stopPropagation();
                  } else {
                      evt.cancelBubble = false;
                  }
              }
          });
      });
      /*
   * 图形上的点抽象
   */
      define("graphic/shapepoint", ["core/class", "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) {
                  return this.setPoint(x, this.y);
              },
              setY: function (y) {
                  return this.setPoint(this.x, y);
              },
              setPoint: function (x, y) {
                  this.x = x;
                  this.y = y;
                  this.update();
                  return this;
              },
              getPoint: function () {
                  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/star", ["graphic/point", "core/class", "graphic/path", "core/utils", "graphic/shape", "graphic/svg", "graphic/geometry"], function (require, exports, module) {
          /**
           * @see http://www.jdawiseman.com/papers/easymath/surds_star_inner_radius.html
           */
          var defaultRatioForStar = {
              "3": .2,
              // yy
              "5": .38196601125,
              "6": .57735026919,
              "8": .541196100146,
              "10": .726542528005,
              "12": .707106781187
          };
          var Point = require("graphic/point");
          return require("core/class").createClass("Star", {
              base: require("graphic/path"),
              constructor: function (vertex, radius, shrink, offset, angleOffset) {
                  this.callBase();
                  this.vertex = vertex || 3;
                  this.radius = radius || 0;
                  this.shrink = shrink;
                  this.offset = offset || new Point(0, 0);
                  this.angleOffset = angleOffset || 0;
                  this.draw();
              },
              getVertex: function () {
                  return this.vertex;
              },
              setVertex: function (value) {
                  this.vertex = value;
                  return this.draw();
              },
              getRadius: function () {
                  return this.radius;
              },
              setRadius: function (value) {
                  this.radius = value;
                  return this.draw();
              },
              getShrink: function () {
                  return this.shrink;
              },
              setShrink: function (value) {
                  this.shrink = value;
                  return this.draw();
              },
              getOffset: function () {
                  return this.offset;
              },
              setOffset: function (value) {
                  this.offset = value;
                  return this.draw();
              },
              getAngleOffset: function () {
                  return this.angleOffset;
              },
              setAngleOffset: function (value) {
                  this.angleOffset = value;
                  return this.draw();
              },
              draw: function () {
                  var innerRadius = this.radius,
                      outerRadius = this.radius * (this.shrink || defaultRatioForStar[this.vertex] || .5),
                      vertex = this.vertex, offset = this.offset, angleStart = 90, angleStep = 180 / vertex,
                      angleOffset = this.angleOffset, drawer = this.getDrawer(), i, angle;
                  drawer.clear();
                  drawer.moveTo(Point.fromPolar(outerRadius, angleStart));
                  for (i = 1; i <= vertex * 2; i++) {
                      angle = angleStart + angleStep * i;
                      // 绘制内点
                      if (i % 2) {
                          drawer.lineTo(Point.fromPolar(innerRadius, angle + angleOffset).offset(offset));
                      } else {
                          drawer.lineTo(Point.fromPolar(outerRadius, angle));
                      }
                  }
                  drawer.close();
              }
          });
      });
      define("graphic/styled", ["core/class"], 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/sweep", ["graphic/point", "core/class", "graphic/path", "core/utils", "graphic/shape", "graphic/svg", "graphic/geometry"], function (require, exports, module) {
          var Point = require("graphic/point");
          return require("core/class").createClass("Sweep", {
              base: require("graphic/path"),
              constructor: function (sectionArray, angle, angleOffset) {
                  this.callBase();
                  this.sectionArray = sectionArray || [];
                  this.angle = angle || 0;
                  this.angleOffset = angleOffset || 0;
                  this.draw();
              },
              getSectionArray: function () {
                  return this.sectionArray;
              },
              setSectionArray: function (value) {
                  this.sectionArray = value;
                  return this.draw();
              },
              getAngle: function () {
                  return this.angle;
              },
              setAngle: function (value) {
                  this.angle = value;
                  return this.draw();
              },
              getAngleOffset: function () {
                  return this.angleOffset;
              },
              setAngleOffset: function (value) {
                  this.angleOffset = value;
                  return this.draw();
              },
              draw: function () {
                  var sectionArray = this.sectionArray, i;
                  for (i = 0; i < sectionArray.length; i += 2) {
                      this.drawSection(sectionArray[i], sectionArray[i + 1]);
                  }
                  return this;
              },
              drawSection: function (from, to) {
                  var angleLength = this.angle && (this.angle % 360 ? this.angle % 360 : 360),
                      angleStart = this.angleOffset, angleHalf = angleStart + angleLength / 2,
                      angleEnd = angleStart + angleLength, drawer = this.getDrawer();
                  drawer.redraw();
                  if (angleLength === 0) {
                      drawer.done();
                      return;
                  }
                  drawer.moveTo(Point.fromPolar(from, angleStart));
                  drawer.lineTo(Point.fromPolar(to, angleStart));
                  if (to) {
                      drawer.carcTo(to, 0, 1, Point.fromPolar(to, angleHalf));
                      drawer.carcTo(to, 0, 1, Point.fromPolar(to, angleEnd));
                  }
                  drawer.lineTo(Point.fromPolar(from, angleEnd));
                  if (from) {
                      drawer.carcTo(from, 0, 1, Point.fromPolar(from, angleHalf));
                      drawer.carcTo(from, 0, 1, Point.fromPolar(from, angleStart));
                  }
                  drawer.close();
                  drawer.done();
              }
          });
      });
      define("graphic/text", ["graphic/textcontent", "graphic/shape", "core/class", "graphic/shapecontainer", "graphic/container", "core/utils", "graphic/svg"], function (require, exports, module) {
          var TextContent = require("graphic/textcontent");
          var ShapeContainer = require("graphic/shapecontainer");
          var svg = require("graphic/svg");
          var offsetHash = {};
  
          function getTextBoundOffset(text) {
              var style = window.getComputedStyle(text.node);
              var font = [style.fontFamily, style.fontSize, style.fontStretch, style.fontStyle, style.fontVariant, style.fontWeight].join("-");
              if (offsetHash[font]) {
                  return offsetHash[font];
              }
              var textContent = text.getContent();
              text.setContent("test");
              var bbox = text.getBoundaryBox(), y = text.getY() + +text.node.getAttribute("dy");
              var topOffset = y - bbox.y, bottomOffset = topOffset - bbox.height;
              text.setContent(textContent);
              return offsetHash[font] = {
                  top: topOffset,
                  bottom: bottomOffset,
                  middle: (topOffset + bottomOffset) / 2
              };
          }
  
          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") || 0;
              },
              getY: function () {
                  return +this.node.getAttribute("y") || 0;
              },
              setFont: function (font) {
                  this.callBase(font);
                  return this.setVerticalAlign(this.getVerticalAlign());
              },
              setTextAnchor: function (anchor) {
                  this.node.setAttribute("text-anchor", anchor);
                  return this;
              },
              getTextAnchor: function () {
                  return this.node.getAttribute("text-anchor") || "start";
              },
              // top/bottom/middle/baseline
              setVerticalAlign: function (align) {
                  this.whenPaperReady(function () {
                      var dy;
                      switch (align) {
                          case "top":
                              dy = getTextBoundOffset(this).top;
                              break;
  
                          case "bottom":
                              dy = getTextBoundOffset(this).bottom;
                              break;
  
                          case "middle":
                              dy = getTextBoundOffset(this).middle;
                              break;
  
                          default:
                              dy = 0;
                      }
                      this.node.setAttribute("dy", dy);
                  });
                  this.verticalAlign = align;
                  return this;
              },
              getVerticalAlign: function () {
                  return this.verticalAlign || "baseline";
              },
              setStartOffset: function (offset) {
                  // only for text path
                  if (this.shapeNode != this.node) {
                      this.shapeNode.setAttribute("startOffset", offset * 100 + "%");
                  }
              },
              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.setTextAnchor(this.getTextAnchor());
                  return this;
              }
          });
      });
      define("graphic/textcontent", ["graphic/shape", "graphic/svg", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box", "core/class"], 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) {
                  return this.setFontSize(value);
              },
              setFontSize: function (value) {
                  return this.setFont({
                      size: value
                  });
              },
              setFontFamily: function (value) {
                  return this.setFont({
                      family: value
                  });
              },
              setFontBold: function (bold) {
                  return this.setFont({
                      weight: bold ? "bold" : "normal"
                  });
              },
              setFontItalic: function (italic) {
                  return this.setFont({
                      style: italic ? "italic" : "normal"
                  });
              },
              setFont: function (font) {
                  var node = this.node;
                  ["family", "size", "weight", "style"].forEach(function (section) {
                      if (font[section] === null) {
                          node.removeAttribute("font-" + section);
                      } else if (font[section]) {
                          node.setAttribute("font-" + section, font[section]);
                      }
                  });
                  return this;
              },
              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"], 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", "graphic/shape", "core/utils", "graphic/eventhandler", "graphic/styled", "graphic/data", "graphic/matrix", "graphic/pen", "graphic/box"], 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", ["graphic/point", "core/class", "graphic/matrix", "core/utils", "graphic/box"], function (require, exports, module) {
          var Point = require("graphic/point");
          var Matrix = require("graphic/matrix");
          var Vector = require("core/class").createClass("Vector", {
              base: Point,
              constructor: function (x, y) {
                  this.callBase(x, y);
              },
              square: function () {
                  return this.x * this.x + this.y * this.y;
              },
              length: function () {
                  return Math.sqrt(this.square());
              },
              add: function (q) {
                  return new Vector(this.x + q.x, this.y + q.y);
              },
              minus: function (q) {
                  return new Vector(this.x - q.x, this.y - q.y);
              },
              dot: function (q) {
                  return this.x * q.x + this.y * q.y;
              },
              project: function (q) {
                  return q.multipy(this.dot(q) / q.square());
              },
              normalize: function (length) {
                  if (length === undefined) {
                      length = 1;
                  }
                  return this.multipy(length / this.length());
              },
              multipy: function (scale) {
                  return new Vector(this.x * scale, this.y * scale);
              },
              rotate: function (angle, unit) {
                  if (unit == "rad") {
                      angle = angle / Math.PI * 180;
                  }
                  var p = new Matrix().rotate(angle).transformPoint(this);
                  return new Vector(p.x, p.y);
              },
              vertical: function () {
                  return new Vector(this.y, -this.x);
              },
              reverse: function () {
                  return this.multipy(-1);
              },
              getAngle: function () {
                  var length = this.length();
                  if (length === 0) return 0;
                  var rad = Math.acos(this.x / length);
                  var sign = this.y > 0 ? 1 : -1;
                  return sign * 180 * rad / Math.PI;
              }
          });
          Vector.fromPoints = function (p1, p2) {
              return new Vector(p2.x - p1.x, p2.y - p1.y);
          };
          require("core/class").extendClass(Point, {
              asVector: function () {
                  return new Vector(this.x, this.y);
              }
          });
          return Vector;
      });
      define("graphic/view", ["graphic/shapecontainer", "graphic/container", "core/utils", "core/class", "graphic/shape", "graphic/viewbox", "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"], 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;
              }
          });
      });
      define("kity", ["core/utils", "core/class", "core/browser", "graphic/bezier", "graphic/pointcontainer", "graphic/path", "graphic/bezierpoint", "graphic/shapepoint", "graphic/vector", "graphic/circle", "graphic/ellipse", "graphic/clip", "graphic/shape", "graphic/shapecontainer", "graphic/color", "graphic/standardcolor", "graphic/container", "graphic/curve", "graphic/point", "graphic/gradientbrush", "graphic/svg", "graphic/defbrush", "graphic/group", "graphic/hyperlink", "graphic/image", "graphic/line", "graphic/lineargradientbrush", "graphic/mask", "graphic/matrix", "graphic/box", "graphic/marker", "graphic/resource", "graphic/viewbox", "graphic/palette", "graphic/paper", "graphic/eventhandler", "graphic/styled", "graphic/geometry", "graphic/patternbrush", "graphic/pen", "graphic/polygon", "graphic/poly", "graphic/polyline", "graphic/pie", "graphic/sweep", "graphic/radialgradientbrush", "graphic/rect", "graphic/regularpolygon", "graphic/ring", "graphic/data", "graphic/star", "graphic/text", "graphic/textcontent", "graphic/textspan", "graphic/use", "animate/animator", "animate/timeline", "animate/easing", "animate/opacityanimator", "animate/rotateanimator", "animate/scaleanimator", "animate/frame", "animate/translateanimator", "animate/pathanimator", "animate/motionanimator", "filter/filter", "filter/effectcontainer", "filter/gaussianblurfilter", "filter/effect/gaussianblureffect", "filter/projectionfilter", "filter/effect/effect", "filter/effect/colormatrixeffect", "filter/effect/compositeeffect", "filter/effect/offseteffect", "filter/effect/convolvematrixeffect"], function (require, exports, module) {
          var kity = {}, utils = require("core/utils");
          kity.version = "2.0.0";
          utils.extend(kity, {
              // core
              createClass: require("core/class").createClass,
              extendClass: require("core/class").extendClass,
              Utils: 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"),
              Container: require("graphic/container"),
              Curve: require("graphic/curve"),
              Ellipse: require("graphic/ellipse"),
              GradientBrush: require("graphic/gradientbrush"),
              Group: require("graphic/group"),
              HyperLink: require("graphic/hyperlink"),
              Image: require("graphic/image"),
              Line: require("graphic/line"),
              LinearGradientBrush: require("graphic/lineargradientbrush"),
              Mask: require("graphic/mask"),
              Matrix: require("graphic/matrix"),
              Marker: require("graphic/marker"),
              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"),
              Pie: require("graphic/pie"),
              RadialGradientBrush: require("graphic/radialgradientbrush"),
              Rect: require("graphic/rect"),
              RegularPolygon: require("graphic/regularpolygon"),
              Ring: require("graphic/ring"),
              Shape: require("graphic/shape"),
              ShapePoint: require("graphic/shapepoint"),
              ShapeContainer: require("graphic/shapecontainer"),
              Sweep: require("graphic/sweep"),
              Star: require("graphic/star"),
              Text: require("graphic/text"),
              TextSpan: require("graphic/textspan"),
              Use: require("graphic/use"),
              Vector: require("graphic/vector"),
              g: require("graphic/geometry"),
              // 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"),
              PathAnimator: require("animate/pathanimator"),
              MotionAnimator: require("animate/motionanimator"),
              // 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")
          });
          return window.kity = kity;
      });
  
      /* global use, inc: true */
  
      /**
       * 模块暴露
       */
  
      (function () {
  
          try {
              inc.use('kity');
          } catch (e) {
              use('kity');
          }
  
      })();
  })();
  