PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

kity-formula-parser.all.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/tinymce/plugins/kitymath/kityformula/js/kity-formula-parser.all.min.js'
View Content
/*!
 * ====================================================
 * Kity Formula Parser - v1.0.0 - 2014-07-31
 * https://github.com/HanCong03/kityformula-editor
 * GitHub: https://github.com/kitygraph/kityformula-editor.git 
 * Copyright (c) 2014 Baidu Kity Group; Licensed MIT
 * ====================================================
 */
!function(){function a(a){b.r([c[a]])}var b={r:function(a){if(b[a].inited)return b[a].value;if("function"!=typeof b[a].value)return b[a].inited=!0,b[a].value;var c={exports:{}},d=b[a].value(null,c.exports,c);if(b[a].inited=!0,b[a].value=d,void 0!==d)return d;for(var e in c.exports)if(c.exports.hasOwnProperty(e))return b[a].inited=!0,b[a].value=c.exports,c.exports}};b[0]={value:function(){function a(a){this.formula=a}function b(a,e,f,g,i){var j,k=null,l=null,m=[],n=e.operand||[],o=null;if(f.operand=[],-1===e.name.indexOf("text")){for(var p=0,q=n.length;q>p;p++)k=n[p],k!==h?k?"string"==typeof k?(n[p]="brackets"===e.name&&2>p?k:"function"===e.name&&0===p?k:c("text",k),f.operand.push(n[p])):(f.operand.push({}),n[p]=b(a.operand[p],k,f.operand[f.operand.length-1],g,i)):(n[p]=c("empty"),f.operand.push(n[p])):(m.push(p),i.hasOwnProperty("startOffset")||(i.startOffset=p),i.endOffset=p,e.attr&&e.attr.id&&(i.groupId=e.attr.id));for(2===m.length&&(i.endOffset-=1);p=m.length;)p=m[p-1],n.splice(p,1),m.length--,a.operand.splice(p,1)}if(o=d(e.name),!o)throw new Error("operator type error: not found "+e.operator);j=function(){},j.prototype=o.prototype,l=new j,o.apply(l,n),f.func=l;for(var r in e.callFn)e.callFn.hasOwnProperty(r)&&l[r]&&l[r].apply(l,e.callFn[r]);return e.attr&&(e.attr.id&&(g[e.attr.id]={objGroup:l,strGroup:a}),e.attr["data-root"]&&(g.root={objGroup:l,strGroup:a}),l.setAttr(e.attr)),l}function c(a,b){switch(a){case"empty":return new kf.EmptyExpression;case"text":return new kf.TextExpression(b)}}function d(a){return g[a]||kf[a.replace(/^[a-z]/i,function(a){return a.toUpperCase()}).replace(/-([a-z])/gi,function(a,b){return b.toUpperCase()})+"Expression"]}function e(a){var b={};if("[object Array]"==={}.toString.call(a)){b=[];for(var c=0,d=a.length;d>c;c++)b[c]=f(a[c])}else for(var e in a)a.hasOwnProperty(e)&&(b[e]=f(a[e]));return b}function f(a){return a?"object"!=typeof a?a:e(a):a}var g={},h="\uf155";return a.prototype.generateBy=function(a){var c=a.tree,d={},f={},g={};if("string"==typeof c)throw new Error("Unhandled error");return this.formula.appendExpression(b(c,e(c),d,g,f)),{select:f,parsedTree:c,tree:d,mapping:g}},a.prototype.regenerateBy=function(a){return this.formula.clearExpressions(),this.generateBy(a)},a}},b[1]={value:function(){return{toRPNExpression:b.r(2),generateTree:b.r(3)}}},b[2]={value:function(){function a(b){var e=[],f=null;for(b=c(b);f=b.shift();)"combination"===f.name&&1===f.operand.length&&"brackets"===f.operand[0].name&&(f=f.operand[0]),e.push(d.isArray(f)?a(f):f);return e}function c(a){for(var b=[],c=null;void 0!==(c=a.pop());)if(!c||"object"!=typeof c||c.sign!==!1&&"function"!==c.name)b.push(c);else{var d=c.handler(c,[],b.reverse());b.unshift(d),b.reverse()}return b.reverse()}var d=b.r(4);return a}},b[3]={value:function(){function a(b){for(var e=null,f=[],g=0,h=b.length;h>g;g++)d.isArray(b[g])&&(b[g]=a(b[g]));for(;e=b.shift();)f.push("object"==typeof e&&e.handler?e.handler(e,f,b):e);return c(f)}var c=b.r(13),d=b.r(4);return a}},b[4]={value:function(){var a=b.r(7),c=b.r(6),d=b.r(15),e={getLatexType:function(b){return b=b.replace(/^\\/,""),a[b]?"operator":c[b]?"function":"text"},isArray:function(a){return a&&"[object Array]"===Object.prototype.toString.call(a)},getDefine:function(b){return e.extend({},a[b.replace("\\","")])},getFuncDefine:function(a){return{name:"function",params:a.replace(/^\\/,""),handler:d}},getBracketsDefine:function(b,c){return e.extend({params:[b,c]},a.brackets)},extend:function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}};return e}},b[5]={value:function(){var a=!0;return{".":a,"{":a,"}":a,"[":a,"]":a,"(":a,")":a,"|":a}}},b[6]={value:function(){return{sin:1,cos:1,arccos:1,cosh:1,det:1,inf:1,limsup:1,Pr:1,tan:1,arcsin:1,cot:1,dim:1,ker:1,ln:1,sec:1,tanh:1,arctan:1,coth:1,exp:1,lg:1,log:1,arg:1,csc:1,gcd:1,lim:1,max:1,sinh:1,deg:1,hom:1,liminf:1,min:1,sup:1}}},b[7]={value:function(){var a=b.r(22),c=b.r(11);return{"^":{name:"superscript",type:c.OP,handler:a},_:{name:"subscript",type:c.OP,handler:a},frac:{name:"fraction",type:c.FN,sign:!1,handler:b.r(14)},sqrt:{name:"radical",type:c.FN,sign:!1,handler:b.r(23)},sum:{name:"summation",type:c.FN,traversal:"rtl",handler:b.r(24)},"int":{name:"integration",type:c.FN,traversal:"rtl",handler:b.r(16)},brackets:{name:"brackets",type:c.FN,handler:b.r(12)},mathcal:{name:"mathcal",type:c.FN,sign:!1,handler:b.r(19)},mathfrak:{name:"mathfrak",type:c.FN,sign:!1,handler:b.r(20)},mathbb:{name:"mathbb",type:c.FN,sign:!1,handler:b.r(18)},mathrm:{name:"mathrm",type:c.FN,sign:!1,handler:b.r(21)}}}},b[8]={value:function(){return{"int":b.r(26),quot:b.r(27)}}},b[9]={value:function(){return{combination:b.r(29),fraction:b.r(30),"function":b.r(31),integration:b.r(32),subscript:b.r(39),superscript:b.r(41),script:b.r(37),radical:b.r(38),summation:b.r(40),brackets:b.r(28),mathcal:b.r(34),mathfrak:b.r(35),mathbb:b.r(33),mathrm:b.r(36)}}},b[10]={value:function(){return{"#":1,$:1,"%":1,_:1,"&":1,"{":1,"}":1,"^":1,"~":1}}},b[11]={value:function(){return{OP:1,FN:2}}},b[12]={value:function(){var a=b.r(5);return function(b,c,d){for(var e=0,f=b.params.length;f>e;e++)if(!(b.params[e]in a))throw new Error("Brackets: invalid params");return b.operand=b.params,b.params[2]=d.shift(),delete b.handler,delete b.params,b}}},b[13]={value:function(){return function(){return{name:"combination",operand:arguments[0]||[]}}}},b[14]={value:function(){return function(a,b,c){var d=c.shift(),e=c.shift();if(void 0===d||void 0===e)throw new Error("Frac: Syntax Error");return d.handler&&"integration"===d.name?(d=d.handler(d,b,[e]),e=c.shift()):e.handler&&"integration"===e.name&&(e=e.handler(e,b,[c.shift()])),a.operand=[d,e],delete a.handler,a}}},b[15]={value:function(){var a=b.r(17);return function(b,c,d){var e=a.exec(d);return e.expr&&e.expr.handler&&"integration"===e.expr.name&&(e.expr=e.expr.handler(e.expr,c,[d.shift()])),b.operand=[b.params,e.expr,e.superscript,e.subscript],delete b.params,delete b.handler,b}}},b[16]={value:function(){var a=b.r(17),c=b.r(11).FN;return function(b,d,e){var f=e.shift(),g=a.exec(e);return g.expr&&g.expr.type===c&&g.expr.handler&&"integration"===g.expr.name&&(g.expr=g.expr.handler(g.expr,d,[e.shift()])),b.operand=[g.expr,g.superscript,g.subscript],b.callFn={setType:[0|f]},delete b.handler,b}}},b[17]={value:function(){function a(a){var c=b(a),d=null,e={superscript:null,subscript:null};if(!c)return e;if(d=b(a),e[c.type]=c.value||null,d){if(d.type===c.type)throw new Error("Script: syntax error!");e[d.type]=d.value||null}return e}function b(a){var b=a.shift();return b?"subscript"===b.name||"superscript"===b.name?{type:b.name,value:a.shift()}:(a.unshift(b),null):null}return{exec:function(b){var c=a(b),d=b.shift();if(d&&d.name&&-1!==d.name.indexOf("script"))throw new Error("Script: syntax error!");return c.expr=d||null,c}}}},b[18]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathbb"},a.callFn={setFamily:["KF AMS BB"]},a.operand=[d],delete a.handler,a}}},b[19]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathcal"},a.callFn={setFamily:["KF AMS CAL"]},a.operand=[d],delete a.handler,a}}},b[20]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathfrak"},a.callFn={setFamily:["KF AMS FRAK"]},a.operand=[d],delete a.handler,a}}},b[21]={value:function(){return function(a,b,c){var d=c.shift();return"object"==typeof d&&"combination"===d.name&&(d=d.operand.join("")),a.name="text",a.attr={_reverse:"mathrm"},a.callFn={setFamily:["KF AMS ROMAN"]},a.operand=[d],delete a.handler,a}}},b[22]={value:function(){return function(a,b,c){var d=b.pop(),e=c.shift()||null;if(!e)throw new Error("Missing script");if(d=d||"",d.name===a.name||"script"===d.name)throw new Error("script error");return"subscript"===d.name?(d.name="script",d.operand[2]=d.operand[1],d.operand[1]=e,d):"superscript"===d.name?(d.name="script",d.operand[2]=e,d):(a.operand=[d,e],delete a.handler,a)}}},b[23]={value:function(){var a=b.r(13);return function(b,c,d){var e=d.shift(),f=null,g=null;if("["===e){for(e=[];(f=d.shift())&&"]"!==f;)e.push(f);e=0===e.length?null:a(e),g=d.shift()}else g=e,e=null;return b.operand=[g,e],delete b.handler,b}}},b[24]={value:function(){var a=b.r(17),c=b.r(11).FN;return function(b,d,e){var f=a.exec(e);return f.expr&&f.expr.type===c&&f.expr.handler&&"integration"===f.expr.name&&(f.expr=f.expr.handler(f.expr,d,[e.shift()])),b.operand=[f.expr,f.superscript,f.subscript],delete b.handler,b}}},b[25]={value:function(){function a(a){if(d(a))return a.substring(1);switch(m.getLatexType(a)){case"operator":return m.getDefine(a);case"function":return m.getFuncDefine(a);default:return c(a)}}function c(a){return 0===a.indexOf("\\")?a+"\\":a}function d(a){return 0===a.indexOf("\\")?!!l[a.substring(1)]:!1}function e(a){return a.replace(/\\\s+/,"").replace(/\s*([^a-z0-9\s])\s*/gi,function(a,b){return b})}var f=b.r(43).Parser,g=b.r(1),h=b.r(8),i=b.r(42),j=b.r(7),k=b.r(9),l=b.r(10),m=b.r(4),n="\ufff8",o="\ufffc",p=new RegExp(n+"|"+o,"g"),q=new RegExp(n,"g"),r=new RegExp(o,"g");f.register("latex",f.implement({parse:function(a){var b=this.split(this.format(a));return b=this.parseToGroup(b),b=this.parseToStruct(b),this.generateTree(b)},serialization:function(a,b){return i(a,b)},expand:function(a){var b=a.parse,c=null,d=a.pre,e=a.reverse;for(var f in b)b.hasOwnProperty(f)&&(c=f.replace(/\\/g,""),j[c]=b[f]);for(var f in e)e.hasOwnProperty(f)&&(k[f.replace(/\\/g,"")]=e[f]);if(d)for(var f in d)d.hasOwnProperty(f)&&(h[f.replace(/\\/g,"")]=d[f])},format:function(a){a=e(a),a=a.replace(p,"").replace(/\\{/gi,n).replace(/\\}/gi,o);for(var b in h)h.hasOwnProperty(b)&&(a=h[b](a));return a},split:function(a){var b=[],c=/(?:\\[^a-z]\s*)|(?:\\[a-z]+\s*)|(?:[{}]\s*)|(?:[^\\{}]\s*)/gi,d=/^\s+|\s+$/g,e=null;for(a=a.replace(d,"");e=c.exec(a);)e=e[0].replace(d,""),e&&b.push(e);return b},generateTree:function(a){for(var b=[],c=null;c=a.shift();)b.push(m.isArray(c)?this.generateTree(c):c);return b=g.toRPNExpression(b),g.generateTree(b)},parseToGroup:function(a){for(var b=[],c=[b],d=0,e=0,f=0,g=a.length;g>f;f++)switch(a[f]){case"{":d++,c.push(b),b.push([]),b=b[b.length-1];break;case"}":d--,b=c.pop();break;case"\\left":e++,c.push(b),b.push([[]]),b=b[b.length-1][0],b.type="brackets",f++,b.leftBrackets=a[f].replace(q,"{").replace(r,"}");break;case"\\right":e--,f++,b.rightBrackets=a[f].replace(q,"{").replace(r,"}"),b=c.pop();break;default:b.push(a[f].replace(q,"\\{").replace(r,"\\}"))}if(0!==d)throw new Error("Group Error!");if(0!==e)throw new Error("Brackets Error!");return c[0]},parseToStruct:function(b){for(var c=[],d=0,e=b.length;e>d;d++)m.isArray(b[d])?"brackets"===b[d].type?(c.push(m.getBracketsDefine(b[d].leftBrackets,b[d].rightBrackets)),c.push(this.parseToStruct(b[d]))):c.push(this.parseToStruct(b[d])):c.push(a(b[d]));return c}}))}},b[26]={value:function(){return function(a){return a.replace(/\\(i+)nt(\b|[^a-zA-Z])/g,function(a,b,c){return"\\int "+b.length+c})}}},b[27]={value:function(){return function(a){return a.replace(/``/g,"\u201c")}}},b[28]={value:function(){return function(a){return("{"===a[0]||"}"===a[0])&&(a[0]="\\"+a[0]),("{"===a[1]||"}"===a[1])&&(a[1]="\\"+a[1]),["\\left",a[0],a[2],"\\right",a[1]].join(" ")}}},b[29]={value:function(){return function(a){return this.attr["data-root"]||this.attr["data-placeholder"]?a.join(""):"{"+a.join("")+"}"}}},b[30]={value:function(){return function(a){return"\\frac "+a[0]+" "+a[1]}}},b[31]={value:function(){return function(a){var b=["\\"+a[0]];return a[2]&&b.push("^"+a[2]),a[3]&&b.push("_"+a[3]),a[1]&&b.push(" "+a[1]),b.join("")}}},b[32]={value:function(){return function(a){var b=["\\int "];if(this.callFn&&this.callFn.setType){b=["\\"];for(var c=0,d=this.callFn.setType;d>c;c++)b.push("i");b.push("nt ")}return a[1]&&b.push("^"+a[1]),a[2]&&b.push("_"+a[2]),a[0]&&b.push(" "+a[0]),b.join("")}}},b[33]={value:function(){return function(a){return"\\mathbb{"+a[0]+"}"}}},b[34]={value:function(){return function(a){return"\\mathcal{"+a[0]+"}"}}},b[35]={value:function(){return function(a){return"\\mathfrak{"+a[0]+"}"}}},b[36]={value:function(){return function(a){return"\\mathrm{"+a[0]+"}"}}},b[37]={value:function(){return function(a){return a[0]+"^"+a[1]+"_"+a[2]}}},b[38]={value:function(){return function(a){var b=["\\sqrt"];return a[1]&&b.push("["+a[1]+"]"),b.push(" "+a[0]),b.join("")}}},b[39]={value:function(){return function(a){return a[0]+"_"+a[1]}}},b[40]={value:function(){return function(a){var b=["\\sum "];return a[1]&&b.push("^"+a[1]),a[2]&&b.push("_"+a[2]),a[0]&&b.push(" "+a[0]),b.join("")}}},b[41]={value:function(){return function(a){return a[0]+"^"+a[1]}}},b[42]={value:function(){function a(b,e){var g=[],h=null,i=null;if("object"!=typeof b)return c(b)?"\\"+b+" ":b.replace(f,function(a,b){return b+" "});"combination"===b.name&&1===b.operand.length&&"combination"===b.operand[0].name&&(b=b.operand[0]),i=b.operand;for(var j=0,k=i.length;k>j;j++)g.push(i[j]?a(i[j]):i[j]);return h=b.attr&&b.attr._reverse?b.attr._reverse:b.name,d[h].call(b,g,e)}function c(a){return!!e[a]}var d=b.r(9),e=b.r(10),f=/(\\(?:[\w]+)|(?:[^a-z]))\\/gi;return function(b,c){return a(b,c)}}},b[43]={value:function(a,b,c){function d(a){this.impl=new a,this.conf={}}function e(){this.conf={}}var f={},g={},h={extend:function(a,b){var c=null;b=[].slice.call(arguments,1);for(var d=0,e=b.length;e>d;d++){c=b[d];for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f])}},setData:function(a,b,c){if("string"==typeof b)a[b]=c;else{if("object"!=typeof b)throw new Error("invalid option");for(c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}}},i={use:function(a){if(!g[a])throw new Error("unknown parser type");return this.proxy(g[a])},config:function(a,b){return h.setData(f,a,b),this},register:function(a,b){return g[a.toLowerCase()]=b,this},implement:function(a){var b=function(){},c=a.constructor||function(){},d=function(){e.call(this),c.call(this)};b.prototype=e.prototype,d.prototype=new b,delete a.constructor;for(var f in a)"constructor"!==f&&a.hasOwnProperty(f)&&(d.prototype[f]=a[f]);return d},proxy:function(a){return new d(a)}};h.extend(d.prototype,{config:function(a,b){h.setData(this.conf,a,b)},set:function(a,b){this.impl.set(a,b)},parse:function(a){var b={config:{},tree:this.impl.parse(a)};return h.extend(b.config,f,this.conf),b},serialization:function(a,b){return this.impl.serialization(a,b)},expand:function(a){this.impl.expand(a)}}),h.extend(e.prototype,{set:function(a,b){h.extend(this.conf,a,b)},parse:function(){throw new Error("Abstract function")}}),c.exports={Parser:i,ParserInterface:e}}},b[44]={value:function(){var a=b.r(43).Parser;b.r(25),window.kf.Parser=a,window.kf.Assembly=b.r(0)}};var c={"kf.start":44};!function(){try{a("kf.start")}catch(b){}}(this)}();
kity-formula-render.all.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/tinymce/plugins/kitymath/kityformula/js/kity-formula-render.all.js'
View Content
/*!
 * ====================================================
 * Kity Formula Render - v1.0.0 - 2014-07-30
 * https://github.com/kitygraph/formula
 * GitHub: https://github.com/kitygraph/formula.git 
 * Copyright (c) 2014 Baidu Kity Group; Licensed MIT
 * ====================================================
 */

(function () {
var _p = {
    r: function(index) {
        if (_p[index].inited) {
            return _p[index].value;
        }
        if (typeof _p[index].value === "function") {
            var module = {
                exports: {}
            }, returnValue = _p[index].value(null, module.exports, module);
            _p[index].inited = true;
            _p[index].value = returnValue;
            if (returnValue !== undefined) {
                return returnValue;
            } else {
                for (var key in module.exports) {
                    if (module.exports.hasOwnProperty(key)) {
                        _p[index].inited = true;
                        _p[index].value = module.exports;
                        return module.exports;
                    }
                }
            }
        } else {
            _p[index].inited = true;
            return _p[index].value;
        }
    }
};

/*!
 * canvg库封装
 * canvg官网: https://code.google.com/p/canvg/
 */
_p[0] = {
    value: function(require) {
        /**
     * A class to parse color values
     * @author Stoyan Stefanov <sstoo@gmail.com>
     * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
     * @license Use it if you like it
     */
        function RGBColor(color_string) {
            this.ok = false;
            // strip any leading #
            if (color_string.charAt(0) == "#") {
                // remove # if any
                color_string = color_string.substr(1, 6);
            }
            color_string = color_string.replace(/ /g, "");
            color_string = color_string.toLowerCase();
            // before getting into regexps, try simple matches
            // and overwrite the input
            var simple_colors = {
                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",
                darkkhaki: "bdb76b",
                darkmagenta: "8b008b",
                darkolivegreen: "556b2f",
                darkorange: "ff8c00",
                darkorchid: "9932cc",
                darkred: "8b0000",
                darksalmon: "e9967a",
                darkseagreen: "8fbc8f",
                darkslateblue: "483d8b",
                darkslategray: "2f4f4f",
                darkturquoise: "00ced1",
                darkviolet: "9400d3",
                deeppink: "ff1493",
                deepskyblue: "00bfff",
                dimgray: "696969",
                dodgerblue: "1e90ff",
                feldspar: "d19275",
                firebrick: "b22222",
                floralwhite: "fffaf0",
                forestgreen: "228b22",
                fuchsia: "ff00ff",
                gainsboro: "dcdcdc",
                ghostwhite: "f8f8ff",
                gold: "ffd700",
                goldenrod: "daa520",
                gray: "808080",
                green: "008000",
                greenyellow: "adff2f",
                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",
                lightgrey: "d3d3d3",
                lightgreen: "90ee90",
                lightpink: "ffb6c1",
                lightsalmon: "ffa07a",
                lightseagreen: "20b2aa",
                lightskyblue: "87cefa",
                lightslateblue: "8470ff",
                lightslategray: "778899",
                lightsteelblue: "b0c4de",
                lightyellow: "ffffe0",
                lime: "00ff00",
                limegreen: "32cd32",
                linen: "faf0e6",
                magenta: "ff00ff",
                maroon: "800000",
                mediumaquamarine: "66cdaa",
                mediumblue: "0000cd",
                mediumorchid: "ba55d3",
                mediumpurple: "9370d8",
                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: "d87093",
                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",
                snow: "fffafa",
                springgreen: "00ff7f",
                steelblue: "4682b4",
                tan: "d2b48c",
                teal: "008080",
                thistle: "d8bfd8",
                tomato: "ff6347",
                turquoise: "40e0d0",
                violet: "ee82ee",
                violetred: "d02090",
                wheat: "f5deb3",
                white: "ffffff",
                whitesmoke: "f5f5f5",
                yellow: "ffff00",
                yellowgreen: "9acd32"
            };
            for (var key in simple_colors) {
                if (color_string == key) {
                    color_string = simple_colors[key];
                }
            }
            // emd of simple type-in colors
            // array of color definition objects
            var color_defs = [ {
                re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
                example: [ "rgb(123, 234, 45)", "rgb(255,234,245)" ],
                process: function(bits) {
                    return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ];
                }
            }, {
                re: /^(\w{2})(\w{2})(\w{2})$/,
                example: [ "#00ff00", "336699" ],
                process: function(bits) {
                    return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16) ];
                }
            }, {
                re: /^(\w{1})(\w{1})(\w{1})$/,
                example: [ "#fb0", "f0f" ],
                process: function(bits) {
                    return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16) ];
                }
            } ];
            // search through the definitions to find a match
            for (var i = 0; i < color_defs.length; i++) {
                var re = color_defs[i].re;
                var processor = color_defs[i].process;
                var bits = re.exec(color_string);
                if (bits) {
                    channels = processor(bits);
                    this.r = channels[0];
                    this.g = channels[1];
                    this.b = channels[2];
                    this.ok = true;
                }
            }
            // validate/cleanup values
            this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
            this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
            this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b;
            // some getters
            this.toRGB = function() {
                return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
            };
            this.toHex = function() {
                var r = this.r.toString(16);
                var g = this.g.toString(16);
                var b = this.b.toString(16);
                if (r.length == 1) r = "0" + r;
                if (g.length == 1) g = "0" + g;
                if (b.length == 1) b = "0" + b;
                return "#" + r + g + b;
            };
            // help
            this.getHelpXML = function() {
                var examples = new Array();
                // add regexps
                for (var i = 0; i < color_defs.length; i++) {
                    var example = color_defs[i].example;
                    for (var j = 0; j < example.length; j++) {
                        examples[examples.length] = example[j];
                    }
                }
                // add type-in colors
                for (var sc in simple_colors) {
                    examples[examples.length] = sc;
                }
                var xml = document.createElement("ul");
                xml.setAttribute("id", "rgbcolor-examples");
                for (var i = 0; i < examples.length; i++) {
                    try {
                        var list_item = document.createElement("li");
                        var list_color = new RGBColor(examples[i]);
                        var example_div = document.createElement("div");
                        example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex();
                        example_div.appendChild(document.createTextNode("test"));
                        var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex());
                        list_item.appendChild(example_div);
                        list_item.appendChild(list_item_value);
                        xml.appendChild(list_item);
                    } catch (e) {}
                }
                return xml;
            };
        }
        /*

     StackBlur - a fast almost Gaussian Blur For Canvas

     Version: 	0.5
     Author:		Mario Klingemann
     Contact: 	mario@quasimondo.com
     Website:	http://www.quasimondo.com/StackBlurForCanvas
     Twitter:	@quasimondo

     In case you find this class useful - especially in commercial projects -
     I am not totally unhappy for a small donation to my PayPal account
     mario@quasimondo.de

     Or support me on flattr:
     https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript

     Copyright (c) 2010 Mario Klingemann

     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation
     files (the "Software"), to deal in the Software without
     restriction, including without limitation the rights to use,
     copy, modify, merge, publish, distribute, sublicense, and/or sell
     copies of the Software, and to permit persons to whom the
     Software is furnished to do so, subject to the following
     conditions:

     The above copyright notice and this permission notice shall be
     included in all copies or substantial portions of the Software.

     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     OTHER DEALINGS IN THE SOFTWARE.
     */
        var mul_table = [ 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 ];
        var shg_table = [ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ];
        function stackBlurImage(imageID, canvasID, radius, blurAlphaChannel) {
            var img = document.getElementById(imageID);
            var w = img.naturalWidth;
            var h = img.naturalHeight;
            var canvas = document.getElementById(canvasID);
            canvas.style.width = w + "px";
            canvas.style.height = h + "px";
            canvas.width = w;
            canvas.height = h;
            var context = canvas.getContext("2d");
            context.clearRect(0, 0, w, h);
            context.drawImage(img, 0, 0);
            if (isNaN(radius) || radius < 1) return;
            if (blurAlphaChannel) stackBlurCanvasRGBA(canvasID, 0, 0, w, h, radius); else stackBlurCanvasRGB(canvasID, 0, 0, w, h, radius);
        }
        function stackBlurCanvasRGBA(id, top_x, top_y, width, height, radius) {
            if (isNaN(radius) || radius < 1) return;
            radius |= 0;
            var canvas = document.getElementById(id);
            var context = canvas.getContext("2d");
            var imageData;
            try {
                try {
                    imageData = context.getImageData(top_x, top_y, width, height);
                } catch (e) {
                    // NOTE: this part is supposedly only needed if you want to work with local files
                    // so it might be okay to remove the whole try/catch block and just use
                    // imageData = context.getImageData( top_x, top_y, width, height );
                    try {
                        netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
                        imageData = context.getImageData(top_x, top_y, width, height);
                    } catch (e) {
                        alert("Cannot access local image");
                        throw new Error("unable to access local image data: " + e);
                        return;
                    }
                }
            } catch (e) {
                alert("Cannot access image");
                throw new Error("unable to access image data: " + e);
            }
            var pixels = imageData.data;
            var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum, r_out_sum, g_out_sum, b_out_sum, a_out_sum, r_in_sum, g_in_sum, b_in_sum, a_in_sum, pr, pg, pb, pa, rbs;
            var div = radius + radius + 1;
            var w4 = width << 2;
            var widthMinus1 = width - 1;
            var heightMinus1 = height - 1;
            var radiusPlus1 = radius + 1;
            var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
            var stackStart = new BlurStack();
            var stack = stackStart;
            for (i = 1; i < div; i++) {
                stack = stack.next = new BlurStack();
                if (i == radiusPlus1) var stackEnd = stack;
            }
            stack.next = stackStart;
            var stackIn = null;
            var stackOut = null;
            yw = yi = 0;
            var mul_sum = mul_table[radius];
            var shg_sum = shg_table[radius];
            for (y = 0; y < height; y++) {
                r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
                r_out_sum = radiusPlus1 * (pr = pixels[yi]);
                g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
                b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
                a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
                r_sum += sumFactor * pr;
                g_sum += sumFactor * pg;
                b_sum += sumFactor * pb;
                a_sum += sumFactor * pa;
                stack = stackStart;
                for (i = 0; i < radiusPlus1; i++) {
                    stack.r = pr;
                    stack.g = pg;
                    stack.b = pb;
                    stack.a = pa;
                    stack = stack.next;
                }
                for (i = 1; i < radiusPlus1; i++) {
                    p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
                    r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
                    g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
                    b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
                    a_sum += (stack.a = pa = pixels[p + 3]) * rbs;
                    r_in_sum += pr;
                    g_in_sum += pg;
                    b_in_sum += pb;
                    a_in_sum += pa;
                    stack = stack.next;
                }
                stackIn = stackStart;
                stackOut = stackEnd;
                for (x = 0; x < width; x++) {
                    pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum;
                    if (pa != 0) {
                        pa = 255 / pa;
                        pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa;
                        pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa;
                        pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa;
                    } else {
                        pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
                    }
                    r_sum -= r_out_sum;
                    g_sum -= g_out_sum;
                    b_sum -= b_out_sum;
                    a_sum -= a_out_sum;
                    r_out_sum -= stackIn.r;
                    g_out_sum -= stackIn.g;
                    b_out_sum -= stackIn.b;
                    a_out_sum -= stackIn.a;
                    p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
                    r_in_sum += stackIn.r = pixels[p];
                    g_in_sum += stackIn.g = pixels[p + 1];
                    b_in_sum += stackIn.b = pixels[p + 2];
                    a_in_sum += stackIn.a = pixels[p + 3];
                    r_sum += r_in_sum;
                    g_sum += g_in_sum;
                    b_sum += b_in_sum;
                    a_sum += a_in_sum;
                    stackIn = stackIn.next;
                    r_out_sum += pr = stackOut.r;
                    g_out_sum += pg = stackOut.g;
                    b_out_sum += pb = stackOut.b;
                    a_out_sum += pa = stackOut.a;
                    r_in_sum -= pr;
                    g_in_sum -= pg;
                    b_in_sum -= pb;
                    a_in_sum -= pa;
                    stackOut = stackOut.next;
                    yi += 4;
                }
                yw += width;
            }
            for (x = 0; x < width; x++) {
                g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
                yi = x << 2;
                r_out_sum = radiusPlus1 * (pr = pixels[yi]);
                g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
                b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
                a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
                r_sum += sumFactor * pr;
                g_sum += sumFactor * pg;
                b_sum += sumFactor * pb;
                a_sum += sumFactor * pa;
                stack = stackStart;
                for (i = 0; i < radiusPlus1; i++) {
                    stack.r = pr;
                    stack.g = pg;
                    stack.b = pb;
                    stack.a = pa;
                    stack = stack.next;
                }
                yp = width;
                for (i = 1; i <= radius; i++) {
                    yi = yp + x << 2;
                    r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
                    g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
                    b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
                    a_sum += (stack.a = pa = pixels[yi + 3]) * rbs;
                    r_in_sum += pr;
                    g_in_sum += pg;
                    b_in_sum += pb;
                    a_in_sum += pa;
                    stack = stack.next;
                    if (i < heightMinus1) {
                        yp += width;
                    }
                }
                yi = x;
                stackIn = stackStart;
                stackOut = stackEnd;
                for (y = 0; y < height; y++) {
                    p = yi << 2;
                    pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum;
                    if (pa > 0) {
                        pa = 255 / pa;
                        pixels[p] = (r_sum * mul_sum >> shg_sum) * pa;
                        pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa;
                        pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa;
                    } else {
                        pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
                    }
                    r_sum -= r_out_sum;
                    g_sum -= g_out_sum;
                    b_sum -= b_out_sum;
                    a_sum -= a_out_sum;
                    r_out_sum -= stackIn.r;
                    g_out_sum -= stackIn.g;
                    b_out_sum -= stackIn.b;
                    a_out_sum -= stackIn.a;
                    p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
                    r_sum += r_in_sum += stackIn.r = pixels[p];
                    g_sum += g_in_sum += stackIn.g = pixels[p + 1];
                    b_sum += b_in_sum += stackIn.b = pixels[p + 2];
                    a_sum += a_in_sum += stackIn.a = pixels[p + 3];
                    stackIn = stackIn.next;
                    r_out_sum += pr = stackOut.r;
                    g_out_sum += pg = stackOut.g;
                    b_out_sum += pb = stackOut.b;
                    a_out_sum += pa = stackOut.a;
                    r_in_sum -= pr;
                    g_in_sum -= pg;
                    b_in_sum -= pb;
                    a_in_sum -= pa;
                    stackOut = stackOut.next;
                    yi += width;
                }
            }
            context.putImageData(imageData, top_x, top_y);
        }
        function stackBlurCanvasRGB(id, top_x, top_y, width, height, radius) {
            if (isNaN(radius) || radius < 1) return;
            radius |= 0;
            var canvas = document.getElementById(id);
            var context = canvas.getContext("2d");
            var imageData;
            try {
                try {
                    imageData = context.getImageData(top_x, top_y, width, height);
                } catch (e) {
                    // NOTE: this part is supposedly only needed if you want to work with local files
                    // so it might be okay to remove the whole try/catch block and just use
                    // imageData = context.getImageData( top_x, top_y, width, height );
                    try {
                        netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
                        imageData = context.getImageData(top_x, top_y, width, height);
                    } catch (e) {
                        alert("Cannot access local image");
                        throw new Error("unable to access local image data: " + e);
                        return;
                    }
                }
            } catch (e) {
                alert("Cannot access image");
                throw new Error("unable to access image data: " + e);
            }
            var pixels = imageData.data;
            var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, r_out_sum, g_out_sum, b_out_sum, r_in_sum, g_in_sum, b_in_sum, pr, pg, pb, rbs;
            var div = radius + radius + 1;
            var w4 = width << 2;
            var widthMinus1 = width - 1;
            var heightMinus1 = height - 1;
            var radiusPlus1 = radius + 1;
            var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
            var stackStart = new BlurStack();
            var stack = stackStart;
            for (i = 1; i < div; i++) {
                stack = stack.next = new BlurStack();
                if (i == radiusPlus1) var stackEnd = stack;
            }
            stack.next = stackStart;
            var stackIn = null;
            var stackOut = null;
            yw = yi = 0;
            var mul_sum = mul_table[radius];
            var shg_sum = shg_table[radius];
            for (y = 0; y < height; y++) {
                r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0;
                r_out_sum = radiusPlus1 * (pr = pixels[yi]);
                g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
                b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
                r_sum += sumFactor * pr;
                g_sum += sumFactor * pg;
                b_sum += sumFactor * pb;
                stack = stackStart;
                for (i = 0; i < radiusPlus1; i++) {
                    stack.r = pr;
                    stack.g = pg;
                    stack.b = pb;
                    stack = stack.next;
                }
                for (i = 1; i < radiusPlus1; i++) {
                    p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
                    r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
                    g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
                    b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
                    r_in_sum += pr;
                    g_in_sum += pg;
                    b_in_sum += pb;
                    stack = stack.next;
                }
                stackIn = stackStart;
                stackOut = stackEnd;
                for (x = 0; x < width; x++) {
                    pixels[yi] = r_sum * mul_sum >> shg_sum;
                    pixels[yi + 1] = g_sum * mul_sum >> shg_sum;
                    pixels[yi + 2] = b_sum * mul_sum >> shg_sum;
                    r_sum -= r_out_sum;
                    g_sum -= g_out_sum;
                    b_sum -= b_out_sum;
                    r_out_sum -= stackIn.r;
                    g_out_sum -= stackIn.g;
                    b_out_sum -= stackIn.b;
                    p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
                    r_in_sum += stackIn.r = pixels[p];
                    g_in_sum += stackIn.g = pixels[p + 1];
                    b_in_sum += stackIn.b = pixels[p + 2];
                    r_sum += r_in_sum;
                    g_sum += g_in_sum;
                    b_sum += b_in_sum;
                    stackIn = stackIn.next;
                    r_out_sum += pr = stackOut.r;
                    g_out_sum += pg = stackOut.g;
                    b_out_sum += pb = stackOut.b;
                    r_in_sum -= pr;
                    g_in_sum -= pg;
                    b_in_sum -= pb;
                    stackOut = stackOut.next;
                    yi += 4;
                }
                yw += width;
            }
            for (x = 0; x < width; x++) {
                g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0;
                yi = x << 2;
                r_out_sum = radiusPlus1 * (pr = pixels[yi]);
                g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
                b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
                r_sum += sumFactor * pr;
                g_sum += sumFactor * pg;
                b_sum += sumFactor * pb;
                stack = stackStart;
                for (i = 0; i < radiusPlus1; i++) {
                    stack.r = pr;
                    stack.g = pg;
                    stack.b = pb;
                    stack = stack.next;
                }
                yp = width;
                for (i = 1; i <= radius; i++) {
                    yi = yp + x << 2;
                    r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
                    g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
                    b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
                    r_in_sum += pr;
                    g_in_sum += pg;
                    b_in_sum += pb;
                    stack = stack.next;
                    if (i < heightMinus1) {
                        yp += width;
                    }
                }
                yi = x;
                stackIn = stackStart;
                stackOut = stackEnd;
                for (y = 0; y < height; y++) {
                    p = yi << 2;
                    pixels[p] = r_sum * mul_sum >> shg_sum;
                    pixels[p + 1] = g_sum * mul_sum >> shg_sum;
                    pixels[p + 2] = b_sum * mul_sum >> shg_sum;
                    r_sum -= r_out_sum;
                    g_sum -= g_out_sum;
                    b_sum -= b_out_sum;
                    r_out_sum -= stackIn.r;
                    g_out_sum -= stackIn.g;
                    b_out_sum -= stackIn.b;
                    p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
                    r_sum += r_in_sum += stackIn.r = pixels[p];
                    g_sum += g_in_sum += stackIn.g = pixels[p + 1];
                    b_sum += b_in_sum += stackIn.b = pixels[p + 2];
                    stackIn = stackIn.next;
                    r_out_sum += pr = stackOut.r;
                    g_out_sum += pg = stackOut.g;
                    b_out_sum += pb = stackOut.b;
                    r_in_sum -= pr;
                    g_in_sum -= pg;
                    b_in_sum -= pb;
                    stackOut = stackOut.next;
                    yi += width;
                }
            }
            context.putImageData(imageData, top_x, top_y);
        }
        function BlurStack() {
            this.r = 0;
            this.g = 0;
            this.b = 0;
            this.a = 0;
            this.next = null;
        }
        /*
     * canvg.js - Javascript SVG parser and renderer on Canvas
     * MIT Licensed 
     * Gabe Lerner (gabelerner@gmail.com)
     * http://code.google.com/p/canvg/
     *
     * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
     */
        (function() {
            // canvg(target, s)
            // empty parameters: replace all 'svg' elements on page with 'canvas' elements
            // target: canvas element or the id of a canvas element
            // s: svg string, url to svg file, or xml document
            // opts: optional hash of options
            //		 ignoreMouse: true => ignore mouse events
            //		 ignoreAnimation: true => ignore animations
            //		 ignoreDimensions: true => does not try to resize canvas
            //		 ignoreClear: true => does not clear canvas
            //		 offsetX: int => draws at a x offset
            //		 offsetY: int => draws at a y offset
            //		 scaleWidth: int => scales horizontally to width
            //		 scaleHeight: int => scales vertically to height
            //		 renderCallback: function => will call the function after the first render is completed
            //		 forceRedraw: function => will call the function on every frame, if it returns true, will redraw
            this.canvg = function(target, s, opts) {
                // no parameters
                if (target == null && s == null && opts == null) {
                    var svgTags = document.getElementsByTagName("svg");
                    for (var i = 0; i < svgTags.length; i++) {
                        var svgTag = svgTags[i];
                        var c = document.createElement("canvas");
                        c.width = svgTag.clientWidth;
                        c.height = svgTag.clientHeight;
                        svgTag.parentNode.insertBefore(c, svgTag);
                        svgTag.parentNode.removeChild(svgTag);
                        var div = document.createElement("div");
                        div.appendChild(svgTag);
                        canvg(c, div.innerHTML);
                    }
                    return;
                }
                opts = opts || {};
                if (typeof target == "string") {
                    target = document.getElementById(target);
                }
                // store class on canvas
                if (target.svg != null) target.svg.stop();
                var svg = build();
                // on i.e. 8 for flash canvas, we can't assign the property so check for it
                if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == "OBJECT")) target.svg = svg;
                svg.opts = opts;
                var ctx = target.getContext("2d");
                if (typeof s.documentElement != "undefined") {
                    // load from xml doc
                    svg.loadXmlDoc(ctx, s);
                } else if (s.substr(0, 1) == "<") {
                    // load from xml string
                    svg.loadXml(ctx, s);
                } else {
                    // load from url
                    svg.load(ctx, s);
                }
            };
            function build() {
                var svg = {};
                svg.FRAMERATE = 30;
                svg.MAX_VIRTUAL_PIXELS = 3e4;
                // globals
                svg.init = function(ctx) {
                    var uniqueId = 0;
                    svg.UniqueId = function() {
                        uniqueId++;
                        return "canvg" + uniqueId;
                    };
                    svg.Definitions = {};
                    svg.Styles = {};
                    svg.Animations = [];
                    svg.Images = [];
                    svg.ctx = ctx;
                    svg.ViewPort = new function() {
                        this.viewPorts = [];
                        this.Clear = function() {
                            this.viewPorts = [];
                        };
                        this.SetCurrent = function(width, height) {
                            this.viewPorts.push({
                                width: width,
                                height: height
                            });
                        };
                        this.RemoveCurrent = function() {
                            this.viewPorts.pop();
                        };
                        this.Current = function() {
                            return this.viewPorts[this.viewPorts.length - 1];
                        };
                        this.width = function() {
                            return this.Current().width;
                        };
                        this.height = function() {
                            return this.Current().height;
                        };
                        this.ComputeSize = function(d) {
                            if (d != null && typeof d == "number") return d;
                            if (d == "x") return this.width();
                            if (d == "y") return this.height();
                            return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
                        };
                    }();
                };
                svg.init();
                // images loaded
                svg.ImagesLoaded = function() {
                    for (var i = 0; i < svg.Images.length; i++) {
                        if (!svg.Images[i].loaded) return false;
                    }
                    return true;
                };
                // trim
                svg.trim = function(s) {
                    return s.replace(/^\s+|\s+$/g, "");
                };
                // compress spaces
                svg.compressSpaces = function(s) {
                    return s.replace(/[\s\r\t\n]+/gm, " ");
                };
                // ajax
                svg.ajax = function(url) {
                    var AJAX;
                    if (window.XMLHttpRequest) {
                        AJAX = new XMLHttpRequest();
                    } else {
                        AJAX = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    if (AJAX) {
                        AJAX.open("GET", url, false);
                        AJAX.send(null);
                        return AJAX.responseText;
                    }
                    return null;
                };
                // parse xml
                svg.parseXml = function(xml) {
                    if (window.DOMParser) {
                        var parser = new DOMParser();
                        return parser.parseFromString(xml, "text/xml");
                    } else {
                        xml = xml.replace(/<!DOCTYPE svg[^>]*>/, "");
                        var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                        xmlDoc.async = "false";
                        xmlDoc.loadXML(xml);
                        return xmlDoc;
                    }
                };
                svg.Property = function(name, value) {
                    this.name = name;
                    this.value = value;
                };
                svg.Property.prototype.getValue = function() {
                    return this.value;
                };
                svg.Property.prototype.hasValue = function() {
                    return this.value != null && this.value !== "";
                };
                // return the numerical value of the property
                svg.Property.prototype.numValue = function() {
                    if (!this.hasValue()) return 0;
                    var n = parseFloat(this.value);
                    if ((this.value + "").match(/%$/)) {
                        n = n / 100;
                    }
                    return n;
                };
                svg.Property.prototype.valueOrDefault = function(def) {
                    if (this.hasValue()) return this.value;
                    return def;
                };
                svg.Property.prototype.numValueOrDefault = function(def) {
                    if (this.hasValue()) return this.numValue();
                    return def;
                };
                // color extensions
                // augment the current color value with the opacity
                svg.Property.prototype.addOpacity = function(opacity) {
                    var newValue = this.value;
                    if (opacity != null && opacity != "" && typeof this.value == "string") {
                        // can only add opacity to colors, not patterns
                        var color = new RGBColor(this.value);
                        if (color.ok) {
                            newValue = "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + opacity + ")";
                        }
                    }
                    return new svg.Property(this.name, newValue);
                };
                // definition extensions
                // get the definition from the definitions table
                svg.Property.prototype.getDefinition = function() {
                    var name = this.value.match(/#([^\)'"]+)/);
                    if (name) {
                        name = name[1];
                    }
                    if (!name) {
                        name = this.value;
                    }
                    return svg.Definitions[name];
                };
                svg.Property.prototype.isUrlDefinition = function() {
                    return this.value.indexOf("url(") == 0;
                };
                svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
                    var def = this.getDefinition();
                    // gradient
                    if (def != null && def.createGradient) {
                        return def.createGradient(svg.ctx, e, opacityProp);
                    }
                    // pattern
                    if (def != null && def.createPattern) {
                        if (def.getHrefAttribute().hasValue()) {
                            var pt = def.attribute("patternTransform");
                            def = def.getHrefAttribute().getDefinition();
                            if (pt.hasValue()) {
                                def.attribute("patternTransform", true).value = pt.value;
                            }
                        }
                        return def.createPattern(svg.ctx, e);
                    }
                    return null;
                };
                // length extensions
                svg.Property.prototype.getDPI = function(viewPort) {
                    return 96;
                };
                svg.Property.prototype.getEM = function(viewPort) {
                    var em = 12;
                    var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
                    if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
                    return em;
                };
                svg.Property.prototype.getUnits = function() {
                    var s = this.value + "";
                    return s.replace(/[0-9\.\-]/g, "");
                };
                // get the length as pixels
                svg.Property.prototype.toPixels = function(viewPort, processPercent) {
                    if (!this.hasValue()) return 0;
                    var s = this.value + "";
                    if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
                    if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2;
                    if (s.match(/px$/)) return this.numValue();
                    if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1 / 72);
                    if (s.match(/pc$/)) return this.numValue() * 15;
                    if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
                    if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
                    if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
                    if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
                    var n = this.numValue();
                    if (processPercent && n < 1) return n * svg.ViewPort.ComputeSize(viewPort);
                    return n;
                };
                // time extensions
                // get the time as milliseconds
                svg.Property.prototype.toMilliseconds = function() {
                    if (!this.hasValue()) return 0;
                    var s = this.value + "";
                    if (s.match(/s$/)) return this.numValue() * 1e3;
                    if (s.match(/ms$/)) return this.numValue();
                    return this.numValue();
                };
                // angle extensions
                // get the angle as radians
                svg.Property.prototype.toRadians = function() {
                    if (!this.hasValue()) return 0;
                    var s = this.value + "";
                    if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180);
                    if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200);
                    if (s.match(/rad$/)) return this.numValue();
                    return this.numValue() * (Math.PI / 180);
                };
                // fonts
                svg.Font = new function() {
                    this.Styles = "normal|italic|oblique|inherit";
                    this.Variants = "normal|small-caps|inherit";
                    this.Weights = "normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit";
                    this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
                        var f = inherit != null ? this.Parse(inherit) : this.CreateFont("", "", "", "", "", svg.ctx.font);
                        return {
                            fontFamily: fontFamily || f.fontFamily,
                            fontSize: fontSize || f.fontSize,
                            fontStyle: fontStyle || f.fontStyle,
                            fontWeight: fontWeight || f.fontWeight,
                            fontVariant: fontVariant || f.fontVariant,
                            toString: function() {
                                return [ this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily ].join(" ");
                            }
                        };
                    };
                    var that = this;
                    this.Parse = function(s) {
                        var f = {};
                        var d = svg.trim(svg.compressSpaces(s || "")).split(" ");
                        var set = {
                            fontSize: false,
                            fontStyle: false,
                            fontWeight: false,
                            fontVariant: false
                        };
                        var ff = "";
                        for (var i = 0; i < d.length; i++) {
                            if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) {
                                if (d[i] != "inherit") f.fontStyle = d[i];
                                set.fontStyle = true;
                            } else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) {
                                if (d[i] != "inherit") f.fontVariant = d[i];
                                set.fontStyle = set.fontVariant = true;
                            } else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {
                                if (d[i] != "inherit") f.fontWeight = d[i];
                                set.fontStyle = set.fontVariant = set.fontWeight = true;
                            } else if (!set.fontSize) {
                                if (d[i] != "inherit") f.fontSize = d[i].split("/")[0];
                                set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true;
                            } else {
                                if (d[i] != "inherit") ff += d[i];
                            }
                        }
                        if (ff != "") f.fontFamily = ff;
                        return f;
                    };
                }();
                // points and paths
                svg.ToNumberArray = function(s) {
                    var a = svg.trim(svg.compressSpaces((s || "").replace(/,/g, " "))).split(" ");
                    for (var i = 0; i < a.length; i++) {
                        a[i] = parseFloat(a[i]);
                    }
                    return a;
                };
                svg.Point = function(x, y) {
                    this.x = x;
                    this.y = y;
                };
                svg.Point.prototype.angleTo = function(p) {
                    return Math.atan2(p.y - this.y, p.x - this.x);
                };
                svg.Point.prototype.applyTransform = function(v) {
                    var xp = this.x * v[0] + this.y * v[2] + v[4];
                    var yp = this.x * v[1] + this.y * v[3] + v[5];
                    this.x = xp;
                    this.y = yp;
                };
                svg.CreatePoint = function(s) {
                    var a = svg.ToNumberArray(s);
                    return new svg.Point(a[0], a[1]);
                };
                svg.CreatePath = function(s) {
                    var a = svg.ToNumberArray(s);
                    var path = [];
                    for (var i = 0; i < a.length; i += 2) {
                        path.push(new svg.Point(a[i], a[i + 1]));
                    }
                    return path;
                };
                // bounding box
                svg.BoundingBox = function(x1, y1, x2, y2) {
                    // pass in initial points if you want
                    this.x1 = Number.NaN;
                    this.y1 = Number.NaN;
                    this.x2 = Number.NaN;
                    this.y2 = Number.NaN;
                    this.x = function() {
                        return this.x1;
                    };
                    this.y = function() {
                        return this.y1;
                    };
                    this.width = function() {
                        return this.x2 - this.x1;
                    };
                    this.height = function() {
                        return this.y2 - this.y1;
                    };
                    this.addPoint = function(x, y) {
                        if (x != null) {
                            if (isNaN(this.x1) || isNaN(this.x2)) {
                                this.x1 = x;
                                this.x2 = x;
                            }
                            if (x < this.x1) this.x1 = x;
                            if (x > this.x2) this.x2 = x;
                        }
                        if (y != null) {
                            if (isNaN(this.y1) || isNaN(this.y2)) {
                                this.y1 = y;
                                this.y2 = y;
                            }
                            if (y < this.y1) this.y1 = y;
                            if (y > this.y2) this.y2 = y;
                        }
                    };
                    this.addX = function(x) {
                        this.addPoint(x, null);
                    };
                    this.addY = function(y) {
                        this.addPoint(null, y);
                    };
                    this.addBoundingBox = function(bb) {
                        this.addPoint(bb.x1, bb.y1);
                        this.addPoint(bb.x2, bb.y2);
                    };
                    this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
                        var cp1x = p0x + 2 / 3 * (p1x - p0x);
                        // CP1 = QP0 + 2/3 *(QP1-QP0)
                        var cp1y = p0y + 2 / 3 * (p1y - p0y);
                        // CP1 = QP0 + 2/3 *(QP1-QP0)
                        var cp2x = cp1x + 1 / 3 * (p2x - p0x);
                        // CP2 = CP1 + 1/3 *(QP2-QP0)
                        var cp2y = cp1y + 1 / 3 * (p2y - p0y);
                        // CP2 = CP1 + 1/3 *(QP2-QP0)
                        this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
                    };
                    this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
                        // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
                        var p0 = [ p0x, p0y ], p1 = [ p1x, p1y ], p2 = [ p2x, p2y ], p3 = [ p3x, p3y ];
                        this.addPoint(p0[0], p0[1]);
                        this.addPoint(p3[0], p3[1]);
                        for (i = 0; i <= 1; i++) {
                            var f = function(t) {
                                return Math.pow(1 - t, 3) * p0[i] + 3 * Math.pow(1 - t, 2) * t * p1[i] + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + Math.pow(t, 3) * p3[i];
                            };
                            var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
                            var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
                            var c = 3 * p1[i] - 3 * p0[i];
                            if (a == 0) {
                                if (b == 0) continue;
                                var t = -c / b;
                                if (0 < t && t < 1) {
                                    if (i == 0) this.addX(f(t));
                                    if (i == 1) this.addY(f(t));
                                }
                                continue;
                            }
                            var b2ac = Math.pow(b, 2) - 4 * c * a;
                            if (b2ac < 0) continue;
                            var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
                            if (0 < t1 && t1 < 1) {
                                if (i == 0) this.addX(f(t1));
                                if (i == 1) this.addY(f(t1));
                            }
                            var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
                            if (0 < t2 && t2 < 1) {
                                if (i == 0) this.addX(f(t2));
                                if (i == 1) this.addY(f(t2));
                            }
                        }
                    };
                    this.isPointInBox = function(x, y) {
                        return this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2;
                    };
                    this.addPoint(x1, y1);
                    this.addPoint(x2, y2);
                };
                // transforms
                svg.Transform = function(v) {
                    var that = this;
                    this.Type = {};
                    // translate
                    this.Type.translate = function(s) {
                        this.p = svg.CreatePoint(s);
                        this.apply = function(ctx) {
                            ctx.translate(this.p.x || 0, this.p.y || 0);
                        };
                        this.unapply = function(ctx) {
                            ctx.translate(-1 * this.p.x || 0, -1 * this.p.y || 0);
                        };
                        this.applyToPoint = function(p) {
                            p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
                        };
                    };
                    // rotate
                    this.Type.rotate = function(s) {
                        var a = svg.ToNumberArray(s);
                        this.angle = new svg.Property("angle", a[0]);
                        this.cx = a[1] || 0;
                        this.cy = a[2] || 0;
                        this.apply = function(ctx) {
                            ctx.translate(this.cx, this.cy);
                            ctx.rotate(this.angle.toRadians());
                            ctx.translate(-this.cx, -this.cy);
                        };
                        this.unapply = function(ctx) {
                            ctx.translate(this.cx, this.cy);
                            ctx.rotate(-1 * this.angle.toRadians());
                            ctx.translate(-this.cx, -this.cy);
                        };
                        this.applyToPoint = function(p) {
                            var a = this.angle.toRadians();
                            p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
                            p.applyTransform([ Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0 ]);
                            p.applyTransform([ 1, 0, 0, 1, -this.p.x || 0, -this.p.y || 0 ]);
                        };
                    };
                    this.Type.scale = function(s) {
                        this.p = svg.CreatePoint(s);
                        this.apply = function(ctx) {
                            ctx.scale(this.p.x || 1, this.p.y || this.p.x || 1);
                        };
                        this.unapply = function(ctx) {
                            ctx.scale(1 / this.p.x || 1, 1 / this.p.y || this.p.x || 1);
                        };
                        this.applyToPoint = function(p) {
                            p.applyTransform([ this.p.x || 0, 0, 0, this.p.y || 0, 0, 0 ]);
                        };
                    };
                    this.Type.matrix = function(s) {
                        this.m = svg.ToNumberArray(s);
                        this.apply = function(ctx) {
                            ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
                        };
                        this.applyToPoint = function(p) {
                            p.applyTransform(this.m);
                        };
                    };
                    this.Type.SkewBase = function(s) {
                        this.base = that.Type.matrix;
                        this.base(s);
                        this.angle = new svg.Property("angle", s);
                    };
                    this.Type.SkewBase.prototype = new this.Type.matrix();
                    this.Type.skewX = function(s) {
                        this.base = that.Type.SkewBase;
                        this.base(s);
                        this.m = [ 1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0 ];
                    };
                    this.Type.skewX.prototype = new this.Type.SkewBase();
                    this.Type.skewY = function(s) {
                        this.base = that.Type.SkewBase;
                        this.base(s);
                        this.m = [ 1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0 ];
                    };
                    this.Type.skewY.prototype = new this.Type.SkewBase();
                    this.transforms = [];
                    this.apply = function(ctx) {
                        for (var i = 0; i < this.transforms.length; i++) {
                            this.transforms[i].apply(ctx);
                        }
                    };
                    this.unapply = function(ctx) {
                        for (var i = this.transforms.length - 1; i >= 0; i--) {
                            this.transforms[i].unapply(ctx);
                        }
                    };
                    this.applyToPoint = function(p) {
                        for (var i = 0; i < this.transforms.length; i++) {
                            this.transforms[i].applyToPoint(p);
                        }
                    };
                    var data = svg.trim(svg.compressSpaces(v)).replace(/\)(\s?,\s?)/g, ") ").split(/\s(?=[a-z])/);
                    for (var i = 0; i < data.length; i++) {
                        var type = svg.trim(data[i].split("(")[0]);
                        var s = data[i].split("(")[1].replace(")", "");
                        var transform = new this.Type[type](s);
                        transform.type = type;
                        this.transforms.push(transform);
                    }
                };
                // aspect ratio
                svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
                    // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
                    aspectRatio = svg.compressSpaces(aspectRatio);
                    aspectRatio = aspectRatio.replace(/^defer\s/, "");
                    // ignore defer
                    var align = aspectRatio.split(" ")[0] || "xMidYMid";
                    var meetOrSlice = aspectRatio.split(" ")[1] || "meet";
                    // calculate scale
                    var scaleX = width / desiredWidth;
                    var scaleY = height / desiredHeight;
                    var scaleMin = Math.min(scaleX, scaleY);
                    var scaleMax = Math.max(scaleX, scaleY);
                    if (meetOrSlice == "meet") {
                        desiredWidth *= scaleMin;
                        desiredHeight *= scaleMin;
                    }
                    if (meetOrSlice == "slice") {
                        desiredWidth *= scaleMax;
                        desiredHeight *= scaleMax;
                    }
                    refX = new svg.Property("refX", refX);
                    refY = new svg.Property("refY", refY);
                    if (refX.hasValue() && refY.hasValue()) {
                        ctx.translate(-scaleMin * refX.toPixels("x"), -scaleMin * refY.toPixels("y"));
                    } else {
                        // align
                        if (align.match(/^xMid/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width / 2 - desiredWidth / 2, 0);
                        if (align.match(/YMid$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height / 2 - desiredHeight / 2);
                        if (align.match(/^xMax/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width - desiredWidth, 0);
                        if (align.match(/YMax$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height - desiredHeight);
                    }
                    // scale
                    if (align == "none") ctx.scale(scaleX, scaleY); else if (meetOrSlice == "meet") ctx.scale(scaleMin, scaleMin); else if (meetOrSlice == "slice") ctx.scale(scaleMax, scaleMax);
                    // translate
                    ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
                };
                // elements
                svg.Element = {};
                svg.EmptyProperty = new svg.Property("EMPTY", "");
                svg.Element.ElementBase = function(node) {
                    this.attributes = {};
                    this.styles = {};
                    this.children = [];
                    // get or create attribute
                    this.attribute = function(name, createIfNotExists) {
                        var a = this.attributes[name];
                        if (a != null) return a;
                        if (createIfNotExists == true) {
                            a = new svg.Property(name, "");
                            this.attributes[name] = a;
                        }
                        return a || svg.EmptyProperty;
                    };
                    this.getHrefAttribute = function() {
                        for (var a in this.attributes) {
                            if (a.match(/:href$/)) {
                                return this.attributes[a];
                            }
                        }
                        return svg.EmptyProperty;
                    };
                    // get or create style, crawls up node tree
                    this.style = function(name, createIfNotExists) {
                        var s = this.styles[name];
                        if (s != null) return s;
                        var a = this.attribute(name);
                        if (a != null && a.hasValue()) {
                            this.styles[name] = a;
                            // move up to me to cache
                            return a;
                        }
                        var p = this.parent;
                        if (p != null) {
                            var ps = p.style(name);
                            if (ps != null && ps.hasValue()) {
                                return ps;
                            }
                        }
                        if (createIfNotExists == true) {
                            s = new svg.Property(name, "");
                            this.styles[name] = s;
                        }
                        return s || svg.EmptyProperty;
                    };
                    // base render
                    this.render = function(ctx) {
                        // don't render display=none
                        if (this.style("display").value == "none") return;
                        // don't render visibility=hidden
                        if (this.attribute("visibility").value == "hidden") return;
                        ctx.save();
                        if (this.attribute("mask").hasValue()) {
                            // mask
                            var mask = this.attribute("mask").getDefinition();
                            if (mask != null) mask.apply(ctx, this);
                        } else if (this.style("filter").hasValue()) {
                            // filter
                            var filter = this.style("filter").getDefinition();
                            if (filter != null) filter.apply(ctx, this);
                        } else {
                            this.setContext(ctx);
                            this.renderChildren(ctx);
                            this.clearContext(ctx);
                        }
                        ctx.restore();
                    };
                    // base set context
                    this.setContext = function(ctx) {};
                    // base clear context
                    this.clearContext = function(ctx) {};
                    // base render children
                    this.renderChildren = function(ctx) {
                        for (var i = 0; i < this.children.length; i++) {
                            this.children[i].render(ctx);
                        }
                    };
                    this.addChild = function(childNode, create) {
                        var child = childNode;
                        if (create) child = svg.CreateElement(childNode);
                        child.parent = this;
                        this.children.push(child);
                    };
                    if (node != null && node.nodeType == 1) {
                        //ELEMENT_NODE
                        // add children
                        for (var i = 0; i < node.childNodes.length; i++) {
                            var childNode = node.childNodes[i];
                            if (childNode.nodeType == 1) this.addChild(childNode, true);
                            //ELEMENT_NODE
                            if (this.captureTextNodes && childNode.nodeType == 3) {
                                var text = childNode.nodeValue || childNode.text || "";
                                if (svg.trim(svg.compressSpaces(text)) != "") {
                                    this.addChild(new svg.Element.tspan(childNode), false);
                                }
                            }
                        }
                        // add attributes
                        for (var i = 0; i < node.attributes.length; i++) {
                            var attribute = node.attributes[i];
                            this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);
                        }
                        // add tag styles
                        var styles = svg.Styles[node.nodeName];
                        if (styles != null) {
                            for (var name in styles) {
                                this.styles[name] = styles[name];
                            }
                        }
                        // add class styles
                        if (this.attribute("class").hasValue()) {
                            var classes = svg.compressSpaces(this.attribute("class").value).split(" ");
                            for (var j = 0; j < classes.length; j++) {
                                styles = svg.Styles["." + classes[j]];
                                if (styles != null) {
                                    for (var name in styles) {
                                        this.styles[name] = styles[name];
                                    }
                                }
                                styles = svg.Styles[node.nodeName + "." + classes[j]];
                                if (styles != null) {
                                    for (var name in styles) {
                                        this.styles[name] = styles[name];
                                    }
                                }
                            }
                        }
                        // add id styles
                        if (this.attribute("id").hasValue()) {
                            var styles = svg.Styles["#" + this.attribute("id").value];
                            if (styles != null) {
                                for (var name in styles) {
                                    this.styles[name] = styles[name];
                                }
                            }
                        }
                        // add inline styles
                        if (this.attribute("style").hasValue()) {
                            var styles = this.attribute("style").value.split(";");
                            for (var i = 0; i < styles.length; i++) {
                                if (svg.trim(styles[i]) != "") {
                                    var style = styles[i].split(":");
                                    var name = svg.trim(style[0]);
                                    var value = svg.trim(style[1]);
                                    this.styles[name] = new svg.Property(name, value);
                                }
                            }
                        }
                        // add id
                        if (this.attribute("id").hasValue()) {
                            if (svg.Definitions[this.attribute("id").value] == null) {
                                svg.Definitions[this.attribute("id").value] = this;
                            }
                        }
                    }
                };
                svg.Element.RenderedElementBase = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.setContext = function(ctx) {
                        // fill
                        if (this.style("fill").isUrlDefinition()) {
                            var fs = this.style("fill").getFillStyleDefinition(this, this.style("fill-opacity"));
                            if (fs != null) ctx.fillStyle = fs;
                        } else if (this.style("fill").hasValue()) {
                            var fillStyle = this.style("fill");
                            if (fillStyle.value == "currentColor") fillStyle.value = this.style("color").value;
                            ctx.fillStyle = fillStyle.value == "none" ? "rgba(0,0,0,0)" : fillStyle.value;
                        }
                        if (this.style("fill-opacity").hasValue()) {
                            var fillStyle = new svg.Property("fill", ctx.fillStyle);
                            fillStyle = fillStyle.addOpacity(this.style("fill-opacity").value);
                            ctx.fillStyle = fillStyle.value;
                        }
                        // stroke
                        if (this.style("stroke").isUrlDefinition()) {
                            var fs = this.style("stroke").getFillStyleDefinition(this, this.style("stroke-opacity"));
                            if (fs != null) ctx.strokeStyle = fs;
                        } else if (this.style("stroke").hasValue()) {
                            var strokeStyle = this.style("stroke");
                            if (strokeStyle.value == "currentColor") strokeStyle.value = this.style("color").value;
                            ctx.strokeStyle = strokeStyle.value == "none" ? "rgba(0,0,0,0)" : strokeStyle.value;
                        }
                        if (this.style("stroke-opacity").hasValue()) {
                            var strokeStyle = new svg.Property("stroke", ctx.strokeStyle);
                            strokeStyle = strokeStyle.addOpacity(this.style("stroke-opacity").value);
                            ctx.strokeStyle = strokeStyle.value;
                        }
                        if (this.style("stroke-width").hasValue()) {
                            var newLineWidth = this.style("stroke-width").toPixels();
                            ctx.lineWidth = newLineWidth == 0 ? .001 : newLineWidth;
                        }
                        if (this.style("stroke-linecap").hasValue()) ctx.lineCap = this.style("stroke-linecap").value;
                        if (this.style("stroke-linejoin").hasValue()) ctx.lineJoin = this.style("stroke-linejoin").value;
                        if (this.style("stroke-miterlimit").hasValue()) ctx.miterLimit = this.style("stroke-miterlimit").value;
                        if (this.style("stroke-dasharray").hasValue()) {
                            var gaps = svg.ToNumberArray(this.style("stroke-dasharray").value);
                            if (typeof ctx.setLineDash != "undefined") {
                                ctx.setLineDash(gaps);
                            } else if (typeof ctx.webkitLineDash != "undefined") {
                                ctx.webkitLineDash = gaps;
                            } else if (typeof ctx.mozDash != "undefined") {
                                ctx.mozDash = gaps;
                            }
                            var offset = this.style("stroke-dashoffset").numValueOrDefault(1);
                            if (typeof ctx.lineDashOffset != "undefined") {
                                ctx.lineDashOffset = offset;
                            } else if (typeof ctx.webkitLineDashOffset != "undefined") {
                                ctx.webkitLineDashOffset = offset;
                            } else if (typeof ctx.mozDashOffset != "undefined") {
                                ctx.mozDashOffset = offset;
                            }
                        }
                        // font
                        if (typeof ctx.font != "undefined") {
                            ctx.font = svg.Font.CreateFont(this.style("font-style").value, this.style("font-variant").value, this.style("font-weight").value, this.style("font-size").hasValue() ? this.style("font-size").toPixels() + "px" : "", this.style("font-family").value).toString();
                        }
                        // transform
                        if (this.attribute("transform").hasValue()) {
                            var transform = new svg.Transform(this.attribute("transform").value);
                            transform.apply(ctx);
                        }
                        // clip
                        if (this.style("clip-path").hasValue()) {
                            var clip = this.style("clip-path").getDefinition();
                            if (clip != null) clip.apply(ctx);
                        }
                        // opacity
                        if (this.style("opacity").hasValue()) {
                            ctx.globalAlpha = this.style("opacity").numValue();
                        }
                    };
                };
                svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase();
                svg.Element.PathElementBase = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.path = function(ctx) {
                        if (ctx != null) ctx.beginPath();
                        return new svg.BoundingBox();
                    };
                    this.renderChildren = function(ctx) {
                        this.path(ctx);
                        svg.Mouse.checkPath(this, ctx);
                        if (ctx.fillStyle != "") {
                            if (this.attribute("fill-rule").hasValue()) {
                                ctx.fill(this.attribute("fill-rule").value);
                            } else {
                                ctx.fill();
                            }
                        }
                        if (ctx.strokeStyle != "") ctx.stroke();
                        var markers = this.getMarkers();
                        if (markers != null) {
                            if (this.style("marker-start").isUrlDefinition()) {
                                var marker = this.style("marker-start").getDefinition();
                                marker.render(ctx, markers[0][0], markers[0][1]);
                            }
                            if (this.style("marker-mid").isUrlDefinition()) {
                                var marker = this.style("marker-mid").getDefinition();
                                for (var i = 1; i < markers.length - 1; i++) {
                                    marker.render(ctx, markers[i][0], markers[i][1]);
                                }
                            }
                            if (this.style("marker-end").isUrlDefinition()) {
                                var marker = this.style("marker-end").getDefinition();
                                marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]);
                            }
                        }
                    };
                    this.getBoundingBox = function() {
                        return this.path();
                    };
                    this.getMarkers = function() {
                        return null;
                    };
                };
                svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase();
                // svg element
                svg.Element.svg = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.baseClearContext = this.clearContext;
                    this.clearContext = function(ctx) {
                        this.baseClearContext(ctx);
                        svg.ViewPort.RemoveCurrent();
                    };
                    this.baseSetContext = this.setContext;
                    this.setContext = function(ctx) {
                        // initial values
                        ctx.strokeStyle = "rgba(0,0,0,0)";
                        ctx.lineCap = "butt";
                        ctx.lineJoin = "miter";
                        ctx.miterLimit = 4;
                        this.baseSetContext(ctx);
                        // create new view port
                        if (!this.attribute("x").hasValue()) this.attribute("x", true).value = 0;
                        if (!this.attribute("y").hasValue()) this.attribute("y", true).value = 0;
                        ctx.translate(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"));
                        var width = svg.ViewPort.width();
                        var height = svg.ViewPort.height();
                        if (!this.attribute("width").hasValue()) this.attribute("width", true).value = "100%";
                        if (!this.attribute("height").hasValue()) this.attribute("height", true).value = "100%";
                        if (typeof this.root == "undefined") {
                            width = this.attribute("width").toPixels("x");
                            height = this.attribute("height").toPixels("y");
                            var x = 0;
                            var y = 0;
                            if (this.attribute("refX").hasValue() && this.attribute("refY").hasValue()) {
                                x = -this.attribute("refX").toPixels("x");
                                y = -this.attribute("refY").toPixels("y");
                            }
                            ctx.beginPath();
                            ctx.moveTo(x, y);
                            ctx.lineTo(width, y);
                            ctx.lineTo(width, height);
                            ctx.lineTo(x, height);
                            ctx.closePath();
                            ctx.clip();
                        }
                        svg.ViewPort.SetCurrent(width, height);
                        // viewbox
                        if (this.attribute("viewBox").hasValue()) {
                            var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
                            var minX = viewBox[0];
                            var minY = viewBox[1];
                            width = viewBox[2];
                            height = viewBox[3];
                            svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, svg.ViewPort.width(), width, svg.ViewPort.height(), height, minX, minY, this.attribute("refX").value, this.attribute("refY").value);
                            svg.ViewPort.RemoveCurrent();
                            svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
                        }
                    };
                };
                svg.Element.svg.prototype = new svg.Element.RenderedElementBase();
                // rect element
                svg.Element.rect = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    this.path = function(ctx) {
                        var x = this.attribute("x").toPixels("x");
                        var y = this.attribute("y").toPixels("y");
                        var width = this.attribute("width").toPixels("x");
                        var height = this.attribute("height").toPixels("y");
                        var rx = this.attribute("rx").toPixels("x");
                        var ry = this.attribute("ry").toPixels("y");
                        if (this.attribute("rx").hasValue() && !this.attribute("ry").hasValue()) ry = rx;
                        if (this.attribute("ry").hasValue() && !this.attribute("rx").hasValue()) rx = ry;
                        rx = Math.min(rx, width / 2);
                        ry = Math.min(ry, height / 2);
                        if (ctx != null) {
                            ctx.beginPath();
                            ctx.moveTo(x + rx, y);
                            ctx.lineTo(x + width - rx, y);
                            ctx.quadraticCurveTo(x + width, y, x + width, y + ry);
                            ctx.lineTo(x + width, y + height - ry);
                            ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height);
                            ctx.lineTo(x + rx, y + height);
                            ctx.quadraticCurveTo(x, y + height, x, y + height - ry);
                            ctx.lineTo(x, y + ry);
                            ctx.quadraticCurveTo(x, y, x + rx, y);
                            ctx.closePath();
                        }
                        return new svg.BoundingBox(x, y, x + width, y + height);
                    };
                };
                svg.Element.rect.prototype = new svg.Element.PathElementBase();
                // circle element
                svg.Element.circle = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    this.path = function(ctx) {
                        var cx = this.attribute("cx").toPixels("x");
                        var cy = this.attribute("cy").toPixels("y");
                        var r = this.attribute("r").toPixels();
                        if (ctx != null) {
                            ctx.beginPath();
                            ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
                            ctx.closePath();
                        }
                        return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
                    };
                };
                svg.Element.circle.prototype = new svg.Element.PathElementBase();
                // ellipse element
                svg.Element.ellipse = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    this.path = function(ctx) {
                        var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
                        var rx = this.attribute("rx").toPixels("x");
                        var ry = this.attribute("ry").toPixels("y");
                        var cx = this.attribute("cx").toPixels("x");
                        var cy = this.attribute("cy").toPixels("y");
                        if (ctx != null) {
                            ctx.beginPath();
                            ctx.moveTo(cx, cy - ry);
                            ctx.bezierCurveTo(cx + KAPPA * rx, cy - ry, cx + rx, cy - KAPPA * ry, cx + rx, cy);
                            ctx.bezierCurveTo(cx + rx, cy + KAPPA * ry, cx + KAPPA * rx, cy + ry, cx, cy + ry);
                            ctx.bezierCurveTo(cx - KAPPA * rx, cy + ry, cx - rx, cy + KAPPA * ry, cx - rx, cy);
                            ctx.bezierCurveTo(cx - rx, cy - KAPPA * ry, cx - KAPPA * rx, cy - ry, cx, cy - ry);
                            ctx.closePath();
                        }
                        return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
                    };
                };
                svg.Element.ellipse.prototype = new svg.Element.PathElementBase();
                // line element
                svg.Element.line = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    this.getPoints = function() {
                        return [ new svg.Point(this.attribute("x1").toPixels("x"), this.attribute("y1").toPixels("y")), new svg.Point(this.attribute("x2").toPixels("x"), this.attribute("y2").toPixels("y")) ];
                    };
                    this.path = function(ctx) {
                        var points = this.getPoints();
                        if (ctx != null) {
                            ctx.beginPath();
                            ctx.moveTo(points[0].x, points[0].y);
                            ctx.lineTo(points[1].x, points[1].y);
                        }
                        return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
                    };
                    this.getMarkers = function() {
                        var points = this.getPoints();
                        var a = points[0].angleTo(points[1]);
                        return [ [ points[0], a ], [ points[1], a ] ];
                    };
                };
                svg.Element.line.prototype = new svg.Element.PathElementBase();
                // polyline element
                svg.Element.polyline = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    this.points = svg.CreatePath(this.attribute("points").value);
                    this.path = function(ctx) {
                        var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
                        if (ctx != null) {
                            ctx.beginPath();
                            ctx.moveTo(this.points[0].x, this.points[0].y);
                        }
                        for (var i = 1; i < this.points.length; i++) {
                            bb.addPoint(this.points[i].x, this.points[i].y);
                            if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
                        }
                        return bb;
                    };
                    this.getMarkers = function() {
                        var markers = [];
                        for (var i = 0; i < this.points.length - 1; i++) {
                            markers.push([ this.points[i], this.points[i].angleTo(this.points[i + 1]) ]);
                        }
                        markers.push([ this.points[this.points.length - 1], markers[markers.length - 1][1] ]);
                        return markers;
                    };
                };
                svg.Element.polyline.prototype = new svg.Element.PathElementBase();
                // polygon element
                svg.Element.polygon = function(node) {
                    this.base = svg.Element.polyline;
                    this.base(node);
                    this.basePath = this.path;
                    this.path = function(ctx) {
                        var bb = this.basePath(ctx);
                        if (ctx != null) {
                            ctx.lineTo(this.points[0].x, this.points[0].y);
                            ctx.closePath();
                        }
                        return bb;
                    };
                };
                svg.Element.polygon.prototype = new svg.Element.polyline();
                // path element
                svg.Element.path = function(node) {
                    this.base = svg.Element.PathElementBase;
                    this.base(node);
                    var d = this.attribute("d").value;
                    // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
                    d = d.replace(/,/gm, " ");
                    // get rid of all commas
                    d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
                    // separate commands from commands
                    d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
                    // separate commands from commands
                    d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, "$1 $2");
                    // separate commands from points
                    d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
                    // separate commands from points
                    d = d.replace(/([0-9])([+\-])/gm, "$1 $2");
                    // separate digits when no comma
                    d = d.replace(/(\.[0-9]*)(\.)/gm, "$1 $2");
                    // separate digits when no comma
                    d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, "$1 $3 $4 ");
                    // shorthand elliptical arc path syntax
                    d = svg.compressSpaces(d);
                    // compress multiple spaces
                    d = svg.trim(d);
                    this.PathParser = new function(d) {
                        this.tokens = d.split(" ");
                        this.reset = function() {
                            this.i = -1;
                            this.command = "";
                            this.previousCommand = "";
                            this.start = new svg.Point(0, 0);
                            this.control = new svg.Point(0, 0);
                            this.current = new svg.Point(0, 0);
                            this.points = [];
                            this.angles = [];
                        };
                        this.isEnd = function() {
                            return this.i >= this.tokens.length - 1;
                        };
                        this.isCommandOrEnd = function() {
                            if (this.isEnd()) return true;
                            return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
                        };
                        this.isRelativeCommand = function() {
                            switch (this.command) {
                              case "m":
                              case "l":
                              case "h":
                              case "v":
                              case "c":
                              case "s":
                              case "q":
                              case "t":
                              case "a":
                              case "z":
                                return true;
                                break;
                            }
                            return false;
                        };
                        this.getToken = function() {
                            this.i++;
                            return this.tokens[this.i];
                        };
                        this.getScalar = function() {
                            return parseFloat(this.getToken());
                        };
                        this.nextCommand = function() {
                            this.previousCommand = this.command;
                            this.command = this.getToken();
                        };
                        this.getPoint = function() {
                            var p = new svg.Point(this.getScalar(), this.getScalar());
                            return this.makeAbsolute(p);
                        };
                        this.getAsControlPoint = function() {
                            var p = this.getPoint();
                            this.control = p;
                            return p;
                        };
                        this.getAsCurrentPoint = function() {
                            var p = this.getPoint();
                            this.current = p;
                            return p;
                        };
                        this.getReflectedControlPoint = function() {
                            if (this.previousCommand.toLowerCase() != "c" && this.previousCommand.toLowerCase() != "s" && this.previousCommand.toLowerCase() != "q" && this.previousCommand.toLowerCase() != "t") {
                                return this.current;
                            }
                            // reflect point
                            var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
                            return p;
                        };
                        this.makeAbsolute = function(p) {
                            if (this.isRelativeCommand()) {
                                p.x += this.current.x;
                                p.y += this.current.y;
                            }
                            return p;
                        };
                        this.addMarker = function(p, from, priorTo) {
                            // if the last angle isn't filled in because we didn't have this point yet ...
                            if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
                                this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
                            }
                            this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
                        };
                        this.addMarkerAngle = function(p, a) {
                            this.points.push(p);
                            this.angles.push(a);
                        };
                        this.getMarkerPoints = function() {
                            return this.points;
                        };
                        this.getMarkerAngles = function() {
                            for (var i = 0; i < this.angles.length; i++) {
                                if (this.angles[i] == null) {
                                    for (var j = i + 1; j < this.angles.length; j++) {
                                        if (this.angles[j] != null) {
                                            this.angles[i] = this.angles[j];
                                            break;
                                        }
                                    }
                                }
                            }
                            return this.angles;
                        };
                    }(d);
                    this.path = function(ctx) {
                        var pp = this.PathParser;
                        pp.reset();
                        var bb = new svg.BoundingBox();
                        if (ctx != null) ctx.beginPath();
                        while (!pp.isEnd()) {
                            pp.nextCommand();
                            switch (pp.command) {
                              case "M":
                              case "m":
                                var p = pp.getAsCurrentPoint();
                                pp.addMarker(p);
                                bb.addPoint(p.x, p.y);
                                if (ctx != null) ctx.moveTo(p.x, p.y);
                                pp.start = pp.current;
                                while (!pp.isCommandOrEnd()) {
                                    var p = pp.getAsCurrentPoint();
                                    pp.addMarker(p, pp.start);
                                    bb.addPoint(p.x, p.y);
                                    if (ctx != null) ctx.lineTo(p.x, p.y);
                                }
                                break;

                              case "L":
                              case "l":
                                while (!pp.isCommandOrEnd()) {
                                    var c = pp.current;
                                    var p = pp.getAsCurrentPoint();
                                    pp.addMarker(p, c);
                                    bb.addPoint(p.x, p.y);
                                    if (ctx != null) ctx.lineTo(p.x, p.y);
                                }
                                break;

                              case "H":
                              case "h":
                                while (!pp.isCommandOrEnd()) {
                                    var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
                                    pp.addMarker(newP, pp.current);
                                    pp.current = newP;
                                    bb.addPoint(pp.current.x, pp.current.y);
                                    if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
                                }
                                break;

                              case "V":
                              case "v":
                                while (!pp.isCommandOrEnd()) {
                                    var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
                                    pp.addMarker(newP, pp.current);
                                    pp.current = newP;
                                    bb.addPoint(pp.current.x, pp.current.y);
                                    if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
                                }
                                break;

                              case "C":
                              case "c":
                                while (!pp.isCommandOrEnd()) {
                                    var curr = pp.current;
                                    var p1 = pp.getPoint();
                                    var cntrl = pp.getAsControlPoint();
                                    var cp = pp.getAsCurrentPoint();
                                    pp.addMarker(cp, cntrl, p1);
                                    bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                    if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                }
                                break;

                              case "S":
                              case "s":
                                while (!pp.isCommandOrEnd()) {
                                    var curr = pp.current;
                                    var p1 = pp.getReflectedControlPoint();
                                    var cntrl = pp.getAsControlPoint();
                                    var cp = pp.getAsCurrentPoint();
                                    pp.addMarker(cp, cntrl, p1);
                                    bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                    if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                }
                                break;

                              case "Q":
                              case "q":
                                while (!pp.isCommandOrEnd()) {
                                    var curr = pp.current;
                                    var cntrl = pp.getAsControlPoint();
                                    var cp = pp.getAsCurrentPoint();
                                    pp.addMarker(cp, cntrl, cntrl);
                                    bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                    if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
                                }
                                break;

                              case "T":
                              case "t":
                                while (!pp.isCommandOrEnd()) {
                                    var curr = pp.current;
                                    var cntrl = pp.getReflectedControlPoint();
                                    pp.control = cntrl;
                                    var cp = pp.getAsCurrentPoint();
                                    pp.addMarker(cp, cntrl, cntrl);
                                    bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
                                    if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
                                }
                                break;

                              case "A":
                              case "a":
                                while (!pp.isCommandOrEnd()) {
                                    var curr = pp.current;
                                    var rx = pp.getScalar();
                                    var ry = pp.getScalar();
                                    var xAxisRotation = pp.getScalar() * (Math.PI / 180);
                                    var largeArcFlag = pp.getScalar();
                                    var sweepFlag = pp.getScalar();
                                    var cp = pp.getAsCurrentPoint();
                                    // Conversion from endpoint to center parameterization
                                    // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
                                    // x1', y1'
                                    var currp = new svg.Point(Math.cos(xAxisRotation) * (curr.x - cp.x) / 2 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2, -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2);
                                    // adjust radii
                                    var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2);
                                    if (l > 1) {
                                        rx *= Math.sqrt(l);
                                        ry *= Math.sqrt(l);
                                    }
                                    // cx', cy'
                                    var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt((Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(currp.y, 2) - Math.pow(ry, 2) * Math.pow(currp.x, 2)) / (Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2)));
                                    if (isNaN(s)) s = 0;
                                    var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
                                    // cx, cy
                                    var centp = new svg.Point((curr.x + cp.x) / 2 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, (curr.y + cp.y) / 2 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y);
                                    // vector magnitude
                                    var m = function(v) {
                                        return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2));
                                    };
                                    // ratio between two vectors
                                    var r = function(u, v) {
                                        return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v));
                                    };
                                    // angle between two vectors
                                    var a = function(u, v) {
                                        return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v));
                                    };
                                    // initial angle
                                    var a1 = a([ 1, 0 ], [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ]);
                                    // angle delta
                                    var u = [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ];
                                    var v = [ (-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry ];
                                    var ad = a(u, v);
                                    if (r(u, v) <= -1) ad = Math.PI;
                                    if (r(u, v) >= 1) ad = 0;
                                    // for markers
                                    var dir = 1 - sweepFlag ? 1 : -1;
                                    var ah = a1 + dir * (ad / 2);
                                    var halfWay = new svg.Point(centp.x + rx * Math.cos(ah), centp.y + ry * Math.sin(ah));
                                    pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
                                    pp.addMarkerAngle(cp, ah - dir * Math.PI);
                                    bb.addPoint(cp.x, cp.y);
                                    // TODO: this is too naive, make it better
                                    if (ctx != null) {
                                        var r = rx > ry ? rx : ry;
                                        var sx = rx > ry ? 1 : rx / ry;
                                        var sy = rx > ry ? ry / rx : 1;
                                        ctx.translate(centp.x, centp.y);
                                        ctx.rotate(xAxisRotation);
                                        ctx.scale(sx, sy);
                                        ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
                                        ctx.scale(1 / sx, 1 / sy);
                                        ctx.rotate(-xAxisRotation);
                                        ctx.translate(-centp.x, -centp.y);
                                    }
                                }
                                break;

                              case "Z":
                              case "z":
                                if (ctx != null) ctx.closePath();
                                pp.current = pp.start;
                            }
                        }
                        return bb;
                    };
                    this.getMarkers = function() {
                        var points = this.PathParser.getMarkerPoints();
                        var angles = this.PathParser.getMarkerAngles();
                        var markers = [];
                        for (var i = 0; i < points.length; i++) {
                            markers.push([ points[i], angles[i] ]);
                        }
                        return markers;
                    };
                };
                svg.Element.path.prototype = new svg.Element.PathElementBase();
                // pattern element
                svg.Element.pattern = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.createPattern = function(ctx, element) {
                        var width = this.attribute("width").toPixels("x", true);
                        var height = this.attribute("height").toPixels("y", true);
                        // render me using a temporary svg element
                        var tempSvg = new svg.Element.svg();
                        tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
                        tempSvg.attributes["width"] = new svg.Property("width", width + "px");
                        tempSvg.attributes["height"] = new svg.Property("height", height + "px");
                        tempSvg.attributes["transform"] = new svg.Property("transform", this.attribute("patternTransform").value);
                        tempSvg.children = this.children;
                        var c = document.createElement("canvas");
                        c.width = width;
                        c.height = height;
                        var cctx = c.getContext("2d");
                        if (this.attribute("x").hasValue() && this.attribute("y").hasValue()) {
                            cctx.translate(this.attribute("x").toPixels("x", true), this.attribute("y").toPixels("y", true));
                        }
                        // render 3x3 grid so when we transform there's no white space on edges
                        for (var x = -1; x <= 1; x++) {
                            for (var y = -1; y <= 1; y++) {
                                cctx.save();
                                cctx.translate(x * c.width, y * c.height);
                                tempSvg.render(cctx);
                                cctx.restore();
                            }
                        }
                        var pattern = ctx.createPattern(c, "repeat");
                        return pattern;
                    };
                };
                svg.Element.pattern.prototype = new svg.Element.ElementBase();
                // marker element
                svg.Element.marker = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.baseRender = this.render;
                    this.render = function(ctx, point, angle) {
                        ctx.translate(point.x, point.y);
                        if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(angle);
                        if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(ctx.lineWidth, ctx.lineWidth);
                        ctx.save();
                        // render me using a temporary svg element
                        var tempSvg = new svg.Element.svg();
                        tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
                        tempSvg.attributes["refX"] = new svg.Property("refX", this.attribute("refX").value);
                        tempSvg.attributes["refY"] = new svg.Property("refY", this.attribute("refY").value);
                        tempSvg.attributes["width"] = new svg.Property("width", this.attribute("markerWidth").value);
                        tempSvg.attributes["height"] = new svg.Property("height", this.attribute("markerHeight").value);
                        tempSvg.attributes["fill"] = new svg.Property("fill", this.attribute("fill").valueOrDefault("black"));
                        tempSvg.attributes["stroke"] = new svg.Property("stroke", this.attribute("stroke").valueOrDefault("none"));
                        tempSvg.children = this.children;
                        tempSvg.render(ctx);
                        ctx.restore();
                        if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth);
                        if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(-angle);
                        ctx.translate(-point.x, -point.y);
                    };
                };
                svg.Element.marker.prototype = new svg.Element.ElementBase();
                // definitions element
                svg.Element.defs = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.render = function(ctx) {};
                };
                svg.Element.defs.prototype = new svg.Element.ElementBase();
                // base for gradients
                svg.Element.GradientBase = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.gradientUnits = this.attribute("gradientUnits").valueOrDefault("objectBoundingBox");
                    this.stops = [];
                    for (var i = 0; i < this.children.length; i++) {
                        var child = this.children[i];
                        if (child.type == "stop") this.stops.push(child);
                    }
                    this.getGradient = function() {};
                    this.createGradient = function(ctx, element, parentOpacityProp) {
                        var stopsContainer = this;
                        if (this.getHrefAttribute().hasValue()) {
                            stopsContainer = this.getHrefAttribute().getDefinition();
                        }
                        var addParentOpacity = function(color) {
                            if (parentOpacityProp.hasValue()) {
                                var p = new svg.Property("color", color);
                                return p.addOpacity(parentOpacityProp.value).value;
                            }
                            return color;
                        };
                        var g = this.getGradient(ctx, element);
                        if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
                        for (var i = 0; i < stopsContainer.stops.length; i++) {
                            g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
                        }
                        if (this.attribute("gradientTransform").hasValue()) {
                            // render as transformed pattern on temporary canvas
                            var rootView = svg.ViewPort.viewPorts[0];
                            var rect = new svg.Element.rect();
                            rect.attributes["x"] = new svg.Property("x", -svg.MAX_VIRTUAL_PIXELS / 3);
                            rect.attributes["y"] = new svg.Property("y", -svg.MAX_VIRTUAL_PIXELS / 3);
                            rect.attributes["width"] = new svg.Property("width", svg.MAX_VIRTUAL_PIXELS);
                            rect.attributes["height"] = new svg.Property("height", svg.MAX_VIRTUAL_PIXELS);
                            var group = new svg.Element.g();
                            group.attributes["transform"] = new svg.Property("transform", this.attribute("gradientTransform").value);
                            group.children = [ rect ];
                            var tempSvg = new svg.Element.svg();
                            tempSvg.attributes["x"] = new svg.Property("x", 0);
                            tempSvg.attributes["y"] = new svg.Property("y", 0);
                            tempSvg.attributes["width"] = new svg.Property("width", rootView.width);
                            tempSvg.attributes["height"] = new svg.Property("height", rootView.height);
                            tempSvg.children = [ group ];
                            var c = document.createElement("canvas");
                            c.width = rootView.width;
                            c.height = rootView.height;
                            var tempCtx = c.getContext("2d");
                            tempCtx.fillStyle = g;
                            tempSvg.render(tempCtx);
                            return tempCtx.createPattern(c, "no-repeat");
                        }
                        return g;
                    };
                };
                svg.Element.GradientBase.prototype = new svg.Element.ElementBase();
                // linear gradient element
                svg.Element.linearGradient = function(node) {
                    this.base = svg.Element.GradientBase;
                    this.base(node);
                    this.getGradient = function(ctx, element) {
                        var bb = element.getBoundingBox();
                        if (!this.attribute("x1").hasValue() && !this.attribute("y1").hasValue() && !this.attribute("x2").hasValue() && !this.attribute("y2").hasValue()) {
                            this.attribute("x1", true).value = 0;
                            this.attribute("y1", true).value = 0;
                            this.attribute("x2", true).value = 1;
                            this.attribute("y2", true).value = 0;
                        }
                        var x1 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x1").numValue() : this.attribute("x1").toPixels("x");
                        var y1 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y1").numValue() : this.attribute("y1").toPixels("y");
                        var x2 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x2").numValue() : this.attribute("x2").toPixels("x");
                        var y2 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y2").numValue() : this.attribute("y2").toPixels("y");
                        if (x1 == x2 && y1 == y2) return null;
                        return ctx.createLinearGradient(x1, y1, x2, y2);
                    };
                };
                svg.Element.linearGradient.prototype = new svg.Element.GradientBase();
                // radial gradient element
                svg.Element.radialGradient = function(node) {
                    this.base = svg.Element.GradientBase;
                    this.base(node);
                    this.getGradient = function(ctx, element) {
                        var bb = element.getBoundingBox();
                        if (!this.attribute("cx").hasValue()) this.attribute("cx", true).value = "50%";
                        if (!this.attribute("cy").hasValue()) this.attribute("cy", true).value = "50%";
                        if (!this.attribute("r").hasValue()) this.attribute("r", true).value = "50%";
                        var cx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("cx").numValue() : this.attribute("cx").toPixels("x");
                        var cy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("cy").numValue() : this.attribute("cy").toPixels("y");
                        var fx = cx;
                        var fy = cy;
                        if (this.attribute("fx").hasValue()) {
                            fx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("fx").numValue() : this.attribute("fx").toPixels("x");
                        }
                        if (this.attribute("fy").hasValue()) {
                            fy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("fy").numValue() : this.attribute("fy").toPixels("y");
                        }
                        var r = this.gradientUnits == "objectBoundingBox" ? (bb.width() + bb.height()) / 2 * this.attribute("r").numValue() : this.attribute("r").toPixels();
                        return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
                    };
                };
                svg.Element.radialGradient.prototype = new svg.Element.GradientBase();
                // gradient stop element
                svg.Element.stop = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.offset = this.attribute("offset").numValue();
                    if (this.offset < 0) this.offset = 0;
                    if (this.offset > 1) this.offset = 1;
                    var stopColor = this.style("stop-color");
                    if (this.style("stop-opacity").hasValue()) stopColor = stopColor.addOpacity(this.style("stop-opacity").value);
                    this.color = stopColor.value;
                };
                svg.Element.stop.prototype = new svg.Element.ElementBase();
                // animation base element
                svg.Element.AnimateBase = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    svg.Animations.push(this);
                    this.duration = 0;
                    this.begin = this.attribute("begin").toMilliseconds();
                    this.maxDuration = this.begin + this.attribute("dur").toMilliseconds();
                    this.getProperty = function() {
                        var attributeType = this.attribute("attributeType").value;
                        var attributeName = this.attribute("attributeName").value;
                        if (attributeType == "CSS") {
                            return this.parent.style(attributeName, true);
                        }
                        return this.parent.attribute(attributeName, true);
                    };
                    this.initialValue = null;
                    this.initialUnits = "";
                    this.removed = false;
                    this.calcValue = function() {
                        // OVERRIDE ME!
                        return "";
                    };
                    this.update = function(delta) {
                        // set initial value
                        if (this.initialValue == null) {
                            this.initialValue = this.getProperty().value;
                            this.initialUnits = this.getProperty().getUnits();
                        }
                        // if we're past the end time
                        if (this.duration > this.maxDuration) {
                            // loop for indefinitely repeating animations
                            if (this.attribute("repeatCount").value == "indefinite" || this.attribute("repeatDur").value == "indefinite") {
                                this.duration = 0;
                            } else if (this.attribute("fill").valueOrDefault("remove") == "remove" && !this.removed) {
                                this.removed = true;
                                this.getProperty().value = this.initialValue;
                                return true;
                            } else {
                                return false;
                            }
                        }
                        this.duration = this.duration + delta;
                        // if we're past the begin time
                        var updated = false;
                        if (this.begin < this.duration) {
                            var newValue = this.calcValue();
                            // tween
                            if (this.attribute("type").hasValue()) {
                                // for transform, etc.
                                var type = this.attribute("type").value;
                                newValue = type + "(" + newValue + ")";
                            }
                            this.getProperty().value = newValue;
                            updated = true;
                        }
                        return updated;
                    };
                    this.from = this.attribute("from");
                    this.to = this.attribute("to");
                    this.values = this.attribute("values");
                    if (this.values.hasValue()) this.values.value = this.values.value.split(";");
                    // fraction of duration we've covered
                    this.progress = function() {
                        var ret = {
                            progress: (this.duration - this.begin) / (this.maxDuration - this.begin)
                        };
                        if (this.values.hasValue()) {
                            var p = ret.progress * (this.values.value.length - 1);
                            var lb = Math.floor(p), ub = Math.ceil(p);
                            ret.from = new svg.Property("from", parseFloat(this.values.value[lb]));
                            ret.to = new svg.Property("to", parseFloat(this.values.value[ub]));
                            ret.progress = (p - lb) / (ub - lb);
                        } else {
                            ret.from = this.from;
                            ret.to = this.to;
                        }
                        return ret;
                    };
                };
                svg.Element.AnimateBase.prototype = new svg.Element.ElementBase();
                // animate element
                svg.Element.animate = function(node) {
                    this.base = svg.Element.AnimateBase;
                    this.base(node);
                    this.calcValue = function() {
                        var p = this.progress();
                        // tween value linearly
                        var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
                        return newValue + this.initialUnits;
                    };
                };
                svg.Element.animate.prototype = new svg.Element.AnimateBase();
                // animate color element
                svg.Element.animateColor = function(node) {
                    this.base = svg.Element.AnimateBase;
                    this.base(node);
                    this.calcValue = function() {
                        var p = this.progress();
                        var from = new RGBColor(p.from.value);
                        var to = new RGBColor(p.to.value);
                        if (from.ok && to.ok) {
                            // tween color linearly
                            var r = from.r + (to.r - from.r) * p.progress;
                            var g = from.g + (to.g - from.g) * p.progress;
                            var b = from.b + (to.b - from.b) * p.progress;
                            return "rgb(" + parseInt(r, 10) + "," + parseInt(g, 10) + "," + parseInt(b, 10) + ")";
                        }
                        return this.attribute("from").value;
                    };
                };
                svg.Element.animateColor.prototype = new svg.Element.AnimateBase();
                // animate transform element
                svg.Element.animateTransform = function(node) {
                    this.base = svg.Element.AnimateBase;
                    this.base(node);
                    this.calcValue = function() {
                        var p = this.progress();
                        // tween value linearly
                        var from = svg.ToNumberArray(p.from.value);
                        var to = svg.ToNumberArray(p.to.value);
                        var newValue = "";
                        for (var i = 0; i < from.length; i++) {
                            newValue += from[i] + (to[i] - from[i]) * p.progress + " ";
                        }
                        return newValue;
                    };
                };
                svg.Element.animateTransform.prototype = new svg.Element.animate();
                // font element
                svg.Element.font = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.horizAdvX = this.attribute("horiz-adv-x").numValue();
                    this.isRTL = false;
                    this.isArabic = false;
                    this.fontFace = null;
                    this.missingGlyph = null;
                    this.glyphs = [];
                    for (var i = 0; i < this.children.length; i++) {
                        var child = this.children[i];
                        if (child.type == "font-face") {
                            this.fontFace = child;
                            if (child.style("font-family").hasValue()) {
                                svg.Definitions[child.style("font-family").value] = this;
                            }
                        } else if (child.type == "missing-glyph") this.missingGlyph = child; else if (child.type == "glyph") {
                            if (child.arabicForm != "") {
                                this.isRTL = true;
                                this.isArabic = true;
                                if (typeof this.glyphs[child.unicode] == "undefined") this.glyphs[child.unicode] = [];
                                this.glyphs[child.unicode][child.arabicForm] = child;
                            } else {
                                this.glyphs[child.unicode] = child;
                            }
                        }
                    }
                };
                svg.Element.font.prototype = new svg.Element.ElementBase();
                // font-face element
                svg.Element.fontface = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.ascent = this.attribute("ascent").value;
                    this.descent = this.attribute("descent").value;
                    this.unitsPerEm = this.attribute("units-per-em").numValue();
                };
                svg.Element.fontface.prototype = new svg.Element.ElementBase();
                // missing-glyph element
                svg.Element.missingglyph = function(node) {
                    this.base = svg.Element.path;
                    this.base(node);
                    this.horizAdvX = 0;
                };
                svg.Element.missingglyph.prototype = new svg.Element.path();
                // glyph element
                svg.Element.glyph = function(node) {
                    this.base = svg.Element.path;
                    this.base(node);
                    this.horizAdvX = this.attribute("horiz-adv-x").numValue();
                    this.unicode = this.attribute("unicode").value;
                    this.arabicForm = this.attribute("arabic-form").value;
                };
                svg.Element.glyph.prototype = new svg.Element.path();
                // text element
                svg.Element.text = function(node) {
                    this.captureTextNodes = true;
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.baseSetContext = this.setContext;
                    this.setContext = function(ctx) {
                        this.baseSetContext(ctx);
                        if (this.style("dominant-baseline").hasValue()) ctx.textBaseline = this.style("dominant-baseline").value;
                        if (this.style("alignment-baseline").hasValue()) ctx.textBaseline = this.style("alignment-baseline").value;
                    };
                    this.getBoundingBox = function() {
                        // TODO: implement
                        return new svg.BoundingBox(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"), 0, 0);
                    };
                    this.renderChildren = function(ctx) {
                        this.x = this.attribute("x").toPixels("x");
                        this.y = this.attribute("y").toPixels("y");
                        this.x += this.getAnchorDelta(ctx, this, 0);
                        for (var i = 0; i < this.children.length; i++) {
                            this.renderChild(ctx, this, i);
                        }
                    };
                    this.getAnchorDelta = function(ctx, parent, startI) {
                        var textAnchor = this.style("text-anchor").valueOrDefault("start");
                        if (textAnchor != "start") {
                            var width = 0;
                            for (var i = startI; i < parent.children.length; i++) {
                                var child = parent.children[i];
                                if (i > startI && child.attribute("x").hasValue()) break;
                                // new group
                                width += child.measureTextRecursive(ctx);
                            }
                            return -1 * (textAnchor == "end" ? width : width / 2);
                        }
                        return 0;
                    };
                    this.renderChild = function(ctx, parent, i) {
                        var child = parent.children[i];
                        if (child.attribute("x").hasValue()) {
                            child.x = child.attribute("x").toPixels("x") + this.getAnchorDelta(ctx, parent, i);
                        } else {
                            if (this.attribute("dx").hasValue()) this.x += this.attribute("dx").toPixels("x");
                            if (child.attribute("dx").hasValue()) this.x += child.attribute("dx").toPixels("x");
                            child.x = this.x;
                        }
                        this.x = child.x + child.measureText(ctx);
                        if (child.attribute("y").hasValue()) {
                            child.y = child.attribute("y").toPixels("y");
                        } else {
                            if (this.attribute("dy").hasValue()) this.y += this.attribute("dy").toPixels("y");
                            if (child.attribute("dy").hasValue()) this.y += child.attribute("dy").toPixels("y");
                            child.y = this.y;
                        }
                        this.y = child.y;
                        child.render(ctx);
                        for (var i = 0; i < child.children.length; i++) {
                            this.renderChild(ctx, child, i);
                        }
                    };
                };
                svg.Element.text.prototype = new svg.Element.RenderedElementBase();
                // text base
                svg.Element.TextElementBase = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.getGlyph = function(font, text, i) {
                        var c = text[i];
                        var glyph = null;
                        if (font.isArabic) {
                            var arabicForm = "isolated";
                            if ((i == 0 || text[i - 1] == " ") && i < text.length - 2 && text[i + 1] != " ") arabicForm = "terminal";
                            if (i > 0 && text[i - 1] != " " && i < text.length - 2 && text[i + 1] != " ") arabicForm = "medial";
                            if (i > 0 && text[i - 1] != " " && (i == text.length - 1 || text[i + 1] == " ")) arabicForm = "initial";
                            if (typeof font.glyphs[c] != "undefined") {
                                glyph = font.glyphs[c][arabicForm];
                                if (glyph == null && font.glyphs[c].type == "glyph") glyph = font.glyphs[c];
                            }
                        } else {
                            glyph = font.glyphs[c];
                        }
                        if (glyph == null) glyph = font.missingGlyph;
                        return glyph;
                    };
                    this.renderChildren = function(ctx) {
                        var customFont = this.parent.style("font-family").getDefinition();
                        if (customFont != null) {
                            var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
                            var fontStyle = this.parent.style("font-style").valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
                            var text = this.getText();
                            if (customFont.isRTL) text = text.split("").reverse().join("");
                            var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
                            for (var i = 0; i < text.length; i++) {
                                var glyph = this.getGlyph(customFont, text, i);
                                var scale = fontSize / customFont.fontFace.unitsPerEm;
                                ctx.translate(this.x, this.y);
                                ctx.scale(scale, -scale);
                                var lw = ctx.lineWidth;
                                ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
                                if (fontStyle == "italic") ctx.transform(1, 0, .4, 1, 0, 0);
                                glyph.render(ctx);
                                if (fontStyle == "italic") ctx.transform(1, 0, -.4, 1, 0, 0);
                                ctx.lineWidth = lw;
                                ctx.scale(1 / scale, -1 / scale);
                                ctx.translate(-this.x, -this.y);
                                this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
                                if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
                                    this.x += dx[i];
                                }
                            }
                            return;
                        }
                        if (ctx.fillStyle != "") ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
                        if (ctx.strokeStyle != "") ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
                    };
                    this.getText = function() {};
                    this.measureTextRecursive = function(ctx) {
                        var width = this.measureText(ctx);
                        for (var i = 0; i < this.children.length; i++) {
                            width += this.children[i].measureTextRecursive(ctx);
                        }
                        return width;
                    };
                    this.measureText = function(ctx) {
                        var customFont = this.parent.style("font-family").getDefinition();
                        if (customFont != null) {
                            var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
                            var measure = 0;
                            var text = this.getText();
                            if (customFont.isRTL) text = text.split("").reverse().join("");
                            var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
                            for (var i = 0; i < text.length; i++) {
                                var glyph = this.getGlyph(customFont, text, i);
                                measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
                                if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
                                    measure += dx[i];
                                }
                            }
                            return measure;
                        }
                        var textToMeasure = svg.compressSpaces(this.getText());
                        if (!ctx.measureText) return textToMeasure.length * 10;
                        ctx.save();
                        this.setContext(ctx);
                        var width = ctx.measureText(textToMeasure).width;
                        ctx.restore();
                        return width;
                    };
                };
                svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase();
                // tspan 
                svg.Element.tspan = function(node) {
                    this.captureTextNodes = true;
                    this.base = svg.Element.TextElementBase;
                    this.base(node);
                    this.text = node.nodeValue || node.text || "";
                    this.getText = function() {
                        return this.text;
                    };
                };
                svg.Element.tspan.prototype = new svg.Element.TextElementBase();
                // tref
                svg.Element.tref = function(node) {
                    this.base = svg.Element.TextElementBase;
                    this.base(node);
                    this.getText = function() {
                        var element = this.getHrefAttribute().getDefinition();
                        if (element != null) return element.children[0].getText();
                    };
                };
                svg.Element.tref.prototype = new svg.Element.TextElementBase();
                // a element
                svg.Element.a = function(node) {
                    this.base = svg.Element.TextElementBase;
                    this.base(node);
                    this.hasText = true;
                    for (var i = 0; i < node.childNodes.length; i++) {
                        if (node.childNodes[i].nodeType != 3) this.hasText = false;
                    }
                    // this might contain text
                    this.text = this.hasText ? node.childNodes[0].nodeValue : "";
                    this.getText = function() {
                        return this.text;
                    };
                    this.baseRenderChildren = this.renderChildren;
                    this.renderChildren = function(ctx) {
                        if (this.hasText) {
                            // render as text element
                            this.baseRenderChildren(ctx);
                            var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
                            svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels("y"), this.x + this.measureText(ctx), this.y));
                        } else {
                            // render as temporary group
                            var g = new svg.Element.g();
                            g.children = this.children;
                            g.parent = this;
                            g.render(ctx);
                        }
                    };
                    this.onclick = function() {
                        window.open(this.getHrefAttribute().value);
                    };
                    this.onmousemove = function() {
                        svg.ctx.canvas.style.cursor = "pointer";
                    };
                };
                svg.Element.a.prototype = new svg.Element.TextElementBase();
                // image element
                svg.Element.image = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    var href = this.getHrefAttribute().value;
                    var isSvg = href.match(/\.svg$/);
                    svg.Images.push(this);
                    this.loaded = false;
                    if (!isSvg) {
                        this.img = document.createElement("img");
                        var self = this;
                        this.img.onload = function() {
                            self.loaded = true;
                        };
                        this.img.onerror = function() {
                            if (typeof console != "undefined") {
                                console.log('ERROR: image "' + href + '" not found');
                                self.loaded = true;
                            }
                        };
                        this.img.src = href;
                    } else {
                        this.img = svg.ajax(href);
                        this.loaded = true;
                    }
                    this.renderChildren = function(ctx) {
                        var x = this.attribute("x").toPixels("x");
                        var y = this.attribute("y").toPixels("y");
                        var width = this.attribute("width").toPixels("x");
                        var height = this.attribute("height").toPixels("y");
                        if (width == 0 || height == 0) return;
                        ctx.save();
                        if (isSvg) {
                            ctx.drawSvg(this.img, x, y, width, height);
                        } else {
                            ctx.translate(x, y);
                            svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, width, this.img.width, height, this.img.height, 0, 0);
                            ctx.drawImage(this.img, 0, 0);
                        }
                        ctx.restore();
                    };
                    this.getBoundingBox = function() {
                        var x = this.attribute("x").toPixels("x");
                        var y = this.attribute("y").toPixels("y");
                        var width = this.attribute("width").toPixels("x");
                        var height = this.attribute("height").toPixels("y");
                        return new svg.BoundingBox(x, y, x + width, y + height);
                    };
                };
                svg.Element.image.prototype = new svg.Element.RenderedElementBase();
                // group element
                svg.Element.g = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.getBoundingBox = function() {
                        var bb = new svg.BoundingBox();
                        for (var i = 0; i < this.children.length; i++) {
                            bb.addBoundingBox(this.children[i].getBoundingBox());
                        }
                        return bb;
                    };
                };
                svg.Element.g.prototype = new svg.Element.RenderedElementBase();
                // symbol element
                svg.Element.symbol = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.baseSetContext = this.setContext;
                    this.setContext = function(ctx) {
                        this.baseSetContext(ctx);
                        // viewbox
                        if (this.attribute("viewBox").hasValue()) {
                            var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
                            var minX = viewBox[0];
                            var minY = viewBox[1];
                            width = viewBox[2];
                            height = viewBox[3];
                            svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, this.attribute("width").toPixels("x"), width, this.attribute("height").toPixels("y"), height, minX, minY);
                            svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
                        }
                    };
                };
                svg.Element.symbol.prototype = new svg.Element.RenderedElementBase();
                // style element
                svg.Element.style = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    // text, or spaces then CDATA
                    var css = "";
                    for (var i = 0; i < node.childNodes.length; i++) {
                        css += node.childNodes[i].nodeValue;
                    }
                    css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, "");
                    // remove comments
                    css = svg.compressSpaces(css);
                    // replace whitespace
                    var cssDefs = css.split("}");
                    for (var i = 0; i < cssDefs.length; i++) {
                        if (svg.trim(cssDefs[i]) != "") {
                            var cssDef = cssDefs[i].split("{");
                            var cssClasses = cssDef[0].split(",");
                            var cssProps = cssDef[1].split(";");
                            for (var j = 0; j < cssClasses.length; j++) {
                                var cssClass = svg.trim(cssClasses[j]);
                                if (cssClass != "") {
                                    var props = {};
                                    for (var k = 0; k < cssProps.length; k++) {
                                        var prop = cssProps[k].indexOf(":");
                                        var name = cssProps[k].substr(0, prop);
                                        var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
                                        if (name != null && value != null) {
                                            props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
                                        }
                                    }
                                    svg.Styles[cssClass] = props;
                                    if (cssClass == "@font-face") {
                                        var fontFamily = props["font-family"].value.replace(/"/g, "");
                                        var srcs = props["src"].value.split(",");
                                        for (var s = 0; s < srcs.length; s++) {
                                            if (srcs[s].indexOf('format("svg")') > 0) {
                                                var urlStart = srcs[s].indexOf("url");
                                                var urlEnd = srcs[s].indexOf(")", urlStart);
                                                var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
                                                var doc = svg.parseXml(svg.ajax(url));
                                                var fonts = doc.getElementsByTagName("font");
                                                for (var f = 0; f < fonts.length; f++) {
                                                    var font = svg.CreateElement(fonts[f]);
                                                    svg.Definitions[fontFamily] = font;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                };
                svg.Element.style.prototype = new svg.Element.ElementBase();
                // use element 
                svg.Element.use = function(node) {
                    this.base = svg.Element.RenderedElementBase;
                    this.base(node);
                    this.baseSetContext = this.setContext;
                    this.setContext = function(ctx) {
                        this.baseSetContext(ctx);
                        if (this.attribute("x").hasValue()) ctx.translate(this.attribute("x").toPixels("x"), 0);
                        if (this.attribute("y").hasValue()) ctx.translate(0, this.attribute("y").toPixels("y"));
                    };
                    this.getDefinition = function() {
                        var element = this.getHrefAttribute().getDefinition();
                        if (this.attribute("width").hasValue()) element.attribute("width", true).value = this.attribute("width").value;
                        if (this.attribute("height").hasValue()) element.attribute("height", true).value = this.attribute("height").value;
                        return element;
                    };
                    this.path = function(ctx) {
                        var element = this.getDefinition();
                        if (element != null) element.path(ctx);
                    };
                    this.getBoundingBox = function() {
                        var element = this.getDefinition();
                        if (element != null) return element.getBoundingBox();
                    };
                    this.renderChildren = function(ctx) {
                        var element = this.getDefinition();
                        if (element != null) {
                            // temporarily detach from parent and render
                            var oldParent = element.parent;
                            element.parent = null;
                            element.render(ctx);
                            element.parent = oldParent;
                        }
                    };
                };
                svg.Element.use.prototype = new svg.Element.RenderedElementBase();
                // mask element
                svg.Element.mask = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.apply = function(ctx, element) {
                        // render as temp svg	
                        var x = this.attribute("x").toPixels("x");
                        var y = this.attribute("y").toPixels("y");
                        var width = this.attribute("width").toPixels("x");
                        var height = this.attribute("height").toPixels("y");
                        if (width == 0 && height == 0) {
                            var bb = new svg.BoundingBox();
                            for (var i = 0; i < this.children.length; i++) {
                                bb.addBoundingBox(this.children[i].getBoundingBox());
                            }
                            var x = Math.floor(bb.x1);
                            var y = Math.floor(bb.y1);
                            var width = Math.floor(bb.width());
                            var height = Math.floor(bb.height());
                        }
                        // temporarily remove mask to avoid recursion
                        var mask = element.attribute("mask").value;
                        element.attribute("mask").value = "";
                        var cMask = document.createElement("canvas");
                        cMask.width = x + width;
                        cMask.height = y + height;
                        var maskCtx = cMask.getContext("2d");
                        this.renderChildren(maskCtx);
                        var c = document.createElement("canvas");
                        c.width = x + width;
                        c.height = y + height;
                        var tempCtx = c.getContext("2d");
                        element.render(tempCtx);
                        tempCtx.globalCompositeOperation = "destination-in";
                        tempCtx.fillStyle = maskCtx.createPattern(cMask, "no-repeat");
                        tempCtx.fillRect(0, 0, x + width, y + height);
                        ctx.fillStyle = tempCtx.createPattern(c, "no-repeat");
                        ctx.fillRect(0, 0, x + width, y + height);
                        // reassign mask
                        element.attribute("mask").value = mask;
                    };
                    this.render = function(ctx) {};
                };
                svg.Element.mask.prototype = new svg.Element.ElementBase();
                // clip element
                svg.Element.clipPath = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.apply = function(ctx) {
                        for (var i = 0; i < this.children.length; i++) {
                            var child = this.children[i];
                            if (typeof child.path != "undefined") {
                                var transform = null;
                                if (child.attribute("transform").hasValue()) {
                                    transform = new svg.Transform(child.attribute("transform").value);
                                    transform.apply(ctx);
                                }
                                child.path(ctx);
                                ctx.clip();
                                if (transform) {
                                    transform.unapply(ctx);
                                }
                            }
                        }
                    };
                    this.render = function(ctx) {};
                };
                svg.Element.clipPath.prototype = new svg.Element.ElementBase();
                // filters
                svg.Element.filter = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.apply = function(ctx, element) {
                        // render as temp svg	
                        var bb = element.getBoundingBox();
                        var x = Math.floor(bb.x1);
                        var y = Math.floor(bb.y1);
                        var width = Math.floor(bb.width());
                        var height = Math.floor(bb.height());
                        // temporarily remove filter to avoid recursion
                        var filter = element.style("filter").value;
                        element.style("filter").value = "";
                        var px = 0, py = 0;
                        for (var i = 0; i < this.children.length; i++) {
                            var efd = this.children[i].extraFilterDistance || 0;
                            px = Math.max(px, efd);
                            py = Math.max(py, efd);
                        }
                        var c = document.createElement("canvas");
                        c.width = width + 2 * px;
                        c.height = height + 2 * py;
                        var tempCtx = c.getContext("2d");
                        tempCtx.translate(-x + px, -y + py);
                        element.render(tempCtx);
                        // apply filters
                        for (var i = 0; i < this.children.length; i++) {
                            this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py);
                        }
                        // render on me
                        ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py);
                        // reassign filter
                        element.style("filter", true).value = filter;
                    };
                    this.render = function(ctx) {};
                };
                svg.Element.filter.prototype = new svg.Element.ElementBase();
                svg.Element.feMorphology = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.apply = function(ctx, x, y, width, height) {};
                };
                svg.Element.feMorphology.prototype = new svg.Element.ElementBase();
                svg.Element.feColorMatrix = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    function imGet(img, x, y, width, height, rgba) {
                        return img[y * width * 4 + x * 4 + rgba];
                    }
                    function imSet(img, x, y, width, height, rgba, val) {
                        img[y * width * 4 + x * 4 + rgba] = val;
                    }
                    this.apply = function(ctx, x, y, width, height) {
                        // only supporting grayscale for now per Issue 195, need to extend to all matrix
                        // assuming x==0 && y==0 for now
                        var srcData = ctx.getImageData(0, 0, width, height);
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = imGet(srcData.data, x, y, width, height, 0);
                                var g = imGet(srcData.data, x, y, width, height, 1);
                                var b = imGet(srcData.data, x, y, width, height, 2);
                                var gray = (r + g + b) / 3;
                                imSet(srcData.data, x, y, width, height, 0, gray);
                                imSet(srcData.data, x, y, width, height, 1, gray);
                                imSet(srcData.data, x, y, width, height, 2, gray);
                            }
                        }
                        ctx.clearRect(0, 0, width, height);
                        ctx.putImageData(srcData, 0, 0);
                    };
                };
                svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase();
                svg.Element.feGaussianBlur = function(node) {
                    this.base = svg.Element.ElementBase;
                    this.base(node);
                    this.blurRadius = Math.floor(this.attribute("stdDeviation").numValue());
                    this.extraFilterDistance = this.blurRadius;
                    this.apply = function(ctx, x, y, width, height) {
                        if (typeof stackBlurCanvasRGBA == "undefined") {
                            if (typeof console != "undefined") {
                                console.log("ERROR: StackBlur.js must be included for blur to work");
                            }
                            return;
                        }
                        // StackBlur requires canvas be on document
                        ctx.canvas.id = svg.UniqueId();
                        ctx.canvas.style.display = "none";
                        document.body.appendChild(ctx.canvas);
                        stackBlurCanvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
                        document.body.removeChild(ctx.canvas);
                    };
                };
                svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase();
                // title element, do nothing
                svg.Element.title = function(node) {};
                svg.Element.title.prototype = new svg.Element.ElementBase();
                // desc element, do nothing
                svg.Element.desc = function(node) {};
                svg.Element.desc.prototype = new svg.Element.ElementBase();
                svg.Element.MISSING = function(node) {
                    if (typeof console != "undefined") {
                        console.log("ERROR: Element '" + node.nodeName + "' not yet implemented.");
                    }
                };
                svg.Element.MISSING.prototype = new svg.Element.ElementBase();
                // element factory
                svg.CreateElement = function(node) {
                    var className = node.nodeName.replace(/^[^:]+:/, "");
                    // remove namespace
                    className = className.replace(/\-/g, "");
                    // remove dashes
                    var e = null;
                    if (typeof svg.Element[className] != "undefined") {
                        e = new svg.Element[className](node);
                    } else {
                        e = new svg.Element.MISSING(node);
                    }
                    e.type = node.nodeName;
                    return e;
                };
                // load from url
                svg.load = function(ctx, url) {
                    svg.loadXml(ctx, svg.ajax(url));
                };
                // load from xml
                svg.loadXml = function(ctx, xml) {
                    svg.loadXmlDoc(ctx, svg.parseXml(xml));
                };
                svg.loadXmlDoc = function(ctx, dom) {
                    svg.init(ctx);
                    var mapXY = function(p) {
                        var e = ctx.canvas;
                        while (e) {
                            p.x -= e.offsetLeft;
                            p.y -= e.offsetTop;
                            e = e.offsetParent;
                        }
                        if (window.scrollX) p.x += window.scrollX;
                        if (window.scrollY) p.y += window.scrollY;
                        return p;
                    };
                    // bind mouse
                    if (svg.opts["ignoreMouse"] != true) {
                        ctx.canvas.onclick = function(e) {
                            var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
                            svg.Mouse.onclick(p.x, p.y);
                        };
                        ctx.canvas.onmousemove = function(e) {
                            var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
                            svg.Mouse.onmousemove(p.x, p.y);
                        };
                    }
                    var e = svg.CreateElement(dom.documentElement);
                    e.root = true;
                    // render loop
                    var isFirstRender = true;
                    var draw = function() {
                        svg.ViewPort.Clear();
                        if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
                        if (svg.opts["ignoreDimensions"] != true) {
                            // set canvas size
                            if (e.style("width").hasValue()) {
                                ctx.canvas.width = e.style("width").toPixels("x");
                                ctx.canvas.style.width = ctx.canvas.width + "px";
                            }
                            if (e.style("height").hasValue()) {
                                ctx.canvas.height = e.style("height").toPixels("y");
                                ctx.canvas.style.height = ctx.canvas.height + "px";
                            }
                        }
                        var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
                        var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
                        if (svg.opts["ignoreDimensions"] == true && e.style("width").hasValue() && e.style("height").hasValue()) {
                            cWidth = e.style("width").toPixels("x");
                            cHeight = e.style("height").toPixels("y");
                        }
                        svg.ViewPort.SetCurrent(cWidth, cHeight);
                        if (svg.opts["offsetX"] != null) e.attribute("x", true).value = svg.opts["offsetX"];
                        if (svg.opts["offsetY"] != null) e.attribute("y", true).value = svg.opts["offsetY"];
                        if (svg.opts["scaleWidth"] != null && svg.opts["scaleHeight"] != null) {
                            var xRatio = 1, yRatio = 1, viewBox = svg.ToNumberArray(e.attribute("viewBox").value);
                            if (e.attribute("width").hasValue()) xRatio = e.attribute("width").toPixels("x") / svg.opts["scaleWidth"]; else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts["scaleWidth"];
                            if (e.attribute("height").hasValue()) yRatio = e.attribute("height").toPixels("y") / svg.opts["scaleHeight"]; else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts["scaleHeight"];
                            e.attribute("width", true).value = svg.opts["scaleWidth"];
                            e.attribute("height", true).value = svg.opts["scaleHeight"];
                            e.attribute("viewBox", true).value = "0 0 " + cWidth * xRatio + " " + cHeight * yRatio;
                            e.attribute("preserveAspectRatio", true).value = "none";
                        }
                        // clear and render
                        if (svg.opts["ignoreClear"] != true) {
                            ctx.clearRect(0, 0, cWidth, cHeight);
                        }
                        e.render(ctx);
                        if (isFirstRender) {
                            isFirstRender = false;
                            if (typeof svg.opts["renderCallback"] == "function") svg.opts["renderCallback"](dom);
                        }
                    };
                    var waitingForImages = true;
                    if (svg.ImagesLoaded()) {
                        waitingForImages = false;
                        draw();
                    }
                    svg.intervalID = setInterval(function() {
                        var needUpdate = false;
                        if (waitingForImages && svg.ImagesLoaded()) {
                            waitingForImages = false;
                            needUpdate = true;
                        }
                        // need update from mouse events?
                        if (svg.opts["ignoreMouse"] != true) {
                            needUpdate = needUpdate | svg.Mouse.hasEvents();
                        }
                        // need update from animations?
                        if (svg.opts["ignoreAnimation"] != true) {
                            for (var i = 0; i < svg.Animations.length; i++) {
                                needUpdate = needUpdate | svg.Animations[i].update(1e3 / svg.FRAMERATE);
                            }
                        }
                        // need update from redraw?
                        if (typeof svg.opts["forceRedraw"] == "function") {
                            if (svg.opts["forceRedraw"]() == true) needUpdate = true;
                        }
                        // render if needed
                        if (needUpdate) {
                            draw();
                            svg.Mouse.runEvents();
                        }
                    }, 1e3 / svg.FRAMERATE);
                };
                svg.stop = function() {
                    if (svg.intervalID) {
                        clearInterval(svg.intervalID);
                    }
                };
                svg.Mouse = new function() {
                    this.events = [];
                    this.hasEvents = function() {
                        return this.events.length != 0;
                    };
                    this.onclick = function(x, y) {
                        this.events.push({
                            type: "onclick",
                            x: x,
                            y: y,
                            run: function(e) {
                                if (e.onclick) e.onclick();
                            }
                        });
                    };
                    this.onmousemove = function(x, y) {
                        this.events.push({
                            type: "onmousemove",
                            x: x,
                            y: y,
                            run: function(e) {
                                if (e.onmousemove) e.onmousemove();
                            }
                        });
                    };
                    this.eventElements = [];
                    this.checkPath = function(element, ctx) {
                        for (var i = 0; i < this.events.length; i++) {
                            var e = this.events[i];
                            if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
                        }
                    };
                    this.checkBoundingBox = function(element, bb) {
                        for (var i = 0; i < this.events.length; i++) {
                            var e = this.events[i];
                            if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
                        }
                    };
                    this.runEvents = function() {
                        svg.ctx.canvas.style.cursor = "";
                        for (var i = 0; i < this.events.length; i++) {
                            var e = this.events[i];
                            var element = this.eventElements[i];
                            while (element) {
                                e.run(element);
                                element = element.parent;
                            }
                        }
                        // done running, clear
                        this.events = [];
                        this.eventElements = [];
                    };
                }();
                return svg;
            }
        })();
        if (typeof CanvasRenderingContext2D != "undefined") {
            CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {
                canvg(this.canvas, s, {
                    ignoreMouse: true,
                    ignoreAnimation: true,
                    ignoreDimensions: true,
                    ignoreClear: true,
                    offsetX: dx,
                    offsetY: dy,
                    scaleWidth: dw,
                    scaleHeight: dh
                });
            };
        }
        return canvg;
    }
};

/*!
 * 输出转换器,提供输出支持
 */
_p[1] = {
    value: function(require) {
        var kity = _p.r(34), canvg = _p.r(0);
        return kity.createClass("Output", {
            constructor: function(formula) {
                this.formula = formula;
            },
            toJPG: function(cb) {
                toImage(this.formula, "image/jpeg", cb);
            },
            toPNG: function(cb) {
                toImage(this.formula, "image/png", cb);
            }
        });
        function toImage(formula, type, cb) {
            var rectSpace = formula.container.getRenderBox();
            return getBase64DataURL(formula.node.ownerDocument, {
                width: rectSpace.width,
                height: rectSpace.height,
                content: getSVGContent(formula.node)
            }, type, cb);
        }
        function getBase64DataURL(doc, data, type, cb) {
            var canvas = null, args = arguments, ctx = null;
            if (true) {
                drawToCanvas.apply(null, args);
            } else {
                canvas = getImageCanvas(doc, data.width, data.height, type);
                ctx = canvas.getContext("2d");
                var image = new Image();
                image.onload = function() {
                    try {
                        ctx.drawImage(image, 0, 0);
                        cb(canvas.toDataURL(type));
                    } catch (e) {
                        drawToCanvas.apply(null, args);
                    }
                };
                image.src = getSVGDataURL(data.content);
            }
        }
        function getSVGContent(svgNode) {
            var tmp = svgNode.ownerDocument.createElement("div"), start = [ '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="', svgNode.getAttribute("width"), '" height="', svgNode.getAttribute("height"), '">' ];
            tmp.appendChild(svgNode.cloneNode(true));
            return tmp.innerHTML.replace(/<svg[^>]+?>/i, start.join("")).replace(/&nbsp;/g, "");
        }
        function getSVGDataURL(data) {
            return "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(data)));
        }
        function getImageCanvas(doc, width, height, type) {
            var canvas = doc.createElement("canvas"), ctx = canvas.getContext("2d");
            canvas.width = width;
            canvas.height = height;
            if (type !== "image/png") {
                ctx.fillStyle = "white";
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            }
            return canvas;
        }
        function drawToCanvas(doc, data, type, cb) {
            var canvas = getImageCanvas(doc, data.width, data.height, type);
            canvas.style.cssText = "position: absolute; top: 0; left: 100000px; z-index: -1;";
            window.setTimeout(function() {
                doc.body.appendChild(canvas);
                canvg(canvas, data.content);
                doc.body.removeChild(canvas);
                cb(canvas.toDataURL(type));
            }, 0);
        }
    }
};

/*!
 * 所有字符的列表
 */
_p[2] = {
    value: function() {
        return [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "&#x237;", "&#x131;", "&#x3b1;", "&#x3b2;", "&#x3b3;", "&#x3b4;", "&#x3b5;", "&#x3b6;", "&#x3b7;", "&#x3b8;", "&#x3b9;", "&#x3ba;", "&#x3bb;", "&#x3bc;", "&#x3bd;", "&#x3be;", "&#x3bf;", "&#x3c0;", "&#x3c1;", "&#x3c2;", "&#x3c3;", "&#x3c4;", "&#x3c5;", "&#x3c6;", "&#x3c7;", "&#x3c8;", "&#x3c9;", "&#x3d1;", "&#x3d5;", "&#x3d6;", "&#x3de;", "&#x3dc;", "&#x3f5;", "&#x3f1;", "&#x3f9;", "&#x211c;", "&#x2135;", "&#x2111;", "&#x2127;", "&#x2136;", "&#x2137;", "&#x2138;", "&#xf0;", "&#x210f;", "&#x2141;", "&#x210e;", "&#x2202;", "&#x2118;", "&#x214c;", "&#x2132;", "&#x2201;", "&#x2113;", "&#x24c8;", "(", ")", "&#x393;", "&#x394;", "&#x395;", "&#x396;", "&#x397;", "&#x398;", "&#x399;", "&#x39a;", "&#x39b;", "&#x39c;", "&#x39d;", "&#x39e;", "&#x39f;", "&#x3a0;", "&#x3a1;", "&#x3a3;", "&#x3a4;", "&#x3a5;", "&#x3a6;", "&#x3a7;", "&#x3a8;", "&#x3a9;", "&#x391;", "&#x392;", "#", "!", "$", "%", "&#x26;", "&#x2220;", "&#x2032;", "&#x2035;", "&#x2605;", "&#x25c6;", "&#x25a0;", "&#x25b2;", "&#x25bc;", "&#x22a4;", "&#x22a5;", "&#x2663;", "&#x2660;", "&#x2662;", "&#x2661;", "&#x2203;", "&#x2204;", "&#x266d;", "&#x266e;", "&#x266f;", "&#x2200;", "&#x221e;", "&#x2221;", "&#x2207;", "&#xac;", "&#x2222;", "&#x221a;", "&#x25b3;", "&#x25bd;", "&#x2205;", "&#xf8;", "&#x25c7;", "&#x25c0;", "&#x25b8;", "[", "]", "{", "}", "&#x3008;", "&#x3009;", "&#x3f0;", ",", ".", "/", ":", ";", "?", "\\", "&#x22ee;", "&#x22ef;", "&#x22f0;", "&#x2026;", "@", "&#x22;", "'", "|", "^", "`", "&#x201c;", "_", "*", "+", "-", "&#x2210;", "&#x22bc;", "&#x22bb;", "&#x25ef;", "&#x22a1;", "&#x229f;", "&#x229e;", "&#x22a0;", "&#x2022;", "&#x2229;", "&#x222a;", "&#x22d2;", "&#x22d3;", "&#x22d0;", "&#x22d1;", "&#xb7;", "&#x25aa;", "&#x25e6;", "&#x229b;", "&#x229a;", "&#x2296;", "&#x2299;", "&#x229d;", "&#x2295;", "&#x2297;", "&#x2298;", "&#xb1;", "&#x2213;", "&#x22cf;", "&#x22ce;", "&#x2020;", "&#x2021;", "&#x22c4;", "&#xf7;", "&#x22c7;", "&#x2214;", "&#x232d;", "&#x22d7;", "&#x22d6;", "&#x22c9;", "&#x22ca;", "&#x22cb;", "&#x22cc;", "&#x2293;", "&#x2294;", "&#x2291;", "&#x2292;", "&#x228f;", "&#x2290;", "&#x22c6;", "&#xd7;", "&#x22b3;", "&#x22b2;", "&#x22b5;", "&#x22b4;", "&#x228e;", "&#x2228;", "&#x2227;", "&#x2240;", "&#x3c;", "=", "&#x3e;", "&#x2248;", "&#x2247;", "&#x224d;", "&#x2252;", "&#x2253;", "&#x224a;", "&#x223d;", "&#x2241;", "&#x2242;", "&#x2243;", "&#x22cd;", "&#x224f;", "&#x224e;", "&#x2257;", "&#x2245;", "&#x22de;", "&#x22df;", "&#x2250;", "&#x2251;", "&#x2256;", "&#x2a96;", "&#x2a95;", "&#x2261;", "&#x2265;", "&#x2264;", "&#x2266;", "&#x2267;", "&#x2a7e;", "&#x2a7d;", "&#x226b;", "&#x226a;", "&#x2268;", "&#x2269;", "&#x22d8;", "&#x22d9;", "&#x2a87;", "&#x2a88;", "&#x2a89;", "&#x2a8a;", "&#x22e7;", "&#x22e6;", "&#x2a86;", "&#x2a85;", "&#x22db;", "&#x22da;", "&#x2a8b;", "&#x2a8c;", "&#x2277;", "&#x2276;", "&#x2273;", "&#x2272;", "&#x232e;", "&#x232f;", "&#x226f;", "&#x2271;", "&#x2270;", "&#x226e;", "&#x2331;", "&#x2330;", "&#x2332;", "&#x2333;", "&#x226c;", "&#x2280;", "&#x2281;", "&#x22e0;", "&#x22e1;", "&#x227a;", "&#x227b;", "&#x227c;", "&#x227d;", "&#x227e;", "&#x227f;", "&#x2282;", "&#x2283;", "&#x2288;", "&#x2289;", "&#x2286;", "&#x2287;", "&#x228a;", "&#x228b;", "&#x2ab7;", "&#x2ab8;", "&#x2aaf;", "&#x2ab0;", "&#x2ab9;", "&#x2aba;", "&#x2ab5;", "&#x2ab6;", "&#x22e8;", "&#x22e9;", "&#x223c;", "&#x225c;", "&#x21b6;", "&#x21b7;", "&#x21ba;", "&#x21bb;", "&#x21be;", "&#x21bf;", "&#x21c2;", "&#x21c3;", "&#x21c4;", "&#x21c6;", "&#x21c8;", "&#x21ca;", "&#x21cb;", "&#x21cc;", "&#x21cd;", "&#x21ce;", "&#x21cf;", "&#x21d0;", "&#x21d1;", "&#x21d2;", "&#x21d3;", "&#x21d4;", "&#x21d5;", "&#x21da;", "&#x21db;", "&#x21dd;", "&#x21ab;", "&#x21ac;", "&#x21ad;", "&#x21ae;", "&#x2190;", "&#x2191;", "&#x2192;", "&#x2193;", "&#x2194;", "&#x2195;", "&#x2196;", "&#x2197;", "&#x2198;", "&#x2199;", "&#x219e;", "&#x21a0;", "&#x21a2;", "&#x21a3;", "&#x21b0;", "&#x21b1;", "&#x22a2;", "&#x22a3;", "&#x22a8;", "&#x22a9;", "&#x22aa;", "&#x22ad;", "&#x22af;", "&#x22b8;", "&#x22ba;", "&#x22d4;", "&#x22ea;", "&#x22eb;", "&#x22ec;", "&#x22ed;", "&#x2308;", "&#x2309;", "&#x230a;", "&#x230b;", "&#x2acb;", "&#x2acc;", "&#x2ac5;", "&#x2ac6;", "&#x2208;", "&#x220b;", "&#x221d;", "&#x2224;", "&#x2226;", "&#x2234;", "&#x2235;", "&#x220d;", "&#x22c8;", "&#x2322;", "&#x2323;", "&#x2223;", "&#x2225;", "&#x23d0;", "&#x23d1;", "&#x23d2;", "&#x23d3;", "&#x2ac7;", "&#x2ac8;", "&#x22ae;", "&#x22ac;", "&#x2ac9;", "&#x23d4;", "&#x23d5;", "&#x23d6;", "&#x23d7;", "&#x21c7;", "&#x21c9;", "&#x21bc;", "&#x21bd;", "&#x21c0;", "&#x21c1;", "&#x219a;", "&#x219b;", "&#x27f5;", "&#x27f6;", "&#x27f7;", "&#x27f9;", "&#x27f8;", "&#x27fa;", "&#x2262;", "&#x2260;", "&#x2209;" ];
    }
};

/*!
 * 字符配置
 */
_p[3] = {
    value: function() {
        return {
            // 默认字体
            defaultFont: "KF AMS MAIN"
        };
    }
};

/*!
 * 工厂方法,创建兼容各浏览器的text实现
 */
_p[4] = {
    value: function(require) {
        var kity = _p.r(34), divNode = document.createElement("div"), NAMESPACE = "http://www.w3.org/XML/1998/namespace";
        function createText(content) {
            var text = new kity.Text();
            // Non-IE
            if ("innerHTML" in text.node) {
                text.node.setAttributeNS(NAMESPACE, "xml:space", "preserve");
            } else {
                if (content.indexOf(" ") != -1) {
                    content = convertContent(content);
                }
            }
            text.setContent(content);
            return text;
        }
        /**
     * 构建节点来转换内容
     */
        function convertContent(content) {
            divNode.innerHTML = '<svg><text gg="asfdas">' + content.replace(/\s/gi, "&nbsp;") + "</text></svg>";
            return divNode.firstChild.firstChild.textContent;
        }
        return {
            create: function(content) {
                return createText(content);
            }
        };
    }
};

/**
 * 文本
 */
_p[5] = {
    value: function(require) {
        var kity = _p.r(34), FONT_CONF = _p.r(47).font, FontManager = _p.r(25), TextFactory = _p.r(4);
        return kity.createClass("Text", {
            base: _p.r(46),
            constructor: function(content, fontFamily) {
                this.callBase();
                this.fontFamily = fontFamily;
                this.fontSize = 50;
                this.content = content || "";
                // 移除多余的节点
                this.box.remove();
                this.translationContent = this.translation(this.content);
                this.contentShape = new kity.Group();
                this.contentNode = this.createContent();
                this.contentShape.addShape(this.contentNode);
                this.addShape(this.contentShape);
            },
            createContent: function() {
                var contentNode = TextFactory.create(this.translationContent);
                contentNode.setAttr({
                    "font-family": this.fontFamily,
                    "font-size": 50,
                    x: 0,
                    y: FONT_CONF.offset
                });
                return contentNode;
            },
            setFamily: function(fontFamily) {
                this.fontFamily = fontFamily;
                this.contentNode.setAttr("font-family", fontFamily);
            },
            setFontSize: function(fontSize) {
                this.fontSize = fontSize;
                this.contentNode.setAttr("font-size", fontSize + "px");
                this.contentNode.setAttr("y", fontSize / 50 * FONT_CONF.offset);
            },
            getBaseHeight: function() {
                var chars = this.contentShape.getItems(), currentChar = null, index = 0, height = 0;
                while (currentChar = chars[index]) {
                    height = Math.max(height, currentChar.getHeight());
                    index++;
                }
                return height;
            },
            translation: function(content) {
                var fontFamily = this.fontFamily;
                // 首先特殊处理掉两个相连的"`"符号
                return content.replace(/``/g, "“").replace(/\\([a-zA-Z,]+)\\/g, function(match, input) {
                    if (input === ",") {
                        return " ";
                    }
                    var data = FontManager.getCharacterValue(input, fontFamily);
                    if (!data) {
                        return "";
                    }
                    return data;
                });
            }
        });
    }
};

/**
 * 定义公式中各种对象的类型
 */
_p[6] = {
    value: function() {
        return {
            UNKNOWN: -1,
            EXP: 0,
            COMPOUND_EXP: 1,
            OP: 2
        };
    }
};

/**
 * 定义公式中上下标的类型
 */
_p[7] = {
    value: function() {
        return {
            SIDE: "side",
            FOLLOW: "follow"
        };
    }
};

/**
 * 下标表达式
 */
_p[8] = {
    value: function(require) {
        var kity = _p.r(34);
        return kity.createClass("SubscriptExpression", {
            base: _p.r(17),
            constructor: function(operand, subscript) {
                this.callBase(operand, null, subscript);
                this.setFlag("Subscript");
            }
        });
    }
};

/**
 * 上标表达式
 */
_p[9] = {
    value: function(require) {
        var kity = _p.r(34);
        return kity.createClass("SuperscriptExpression", {
            base: _p.r(17),
            constructor: function(operand, superscript) {
                this.callBase(operand, superscript, null);
                this.setFlag("Superscript");
            }
        });
    }
};

/**
 * 二元操作表达式
 */
_p[10] = {
    value: function(require) {
        var kity = _p.r(34);
        return kity.createClass("BinaryExpression", {
            base: _p.r(19),
            constructor: function(firstOperand, lastOperand) {
                this.callBase();
                this.setFirstOperand(firstOperand);
                this.setLastOperand(lastOperand);
            },
            setFirstOperand: function(operand) {
                return this.setOperand(operand, 0);
            },
            getFirstOperand: function() {
                return this.getOperand(0);
            },
            setLastOperand: function(operand) {
                return this.setOperand(operand, 1);
            },
            getLastOperand: function() {
                return this.getOperand(1);
            }
        });
    }
};

/**
 * 自动增长括号表达式
 */
_p[11] = {
    value: function(require) {
        var kity = _p.r(34), BracketsOperator = _p.r(35);
        return kity.createClass("BracketsExpression", {
            base: _p.r(19),
            /**
         * 构造函数调用方式:
         *  new Constructor( 左括号, 右括号, 表达式 )
         *  或者
         *  new Constructor( 括号, 表达式 ), 该构造函数转换成上面的构造函数,是: new Constructor( 括号, 括号, 表达式 )
         * @param left 左括号
         * @param right 右括号
         * @param exp 表达式
         */
            constructor: function(left, right, exp) {
                this.callBase();
                this.setFlag("Brackets");
                // 参数整理
                if (arguments.length === 2) {
                    exp = right;
                    right = left;
                }
                this.leftSymbol = left;
                this.rightSymbol = right;
                this.setOperator(new BracketsOperator());
                this.setOperand(exp, 0);
            },
            getLeftSymbol: function() {
                return this.leftSymbol;
            },
            getRightSymbol: function() {
                return this.rightSymbol;
            }
        });
    }
};

/**
 * 组合表达式
 * 可以组合多个表达式
 */
_p[12] = {
    value: function(require) {
        var kity = _p.r(34), FONT_CONF = _p.r(47).font, CombinationOperator = _p.r(36);
        return kity.createClass("CombinationExpression", {
            base: _p.r(19),
            constructor: function() {
                this.callBase();
                this.setFlag("Combination");
                this.setOperator(new CombinationOperator());
                kity.Utils.each(arguments, function(operand, index) {
                    this.setOperand(operand, index);
                }, this);
            },
            getRenderBox: function(refer) {
                var rectBox = this.callBase(refer);
                if (this.getOperands().length === 0) {
                    rectBox.height = FONT_CONF.spaceHeight;
                }
                return rectBox;
            },
            getBaseline: function(refer) {
                var maxBaseline = 0, operands = this.getOperands();
                if (operands.length === 0) {
                    return this.callBase(refer);
                }
                kity.Utils.each(operands, function(operand) {
                    maxBaseline = Math.max(operand.getBaseline(refer), maxBaseline);
                });
                return maxBaseline;
            },
            getMeanline: function(refer) {
                var minMeanline = 1e7, operands = this.getOperands();
                if (operands.length === 0) {
                    return this.callBase(refer);
                }
                kity.Utils.each(operands, function(operand) {
                    minMeanline = Math.min(operand.getMeanline(refer), minMeanline);
                });
                return minMeanline;
            }
        });
    }
};

/**
 * 分数表达式
 */
_p[13] = {
    value: function(require) {
        var kity = _p.r(34), FractionOperator = _p.r(38);
        return kity.createClass("FractionExpression", {
            base: _p.r(10),
            constructor: function(upOperand, downOperand) {
                this.callBase(upOperand, downOperand);
                this.setFlag("Fraction");
                this.setOperator(new FractionOperator());
            },
            /*------- 重写分数结构的baseline和mealine计算方式 */
            getBaseline: function(refer) {
                var downOperand = this.getOperand(1), rectBox = downOperand.getRenderBox(refer);
                return rectBox.y + downOperand.getBaselineProportion() * rectBox.height;
            },
            getMeanline: function(refer) {
                var upOperand = this.getOperand(0), rectBox = upOperand.getRenderBox(refer);
                return upOperand.getMeanlineProportion() * rectBox.height;
            }
        });
    }
};

/**
 * 函数表达式
 */
_p[14] = {
    value: function(require) {
        var kity = _p.r(34), FUNC_CONF = _p.r(47).func, FunctionOperator = _p.r(39);
        return kity.createClass("FunctionExpression", {
            base: _p.r(19),
            /**
         * function表达式构造函数
         * @param funcName function名称
         * @param expr 函数表达式
         * @param sup 上标
         * @param sub 下标
         */
            constructor: function(funcName, expr, sup, sub) {
                this.callBase();
                this.setFlag("Func");
                this.funcName = funcName;
                this.setOperator(new FunctionOperator(funcName));
                this.setExpr(expr);
                this.setSuperscript(sup);
                this.setSubscript(sub);
            },
            // 当前函数应用的script位置是否是在侧面
            isSideScript: function() {
                return !FUNC_CONF["ud-script"][this.funcName];
            },
            setExpr: function(expr) {
                return this.setOperand(expr, 0);
            },
            setSuperscript: function(sub) {
                return this.setOperand(sub, 1);
            },
            setSubscript: function(sub) {
                return this.setOperand(sub, 2);
            }
        });
    }
};

/**
 * 积分表达式
 */
_p[15] = {
    value: function(require) {
        var kity = _p.r(34), IntegrationOperator = _p.r(40), IntegrationExpression = kity.createClass("IntegrationExpression", {
            base: _p.r(19),
            /**
             * 构造积分表达式
             * @param integrand 被积函数
             * @param supOperand 上限
             * @param subOperand 下限
             */
            constructor: function(integrand, superscript, subscript) {
                this.callBase();
                this.setFlag("Integration");
                this.setOperator(new IntegrationOperator());
                this.setIntegrand(integrand);
                this.setSuperscript(superscript);
                this.setSubscript(subscript);
            },
            setType: function(type) {
                this.getOperator().setType(type);
                return this;
            },
            resetType: function() {
                this.getOperator().resetType();
                return this;
            },
            setIntegrand: function(integrand) {
                this.setOperand(integrand, 0);
            },
            setSuperscript: function(sup) {
                this.setOperand(sup, 1);
            },
            setSubscript: function(sub) {
                this.setOperand(sub, 2);
            }
        });
        return IntegrationExpression;
    }
};

/**
 * 方根表达式
 */
_p[16] = {
    value: function(require) {
        var kity = _p.r(34), RadicalOperator = _p.r(42);
        return kity.createClass("RadicalExpression", {
            base: _p.r(10),
            /**
         * 构造开方表达式
         * @param radicand 被开方数
         * @param exponent 指数
         */
            constructor: function(radicand, exponent) {
                this.callBase(radicand, exponent);
                this.setFlag("Radicand");
                this.setOperator(new RadicalOperator());
            },
            setRadicand: function(operand) {
                return this.setFirstOperand(operand);
            },
            getRadicand: function() {
                return this.getFirstOperand();
            },
            setExponent: function(operand) {
                return this.setLastOperand(operand);
            },
            getExponent: function() {
                return this.getLastOperand();
            }
        });
    }
};

/**
 * 上标表达式
 */
_p[17] = {
    value: function(require) {
        var kity = _p.r(34), ScriptOperator = _p.r(43);
        return kity.createClass("ScriptExpression", {
            base: _p.r(19),
            constructor: function(operand, superscript, subscript) {
                this.callBase();
                this.setFlag("Script");
                this.setOperator(new ScriptOperator());
                this.setOpd(operand);
                this.setSuperscript(superscript);
                this.setSubscript(subscript);
            },
            setOpd: function(operand) {
                this.setOperand(operand, 0);
            },
            setSuperscript: function(sup) {
                this.setOperand(sup, 1);
            },
            setSubscript: function(sub) {
                this.setOperand(sub, 2);
            }
        });
    }
};

/**
 * 求和表达式
 */
_p[18] = {
    value: function(require) {
        var kity = _p.r(34), SummationOperator = _p.r(44);
        return kity.createClass("SummationExpression", {
            base: _p.r(19),
            /**
         * 构造求和表达式
         * @param expr 求和表达式
         * @param upOperand 上标
         * @param downOperand 下标
         */
            constructor: function(expr, superscript, subscript) {
                this.callBase();
                this.setFlag("Summation");
                this.setOperator(new SummationOperator());
                this.setExpr(expr);
                this.setSuperscript(superscript);
                this.setSubscript(subscript);
            },
            setExpr: function(expr) {
                this.setOperand(expr, 0);
            },
            setSuperscript: function(sup) {
                this.setOperand(sup, 1);
            },
            setSubscript: function(sub) {
                this.setOperand(sub, 2);
            }
        });
    }
};

/**
 * 复合表达式
 * @abstract
 */
_p[19] = {
    value: function(require) {
        var kity = _p.r(34), GTYPE = _p.r(6), Expression = _p.r(21);
        return kity.createClass("CompoundExpression", {
            base: _p.r(21),
            constructor: function() {
                this.callBase();
                this.type = GTYPE.COMPOUND_EXP;
                this.operands = [];
                this.operator = null;
                this.operatorBox = new kity.Group();
                this.operatorBox.setAttr("data-type", "kf-editor-exp-op-box");
                this.operandBox = new kity.Group();
                this.operandBox.setAttr("data-type", "kf-editor-exp-operand-box");
                this.setChildren(0, this.operatorBox);
                this.setChildren(1, this.operandBox);
            },
            // 操作符存储在第1位置
            setOperator: function(operator) {
                if (operator === undefined) {
                    return this;
                }
                if (this.operator) {
                    this.operator.remove();
                }
                this.operatorBox.addShape(operator);
                this.operator = operator;
                this.operator.setParentExpression(this);
                // 表达式关联到操作符
                operator.expression = this;
                return this;
            },
            getOperator: function() {
                return this.operator;
            },
            // 操作数存储位置是从1开始
            setOperand: function(operand, index, isWrap) {
                // 不包装操作数
                if (isWrap === false) {
                    this.operands[index] = operand;
                    return this;
                }
                operand = Expression.wrap(operand);
                if (this.operands[index]) {
                    this.operands[index].remove();
                }
                this.operands[index] = operand;
                this.operandBox.addShape(operand);
                return this;
            },
            getOperand: function(index) {
                return this.operands[index];
            },
            getOperands: function() {
                return this.operands;
            },
            addedCall: function() {
                this.operator.applyOperand.apply(this.operator, this.operands);
                return this;
            }
        });
    }
};

/**
 * 空表达式
 * 该表达式主要用途是用于站位
 */
_p[20] = {
    value: function(require) {
        var kity = _p.r(34), FONT_CONF = _p.r(47).font, Expression = _p.r(21), EmptyExpression = kity.createClass("EmptyExpression", {
            base: Expression,
            constructor: function() {
                this.callBase();
                this.setFlag("Empty");
            },
            getRenderBox: function() {
                return {
                    width: 0,
                    height: FONT_CONF.spaceHeight,
                    x: 0,
                    y: 0
                };
            }
        });
        EmptyExpression.isEmpty = function(target) {
            return target instanceof EmptyExpression;
        };
        // 注册打包函数
        Expression.registerWrap("empty", function(operand) {
            if (operand === null || operand === undefined) {
                return new EmptyExpression();
            }
        });
        return EmptyExpression;
    }
};

/**
 * 基础表达式, 该类是表达式和操作数的高层抽象
 * @abstract
 */
_p[21] = {
    value: function(require) {
        var kity = _p.r(34), GTYPE = _p.r(6), FONT_CONF = _p.r(47).font, // 打包函数列表
        WRAP_FN = [], // 注册的打包函数的名称与其在注册器列表中的索引之间的对应关系
        WRAP_FN_INDEX = {}, Expression = kity.createClass("Expression", {
            base: _p.r(46),
            constructor: function() {
                this.callBase();
                this.type = GTYPE.EXP;
                // 表达式的上下偏移
                this._offset = {
                    top: 0,
                    bottom: 0
                };
                this.children = [];
                this.box.fill("transparent").setAttr("data-type", "kf-editor-exp-box");
                this.box.setAttr("data-type", "kf-editor-exp-bg-box");
                this.expContent = new kity.Group();
                this.expContent.setAttr("data-type", "kf-editor-exp-content-box");
                this.addShape(this.expContent);
            },
            getChildren: function() {
                return this.children;
            },
            getChild: function(index) {
                return this.children[index] || null;
            },
            getTopOffset: function() {
                return this._offset.top;
            },
            getBottomOffset: function() {
                return this._offset.bottom;
            },
            getOffset: function() {
                return this._offset;
            },
            setTopOffset: function(val) {
                this._offset.top = val;
            },
            setBottomOffset: function(val) {
                this._offset.bottom = val;
            },
            setOffset: function(top, bottom) {
                this._offset.top = top;
                this._offset.bottom = bottom;
            },
            setFlag: function(flag) {
                this.setAttr("data-flag", flag || "Expression");
            },
            setChildren: function(index, exp) {
                // 首先清理掉之前的表达式
                if (this.children[index]) {
                    this.children[index].remove();
                }
                this.children[index] = exp;
                this.expContent.addShape(exp);
            },
            getBaselineProportion: function() {
                return FONT_CONF.baselinePosition;
            },
            getMeanlineProportion: function() {
                return FONT_CONF.meanlinePosition;
            },
            getBaseline: function(refer) {
                // 上偏移3px
                return this.getRenderBox(refer).height * FONT_CONF.baselinePosition - 3;
            },
            getMeanline: function(refer) {
                // 上偏移1px
                return this.getRenderBox(refer).height * FONT_CONF.meanlinePosition - 1;
            },
            getAscenderline: function() {
                return this.getFixRenderBox().height * FONT_CONF.ascenderPosition;
            },
            getDescenderline: function() {
                return this.getFixRenderBox().height * FONT_CONF.descenderPosition;
            },
            translateElement: function(x, y) {
                this.expContent.translate(x, y);
            },
            expand: function(width, height) {
                var renderBox = this.getFixRenderBox();
                this.setBoxSize(renderBox.width + width, renderBox.height + height);
            },
            getBaseWidth: function() {
                return this.getWidth();
            },
            getBaseHeight: function() {
                return this.getHeight();
            },
            updateBoxSize: function() {
                var renderBox = this.expContent.getFixRenderBox();
                this.setBoxSize(renderBox.width, renderBox.height);
            },
            getBox: function() {
                return this.box;
            }
        });
        // 表达式自动打包
        kity.Utils.extend(Expression, {
            registerWrap: function(name, fn) {
                WRAP_FN_INDEX[name] = WRAP_FN.length;
                WRAP_FN.push(fn);
            },
            revokeWrap: function(name) {
                var fn = null;
                if (name in WRAP_FN_INDEX) {
                    fn = WRAP_FN[WRAP_FN_INDEX[name]];
                    WRAP_FN[WRAP_FN_INDEX[name]] = null;
                    delete WRAP_FN_INDEX[name];
                }
                return fn;
            },
            // 打包函数
            wrap: function(operand) {
                var result;
                kity.Utils.each(WRAP_FN, function(fn) {
                    if (!fn) {
                        return;
                    }
                    result = fn(operand);
                    if (result) {
                        return false;
                    }
                });
                return result;
            }
        });
        return Expression;
    }
};

/**
 * Text表达式
 */
_p[22] = {
    value: function(require) {
        var Text = _p.r(5), kity = _p.r(34), FONT_CONF = _p.r(3), Expression = _p.r(21), TextExpression = kity.createClass("TextExpression", {
            base: _p.r(21),
            constructor: function(content, fontFamily) {
                this.callBase();
                this.fontFamily = fontFamily || FONT_CONF.defaultFont;
                this.setFlag("Text");
                this.content = content + "";
                this.textContent = new Text(this.content, this.fontFamily);
                this.setChildren(0, this.textContent);
                this.setChildren(1, new kity.Rect(0, 0, 0, 0).fill("transparent"));
            },
            setFamily: function(fontFamily) {
                this.textContent.setFamily(fontFamily);
            },
            setFontSize: function(fontSize) {
                this.textContent.setFontSize(fontSize);
            },
            addedCall: function() {
                var box = this.textContent.getFixRenderBox();
                this.getChild(1).setSize(box.width, box.height);
                this.updateBoxSize();
                return this;
            }
        });
        // 注册文本表达式的打包函数
        Expression.registerWrap("text", function(operand) {
            var operandType = typeof operand;
            if (operandType === "number" || operandType === "string") {
                operand = new TextExpression(operand);
            }
            return operand;
        });
        return TextExpression;
    }
};

/*!
 * 字体信息检测模板,用于检测浏览器的字体信息
 */
_p[23] = {
    value: function() {
        return [ '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">', '<text id="abcd" font-family="KF AMS MAIN" font-size="50" x="0" y="0">x</text>', "</svg>" ];
    }
};

/*!
 * 字体安装器
 */
_p[24] = {
    value: function(require) {
        var kity = _p.r(34), FontManager = _p.r(25), $ = _p.r(33), FONT_CONF = _p.r(47).font, CHAR_LIST = _p.r(2), NODE_LIST = [];
        return kity.createClass("FontInstaller", {
            constructor: function(doc, resource) {
                this.callBase();
                this.resource = resource || "../src/resource/";
                this.doc = doc;
            },
            // 挂载字体
            mount: function(callback) {
                var fontList = FontManager.getFontList(), count = 0, _self = this;
                kity.Utils.each(fontList, function(fontInfo) {
                    count++;
                    fontInfo.meta.src = _self.resource + fontInfo.meta.src;
                    _self.createFontStyle(fontInfo);
                    preload(_self.doc, fontInfo, function() {
                        count--;
                        if (count === 0) {
                            complete(_self.doc, callback);
                        }
                    });
                });
            },
            createFontStyle: function(fontInfo) {
                var stylesheet = this.doc.createElement("style"), tpl = '@font-face{\nfont-family: "${fontFamily}";\nsrc: url("${src}");\n}';
                stylesheet.setAttribute("type", "text/css");
                stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
                this.doc.head.appendChild(stylesheet);
            }
        });
        function preload(doc, fontInfo, callback) {
            $.get(fontInfo.meta.src, function(data, state) {
                if (state === "success") {
                    applyFonts(doc, fontInfo);
                }
                callback();
            });
        }
        function complete(doc, callback) {
            window.setTimeout(function() {
                initFontSystemInfo(doc);
                removeTmpNode();
                callback();
            }, 100);
        }
        function applyFonts(doc, fontInfo) {
            var node = document.createElement("div"), fontFamily = fontInfo.meta.fontFamily;
            node.style.cssText = "position: absolute; top: -10000px; left: -100000px;";
            node.style.fontFamily = fontFamily;
            node.innerHTML = CHAR_LIST.join("");
            doc.body.appendChild(node);
            NODE_LIST.push(node);
        }
        /**
     * 计算字体系统信息
     */
        function initFontSystemInfo(doc) {
            var tmpNode = doc.createElement("div");
            tmpNode.style.cssText = "position: absolute; top: 0; left: -100000px;";
            tmpNode.innerHTML = _p.r(23).join("");
            doc.body.appendChild(tmpNode);
            var rectBox = tmpNode.getElementsByTagName("text")[0].getBBox();
            // text实际占用空间
            FONT_CONF.spaceHeight = rectBox.height;
            // text顶部空间
            FONT_CONF.topSpace = -rectBox.y - FONT_CONF.baseline;
            FONT_CONF.bottomSpace = FONT_CONF.spaceHeight - FONT_CONF.topSpace - FONT_CONF.baseHeight;
            // text偏移值
            FONT_CONF.offset = FONT_CONF.baseline + FONT_CONF.topSpace;
            // baseline比例
            FONT_CONF.baselinePosition = (FONT_CONF.topSpace + FONT_CONF.baseline) / FONT_CONF.spaceHeight;
            // meanline比例
            FONT_CONF.meanlinePosition = (FONT_CONF.topSpace + FONT_CONF.meanline) / FONT_CONF.spaceHeight;
            // 上下延伸性比例
            FONT_CONF.ascenderPosition = FONT_CONF.topSpace / FONT_CONF.spaceHeight;
            FONT_CONF.descenderPosition = (FONT_CONF.topSpace + FONT_CONF.baseHeight) / FONT_CONF.spaceHeight;
            doc.body.removeChild(tmpNode);
        }
        function removeTmpNode() {
            kity.Utils.each(NODE_LIST, function(node) {
                node.parentNode.removeChild(node);
            });
            NODE_LIST = [];
        }
    }
};

/*!
 * 字体管理器
 */
_p[25] = {
    value: function(require) {
        var FONT_LIST = {}, kity = _p.r(34), CONF = _p.r(47).font.list;
        // init
        (function() {
            kity.Utils.each(CONF, function(fontData) {
                FONT_LIST[fontData.meta.fontFamily] = fontData;
            });
        })();
        return {
            getFontList: function() {
                return FONT_LIST;
            },
            getCharacterValue: function(key, fontFamily) {
                if (!FONT_LIST[fontFamily]) {
                    return null;
                }
                return FONT_LIST[fontFamily].map[key] || null;
            }
        };
    }
};

/*!
 * 双线字体
 */
_p[26] = {
    value: function() {
        return {
            meta: {
                fontFamily: "KF AMS BB",
                src: "KF_AMS_BB.woff"
            }
        };
    }
};

/*!
 * 手写体
 */
_p[27] = {
    value: function() {
        return {
            meta: {
                fontFamily: "KF AMS CAL",
                src: "KF_AMS_CAL.woff"
            }
        };
    }
};

/*!
 * 花体
 */
_p[28] = {
    value: function() {
        return {
            meta: {
                fontFamily: "KF AMS FRAK",
                src: "KF_AMS_FRAK.woff"
            }
        };
    }
};

/*!
 * 字体主文件
 */
_p[29] = {
    value: function() {
        return {
            meta: {
                fontFamily: "KF AMS MAIN",
                src: "KF_AMS_MAIN.woff"
            },
            map: {
                // char
                Alpha: "Α",
                Beta: "Β",
                Gamma: "Γ",
                Delta: "Δ",
                Epsilon: "Ε",
                Zeta: "Ζ",
                Eta: "Η",
                Theta: "Θ",
                Iota: "Ι",
                Kappa: "Κ",
                Lambda: "Λ",
                Mu: "Μ",
                Nu: "Ν",
                Xi: "Ξ",
                Omicron: "Ο",
                Pi: "Π",
                Rho: "Ρ",
                Sigma: "Σ",
                Tau: "Τ",
                Upsilon: "Υ",
                Phi: "Φ",
                Chi: "Χ",
                Psi: "Ψ",
                Omega: "Ω",
                alpha: "α",
                beta: "β",
                gamma: "γ",
                delta: "δ",
                epsilon: "ε",
                zeta: "ζ",
                eta: "η",
                theta: "θ",
                iota: "ι",
                kappa: "κ",
                lambda: "λ",
                mu: "μ",
                nu: "ν",
                xi: "ξ",
                omicron: "ο",
                pi: "π",
                rho: "ρ",
                sigma: "σ",
                tau: "τ",
                upsilon: "υ",
                phi: "φ",
                varkappa: "ϰ",
                chi: "χ",
                psi: "ψ",
                omega: "ω",
                digamma: "Ϝ",
                varepsilon: "ϵ",
                varrho: "ϱ",
                varphi: "ϕ",
                vartheta: "ϑ",
                varpi: "ϖ",
                varsigma: "Ϲ",
                aleph: "ℵ",
                beth: "ℶ",
                daleth: "ℸ",
                gimel: "ℷ",
                eth: "ð",
                hbar: "ℎ",
                hslash: "ℏ",
                mho: "℧",
                partial: "∂",
                wp: "℘",
                Game: "⅁",
                Bbbk: "⅌",
                Finv: "Ⅎ",
                Im: "ℑ",
                Re: "ℜ",
                complement: "∁",
                ell: "ℓ",
                circledS: "Ⓢ",
                imath: "ı",
                jmath: "ȷ",
                // symbol
                doublecap: "⋒",
                Cap: "⋒",
                doublecup: "⋓",
                Cup: "⋓",
                ast: "*",
                divideontimes: "⋇",
                rightthreetimes: "⋌",
                leftthreetimes: "⋋",
                cdot: "·",
                odot: "⊙",
                dotplus: "∔",
                rtimes: "⋊",
                ltimes: "⋉",
                centerdot: "▪",
                doublebarwedge: "⌭",
                setminus: "⒁",
                amalg: "∐",
                circ: "◦",
                bigcirc: "◯",
                gtrdot: "⋗",
                lessdot: "⋖",
                smallsetminus: "⒅",
                circledast: "⊛",
                circledcirc: "⊚",
                sqcap: "⊓",
                sqcup: "⊔",
                barwedge: "⊼",
                circleddash: "⊝",
                star: "⋆",
                bigtriangledown: "▽",
                bigtriangleup: "△",
                cup: "∪",
                cap: "∩",
                times: "×",
                mp: "∓",
                pm: "±",
                triangleleft: "⊲",
                triangleright: "⊳",
                boxdot: "⊡",
                curlyvee: "⋏",
                curlywedge: "⋎",
                boxminus: "⊟",
                boxtimes: "⊠",
                ominus: "⊖",
                oplus: "⊕",
                oslash: "⊘",
                otimes: "⊗",
                uplus: "⊎",
                boxplus: "⊞",
                dagger: "†",
                ddagger: "‡",
                vee: "∨",
                lor: "∨",
                veebar: "⊻",
                bullet: "•",
                diamond: "⋄",
                wedge: "∧",
                land: "∧",
                div: "÷",
                wr: "≀",
                geqq: "≧",
                lll: "⋘",
                llless: "⋘",
                ggg: "⋙",
                gggtr: "⋙",
                preccurlyeq: "≼",
                geqslant: "⩾",
                lnapprox: "⪉",
                preceq: "⪯",
                gg: "≫",
                lneq: "⪇",
                precnapprox: "⪹",
                approx: "≈",
                lneqq: "≨",
                precneqq: "⪵",
                approxeq: "≊",
                gnapprox: "⪊",
                lnsim: "⋦",
                precnsim: "⋨",
                asymp: "≍",
                gneq: "⪈",
                lvertneqq: "⌮",
                precsim: "≾",
                backsim: "∽",
                gneqq: "≩",
                ncong: "≇",
                risingdotseq: "≓",
                backsimeq: "⋍",
                gnsim: "⋧",
                sim: "∼",
                simeq: "≃",
                bumpeq: "≏",
                gtrapprox: "⪆",
                ngeq: "≱",
                Bumpeq: "≎",
                gtreqless: "⋛",
                ngeqq: "⌱",
                succ: "≻",
                circeq: "≗",
                gtreqqless: "⪌",
                ngeqslant: "⌳",
                succapprox: "⪸",
                cong: "≅",
                gtrless: "≷",
                ngtr: "≯",
                succcurlyeq: "≽",
                curlyeqprec: "⋞",
                gtrsim: "≳",
                nleq: "≰",
                succeq: "⪰",
                curlyeqsucc: "⋟",
                gvertneqq: "⌯",
                neq: "≠",
                ne: "≠",
                nequiv: "≢",
                nleqq: "⌰",
                succnapprox: "⪺",
                doteq: "≐",
                leq: "≤",
                le: "≤",
                nleqslant: "⌲",
                succneqq: "⪶",
                doteqdot: "≑",
                Doteq: "≑",
                leqq: "≦",
                nless: "≮",
                succnsim: "⋩",
                leqslant: "⩽",
                nprec: "⊀",
                succsim: "≿",
                eqsim: "≂",
                lessapprox: "⪅",
                npreceq: "⋠",
                eqslantgtr: "⪖",
                lesseqgtr: "⋚",
                nsim: "≁",
                eqslantless: "⪕",
                lesseqqgtr: "⪋",
                nsucc: "⊁",
                triangleq: "≜",
                eqcirc: "≖",
                equiv: "≡",
                lessgtr: "≶",
                nsucceq: "⋡",
                fallingdotseq: "≒",
                lesssim: "≲",
                prec: "≺",
                geq: "≥",
                ge: "≥",
                ll: "≪",
                precapprox: "⪷",
                // arrows
                uparrow: "↑",
                downarrow: "↓",
                updownarrow: "↕",
                Uparrow: "⇑",
                Downarrow: "⇓",
                Updownarrow: "⇕",
                circlearrowleft: "↺",
                circlearrowright: "↻",
                curvearrowleft: "↶",
                curvearrowright: "↷",
                downdownarrows: "⇊",
                downharpoonleft: "⇃",
                downharpoonright: "⇂",
                leftarrow: "←",
                gets: "←",
                Leftarrow: "⇐",
                leftarrowtail: "↢",
                leftharpoondown: "↽",
                leftharpoonup: "↼",
                leftleftarrows: "⇇",
                leftrightarrow: "↔",
                Leftrightarrow: "⇔",
                leftrightarrows: "⇄",
                leftrightharpoons: "⇋",
                leftrightsquigarrow: "↭",
                Lleftarrow: "⇚",
                looparrowleft: "↫",
                looparrowright: "↬",
                multimap: "⊸",
                nLeftarrow: "⇍",
                nRightarrow: "⇏",
                nLeftrightarrow: "⇎",
                nearrow: "↗",
                nleftarrow: "↚",
                nleftrightarrow: "↮",
                nrightarrow: "↛",
                nwarrow: "↖",
                rightarrow: "→",
                to: "→",
                Rightarrow: "⇒",
                rightarrowtail: "↣",
                rightharpoondown: "⇁",
                rightharpoonup: "⇀",
                rightleftarrows: "⇆",
                rightleftharpoons: "⇌",
                rightrightarrows: "⇉",
                rightsquigarrow: "⇝",
                Rrightarrow: "⇛",
                searrow: "↘",
                swarrow: "↙",
                twoheadleftarrow: "↞",
                twoheadrightarrow: "↠",
                upharpoonleft: "↿",
                upharpoonright: "↾",
                restriction: "↾",
                upuparrows: "⇈",
                Lsh: "↰",
                Rsh: "↱",
                longleftarrow: "⟵",
                longrightarrow: "⟶",
                Longleftarrow: "⟸",
                Longrightarrow: "⟹",
                implies: "⟹",
                longleftrightarrow: "⟷",
                Longleftrightarrow: "⟺",
                // relation
                backepsilon: "∍",
                because: "∵",
                therefore: "∴",
                between: "≬",
                blacktriangleleft: "◀",
                blacktriangleright: "▸",
                dashv: "⊣",
                bowtie: "⋈",
                frown: "⌢",
                "in": "∈",
                notin: "∉",
                mid: "∣",
                parallel: "∥",
                models: "⊨",
                ni: "∋",
                owns: "∋",
                nmid: "∤",
                nparallel: "∦",
                nshortmid: "⏒",
                nshortparallel: "⏓",
                nsubseteq: "⊈",
                nsubseteqq: "⫇",
                nsupseteq: "⊉",
                nsupseteqq: "⫈",
                ntriangleleft: "⋪",
                ntrianglelefteq: "⋬",
                ntriangleright: "⋫",
                ntrianglerighteq: "⋭",
                nvdash: "⊬",
                nVdash: "⊮",
                nvDash: "⊭",
                nVDash: "⊯",
                perp: "⊥",
                pitchfork: "⋔",
                propto: "∝",
                shortmid: "⏐",
                shortparallel: "⏑",
                smile: "⌣",
                sqsubset: "⊏",
                sqsubseteq: "⊑",
                sqsupset: "⊐",
                sqsupseteq: "⊒",
                subset: "⊂",
                Subset: "⋐",
                subseteq: "⊆",
                subseteqq: "⫅",
                subsetneq: "⊊",
                subsetneqq: "⫋",
                supset: "⊃",
                Supset: "⋑",
                supseteq: "⊇",
                supseteqq: "⫆",
                supsetneq: "⊋",
                supsetneqq: "⫌",
                trianglelefteq: "⊴",
                trianglerighteq: "⊵",
                varpropto: "⫉",
                varsubsetneq: "⏔",
                varsubsetneqq: "⏖",
                varsupsetneq: "⏕",
                varsupsetneqq: "⏗",
                vdash: "⊢",
                Vdash: "⊩",
                vDash: "⊨",
                Vvdash: "⊪",
                vert: "|",
                Vert: "ǁ",
                "|": "ǁ",
                "{": "{",
                "}": "}",
                backslash: "\\",
                langle: "〈",
                rangle: "〉",
                lceil: "⌈",
                rceil: "⌉",
                lbrace: "{",
                rbrace: "}",
                lfloor: "⌊",
                rfloor: "⌋",
                cdots: "⋯",
                ddots: "⋰",
                vdots: "⋮",
                dots: "…",
                ldots: "…",
                "#": "#",
                bot: "⊥",
                angle: "∠",
                backprime: "‵",
                bigstar: "★",
                blacklozenge: "◆",
                blacksquare: "■",
                blacktriangle: "▲",
                blacktriangledown: "▼",
                clubsuit: "♣",
                diagdown: "⒁",
                diagup: "⒂",
                diamondsuit: "♢",
                emptyset: "ø",
                exists: "∃",
                flat: "♭",
                forall: "∀",
                heartsuit: "♡",
                infty: "∞",
                lozenge: "◇",
                measuredangle: "∡",
                nabla: "∇",
                natural: "♮",
                neg: "¬",
                lnot: "¬",
                nexists: "∄",
                prime: "′",
                sharp: "♯",
                spadesuit: "♠",
                sphericalangle: "∢",
                surd: "√",
                top: "⊤",
                varnothing: "∅",
                triangle: "△",
                triangledown: "▽"
            }
        };
    }
};

/*!
 * 罗马字体
 */
_p[30] = {
    value: function() {
        return {
            meta: {
                fontFamily: "KF AMS ROMAN",
                src: "KF_AMS_ROMAN.woff"
            }
        };
    }
};

/**
 * 公式对象,表达式容器
 */
_p[31] = {
    value: function(require) {
        var kity = _p.r(34), GTYPE = _p.r(6), FontManager = _p.r(25), FontInstaller = _p.r(24), DEFAULT_OPTIONS = {
            fontsize: 50,
            autoresize: true,
            padding: [ 0 ]
        }, Output = _p.r(1), EXPRESSION_INTERVAL = 10, ExpressionWrap = kity.createClass("ExpressionWrap", {
            constructor: function(exp, config) {
                this.wrap = new kity.Group();
                this.bg = new kity.Rect(0, 0, 0, 0).fill("transparent");
                this.exp = exp;
                this.config = config;
                this.wrap.setAttr("data-type", "kf-exp-wrap");
                this.bg.setAttr("data-type", "kf-exp-wrap-bg");
                this.wrap.addShape(this.bg);
                this.wrap.addShape(this.exp);
            },
            getWrapShape: function() {
                return this.wrap;
            },
            getExpression: function() {
                return this.exp;
            },
            getBackground: function() {
                return this.bg;
            },
            resize: function() {
                var padding = this.config.padding, expBox = this.exp.getFixRenderBox();
                if (padding.length === 1) {
                    padding[1] = padding[0];
                }
                this.bg.setSize(padding[1] * 2 + expBox.width, padding[0] * 2 + expBox.height);
                this.exp.translate(padding[1], padding[0]);
            }
        }), Formula = kity.createClass("Formula", {
            base: _p.r(32),
            constructor: function(container, config) {
                this.callBase(container);
                this.expressions = [];
                this.fontInstaller = new FontInstaller(this);
                this.config = kity.Utils.extend({}, DEFAULT_OPTIONS, config);
                this.initEnvironment();
                this.initInnerFont();
            },
            getContentContainer: function() {
                return this.container;
            },
            initEnvironment: function() {
                this.zoom = this.config.fontsize / 50;
                if ("width" in this.config) {
                    this.setWidth(this.config.width);
                }
                if ("height" in this.config) {
                    this.setHeight(this.config.height);
                }
                this.node.setAttribute("font-size", DEFAULT_OPTIONS.fontsize);
            },
            initInnerFont: function() {
                var fontList = FontManager.getFontList(), _self = this;
                kity.Utils.each(fontList, function(fontInfo) {
                    createFontStyle(fontInfo);
                });
                function createFontStyle(fontInfo) {
                    var stylesheet = _self.doc.createElement("style"), tpl = '@font-face{font-family: "${fontFamily}";font-style: normal;src: url("${src}") format("woff");}';
                    stylesheet.setAttribute("type", "text/css");
                    stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
                    _self.resourceNode.appendChild(stylesheet);
                }
            },
            insertExpression: function(expression, index) {
                var expWrap = this.wrap(expression);
                // clear zoom
                this.container.clearTransform();
                this.expressions.splice(index, 0, expWrap.getWrapShape());
                this.addShape(expWrap.getWrapShape());
                notifyExpression.call(this, expWrap.getExpression());
                expWrap.resize();
                correctOffset.call(this);
                this.resetZoom();
                this.config.autoresize && this.resize();
            },
            appendExpression: function(expression) {
                this.insertExpression(expression, this.expressions.length);
            },
            resize: function() {
                var renderBox = this.container.getRenderBox("paper");
                this.node.setAttribute("width", renderBox.width);
                this.node.setAttribute("height", renderBox.height);
            },
            resetZoom: function() {
                var zoomLevel = this.zoom / this.getBaseZoom();
                if (zoomLevel !== 0) {
                    this.container.scale(zoomLevel);
                }
            },
            wrap: function(exp) {
                return new ExpressionWrap(exp, this.config);
            },
            clear: function() {
                this.callBase();
                this.expressions = [];
            },
            clearExpressions: function() {
                kity.Utils.each(this.expressions, function(exp) {
                    exp.remove();
                });
                this.expressions = [];
            },
            toJPG: function(cb) {
                new Output(this).toJPG(cb);
            },
            toPNG: function(cb) {
                new Output(this).toPNG(cb);
            }
        });
        kity.Utils.extend(Formula, {
            registerFont: function(fontData) {
                FontManager.registerFont(fontData);
            }
        });
        // 调整表达式之间的偏移
        function correctOffset() {
            var exprOffset = 0;
            kity.Utils.each(this.expressions, function(expr) {
                var box = null;
                if (!expr) {
                    return;
                }
                expr.setMatrix(new kity.Matrix(1, 0, 0, 1, 0, 0));
                box = expr.getFixRenderBox();
                expr.translate(0 - box.x, exprOffset);
                exprOffset += box.height + EXPRESSION_INTERVAL;
            });
            return this;
        }
        // 通知表达式已接入到paper
        function notifyExpression(expression) {
            var len = 0;
            if (!expression) {
                return;
            }
            if (expression.getType() === GTYPE.EXP) {
                for (var i = 0, len = expression.getChildren().length; i < len; i++) {
                    notifyExpression(expression.getChild(i));
                }
            } else if (expression.getType() === GTYPE.COMPOUND_EXP) {
                // 操作数处理
                for (var i = 0, len = expression.getOperands().length; i < len; i++) {
                    notifyExpression(expression.getOperand(i));
                }
                // 处理操作符
                notifyExpression(expression.getOperator());
            }
            expression.addedCall && expression.addedCall();
        }
        return Formula;
    }
};

/**
 * 公式专用paper
 */
_p[32] = {
    value: function(require) {
        var kity = _p.r(34);
        return kity.createClass("FPaper", {
            base: kity.Paper,
            constructor: function(container) {
                this.callBase(container);
                this.doc = container.ownerDocument;
                this.container = new kity.Group();
                this.container.setAttr("data-type", "kf-container");
                this.background = new kity.Group();
                this.background.setAttr("data-type", "kf-bg");
                this.baseZoom = 1;
                this.zoom = 1;
                this.base("addShape", this.background);
                this.base("addShape", this.container);
            },
            getZoom: function() {
                return this.zoom;
            },
            getBaseZoom: function() {
                return this.baseZoom;
            },
            addShape: function(shape, pos) {
                return this.container.addShape(shape, pos);
            },
            getBackground: function() {
                return this.background;
            },
            removeShape: function(pos) {
                return this.container.removeShape(pos);
            },
            clear: function() {
                return this.container.clear();
            }
        });
    }
};

/**
 * jquery
 */
_p[33] = {
    value: function() {
        if (!window.jQuery) {
            throw new Error("Missing jQuery");
        }
        return window.jQuery;
    }
};

/**
 * kity库封包
 */
_p[34] = {
    value: function() {
        if (!window.kity) {
            throw new Error("Missing Kity Graphic Lib");
        }
        return window.kity;
    }
};

/**
 * 小括号操作符:()
 */
_p[35] = {
    value: function(require) {
        var kity = _p.r(34), Text = _p.r(5);
        return kity.createClass("BracketsOperator", {
            base: _p.r(41),
            constructor: function() {
                this.callBase("Brackets");
            },
            applyOperand: function(exp) {
                generate.call(this, exp);
            }
        });
        function generate(exp) {
            var left = this.getParentExpression().getLeftSymbol(), right = this.getParentExpression().getRightSymbol(), fontSize = exp.getFixRenderBox().height, group = new kity.Group(), offset = 0, leftOp = new Text(left, "KF AMS MAIN").fill("black"), rightOp = new Text(right, "KF AMS MAIN").fill("black");
            leftOp.setFontSize(fontSize);
            rightOp.setFontSize(fontSize);
            this.addOperatorShape(group.addShape(leftOp).addShape(rightOp));
            offset += leftOp.getFixRenderBox().width;
            exp.translate(offset, 0);
            offset += exp.getFixRenderBox().width;
            rightOp.translate(offset, 0);
        }
    }
};

/**
 * 组合操作符
 * 操作多个表达式组合在一起
 */
_p[36] = {
    value: function(require) {
        var kity = _p.r(34);
        return kity.createClass("CombinationOperator", {
            base: _p.r(41),
            constructor: function() {
                this.callBase("Combination");
            },
            applyOperand: function() {
                // 偏移量
                var offsetX = 0, // 操作数
                operands = arguments, // 操作对象最大高度
                maxHeight = 0, // 垂直距离最大偏移
                maxOffsetTop = 0, maxOffsetBottom = 0, cached = [], // 偏移集合
                offsets = [];
                kity.Utils.each(operands, function(operand) {
                    var box = operand.getFixRenderBox(), offsetY = operand.getOffset();
                    box.height -= offsetY.top + offsetY.bottom;
                    cached.push(box);
                    offsets.push(offsetY);
                    maxOffsetTop = Math.max(offsetY.top, maxOffsetTop);
                    maxOffsetBottom = Math.max(offsetY.bottom, maxOffsetBottom);
                    maxHeight = Math.max(box.height, maxHeight);
                });
                kity.Utils.each(operands, function(operand, index) {
                    var box = cached[index];
                    operand.translate(offsetX - box.x, (maxHeight - (box.y + box.height)) / 2 + maxOffsetBottom - offsets[index].bottom);
                    offsetX += box.width;
                });
                this.parentExpression.setOffset(maxOffsetTop, maxOffsetBottom);
                this.parentExpression.updateBoxSize();
            }
        });
    }
};

/*!
 * 上下标控制器
 */
_p[37] = {
    value: function(require) {
        var kity = _p.r(34), EmptyExpression = _p.r(20), defaultOptions = {
            subOffset: 0,
            supOffset: 0,
            // 上下标的默认缩放值
            zoom: .66
        };
        return kity.createClass("ScriptController", {
            constructor: function(opObj, target, sup, sub, options) {
                this.observer = opObj.getParentExpression();
                this.target = target;
                this.sup = sup;
                this.sub = sub;
                this.options = kity.Utils.extend({}, defaultOptions, options);
            },
            // 上下标记
            applyUpDown: function() {
                var target = this.target, sup = this.sup, sub = this.sub, options = this.options;
                sup.scale(options.zoom);
                sub.scale(options.zoom);
                var targetBox = target.getFixRenderBox();
                if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
                    return {
                        width: targetBox.width,
                        height: targetBox.height,
                        top: 0,
                        bottom: 0
                    };
                } else {
                    // 上标
                    if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
                        return this.applyUp(target, sup);
                    } else if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
                        return this.applyDown(target, sub);
                    } else {
                        return this.applyUpDownScript(target, sup, sub);
                    }
                }
            },
            /**
         * 返回应用上下标后的空间占用情况,其中的key各自的意义是:
         * top: 上空间偏移
         * bottom: 下空间偏移
         * width: 当前整个图形的实际占用空间的width
         * height: 当前整个图形的实际占用空间的height
         * @returns {*}
         */
            applySide: function() {
                var target = this.target, sup = this.sup, sub = this.sub;
                if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
                    var targetRectBox = target.getRenderBox(this.observer);
                    return {
                        width: targetRectBox.width,
                        height: targetRectBox.height,
                        top: 0,
                        bottom: 0
                    };
                } else {
                    // 下标处理
                    if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
                        return this.applySideSub(target, sub);
                    } else if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
                        return this.applySideSuper(target, sup);
                    } else {
                        return this.applySideScript(target, sup, sub);
                    }
                }
            },
            applySideSuper: function(target, sup) {
                sup.scale(this.options.zoom);
                var targetRectBox = target.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), supBaseline = sup.getBaseline(this.observer), positionline = targetMeanline, diff = supBaseline - positionline, space = {
                    top: 0,
                    bottom: 0,
                    width: targetRectBox.width + supRectBox.width,
                    height: targetRectBox.height
                };
                sup.translate(targetRectBox.width, 0);
                if (this.options.supOffset) {
                    sup.translate(this.options.supOffset, 0);
                }
                if (diff > 0) {
                    target.translate(0, diff);
                    space.bottom = diff;
                    space.height += diff;
                } else {
                    sup.translate(0, -diff);
                }
                return space;
            },
            applySideSub: function(target, sub) {
                sub.scale(this.options.zoom);
                var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), subOffset = sub.getOffset(), targetBaseline = target.getBaseline(this.observer), // 下标定位线
                subPosition = (subRectBox.height + subOffset.top + subOffset.bottom) / 2, diff = targetRectBox.height - targetBaseline - subPosition, space = {
                    top: 0,
                    bottom: 0,
                    width: targetRectBox.width + subRectBox.width,
                    height: targetRectBox.height
                };
                // 定位下标位置
                sub.translate(targetRectBox.width, subOffset.top + targetBaseline - subPosition);
                if (this.options.subOffset) {
                    sub.translate(this.options.subOffset, 0);
                }
                if (diff < 0) {
                    space.top = -diff;
                    space.height -= diff;
                }
                return space;
            },
            applySideScript: function(target, sup, sub) {
                sup.scale(this.options.zoom);
                sub.scale(this.options.zoom);
                var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), targetBaseline = target.getBaseline(this.observer), supBaseline = sup.getBaseline(this.observer), // 上下标都存在时, 下标的定位以上伸线为准
                subAscenderline = sub.getAscenderline(this.observer), supPosition = targetMeanline, subPosition = targetMeanline + (targetBaseline - targetMeanline) * 2 / 3, topDiff = supPosition - supBaseline, bottomDiff = targetRectBox.height - subPosition - (subRectBox.height - subAscenderline), space = {
                    top: 0,
                    bottom: 0,
                    width: targetRectBox.width + Math.max(subRectBox.width, supRectBox.width),
                    height: targetRectBox.height
                };
                sup.translate(targetRectBox.width, topDiff);
                sub.translate(targetRectBox.width, subPosition - subAscenderline);
                if (this.options.supOffset) {
                    sup.translate(this.options.supOffset, 0);
                }
                if (this.options.subOffset) {
                    sub.translate(this.options.subOffset, 0);
                }
                // 定位纠正
                if (topDiff > 0) {
                    if (bottomDiff < 0) {
                        targetRectBox.height -= bottomDiff;
                        space.top = -bottomDiff;
                    }
                } else {
                    target.translate(0, -topDiff);
                    sup.translate(0, -topDiff);
                    sub.translate(0, -topDiff);
                    space.height -= topDiff;
                    if (bottomDiff > 0) {
                        space.bottom = -topDiff;
                    } else {
                        space.height -= bottomDiff;
                        // 比较上下偏移, 获取正确的偏移值
                        topDiff = -topDiff;
                        bottomDiff = -bottomDiff;
                        if (topDiff > bottomDiff) {
                            space.bottom = topDiff - bottomDiff;
                        } else {
                            space.top = bottomDiff - topDiff;
                        }
                    }
                }
                return space;
            },
            applyUp: function(target, sup) {
                var supBox = sup.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
                    width: Math.max(targetBox.width, supBox.width),
                    height: supBox.height + targetBox.height,
                    top: 0,
                    bottom: supBox.height
                };
                sup.translate((space.width - supBox.width) / 2, 0);
                target.translate((space.width - targetBox.width) / 2, supBox.height);
                return space;
            },
            applyDown: function(target, sub) {
                var subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
                    width: Math.max(targetBox.width, subBox.width),
                    height: subBox.height + targetBox.height,
                    top: subBox.height,
                    bottom: 0
                };
                sub.translate((space.width - subBox.width) / 2, targetBox.height);
                target.translate((space.width - targetBox.width) / 2, 0);
                return space;
            },
            applyUpDownScript: function(target, sup, sub) {
                var supBox = sup.getFixRenderBox(), subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
                    width: Math.max(targetBox.width, supBox.width, subBox.width),
                    height: supBox.height + subBox.height + targetBox.height,
                    top: 0,
                    bottom: 0
                };
                sup.translate((space.width - supBox.width) / 2, 0);
                target.translate((space.width - targetBox.width) / 2, supBox.height);
                sub.translate((space.width - subBox.width) / 2, supBox.height + targetBox.height);
                return space;
            }
        });
    }
};

/**
 * 分数操作符
 */
_p[38] = {
    value: function(require) {
        var kity = _p.r(34), ZOOM = _p.r(47).zoom;
        return kity.createClass("FractionOperator", {
            base: _p.r(41),
            constructor: function() {
                this.callBase("Fraction");
            },
            applyOperand: function(upOperand, downOperand) {
                upOperand.scale(ZOOM);
                downOperand.scale(ZOOM);
                var upWidth = Math.ceil(upOperand.getWidth()), downWidth = Math.ceil(downOperand.getWidth()), upHeight = Math.ceil(upOperand.getHeight()), downHeight = Math.ceil(downOperand.getHeight()), // 分数线overflow值
                overflow = 3, // 整体padding
                padding = 1, maxWidth = Math.max(upWidth, downWidth), maxHeight = Math.max(upHeight, downHeight), operatorShape = generateOperator(maxWidth, overflow);
                this.addOperatorShape(operatorShape);
                upOperand.translate((maxWidth - upWidth) / 2 + overflow, 0);
                operatorShape.translate(0, upHeight + 1);
                // 下部不需要偏移
                downOperand.translate((maxWidth - downWidth) / 2 + overflow, upHeight + operatorShape.getHeight() + 1 * 2);
                this.parentExpression.setOffset(maxHeight - upHeight, maxHeight - downHeight);
                this.parentExpression.expand(padding * 2, padding * 2);
                this.parentExpression.translateElement(padding, padding);
            }
        });
        function generateOperator(width, overflow) {
            return new kity.Rect(width + overflow * 2, 1).fill("black");
        }
    }
};

/**
 * 函数操作符
 */
_p[39] = {
    value: function(require) {
        var kity = _p.r(34), Text = _p.r(5), ScriptController = _p.r(37);
        return kity.createClass("FunctionOperator", {
            base: _p.r(41),
            constructor: function(funcName) {
                this.callBase("Function: " + funcName);
                this.funcName = funcName;
            },
            /*
         * 积分操作符应用操作数
         * @param expr 函数表达式
         * @param sup 上限
         * @param sub 下限
         */
            applyOperand: function(expr, sup, sub) {
                var opShape = generateOperator.call(this), expBox = expr.getFixRenderBox(), scriptHanlder = this.parentExpression.isSideScript() ? "applySide" : "applyUpDown", space = new ScriptController(this, opShape, sup, sub, {
                    zoom: .5
                })[scriptHanlder](), padding = 5, diff = (space.height + space.top + space.bottom - expBox.height) / 2;
                // 应用偏移, 使图形在正确的位置上
                opShape.translate(0, space.top);
                sup.translate(0, space.top);
                sub.translate(0, space.top);
                if (diff >= 0) {
                    expr.translate(space.width + padding, diff);
                } else {
                    diff = -diff;
                    opShape.translate(0, diff);
                    sup.translate(0, diff);
                    sub.translate(0, diff);
                    expr.translate(space.width + padding, 0);
                }
                // 只扩展左边, 不扩展右边, 所以padding不 *2
                this.parentExpression.expand(padding, padding * 2);
                this.parentExpression.translateElement(padding, padding);
            }
        });
        /* 返回操作符对象 */
        function generateOperator() {
            var opShape = new Text(this.funcName, "KF AMS ROMAN");
            this.addOperatorShape(opShape);
            // 为操作符图形创建baseline和meanline方法
            opShape.getBaseline = function() {
                return opShape.getFixRenderBox().height;
            };
            opShape.getMeanline = function() {
                return 0;
            };
            return opShape;
        }
    }
};

/**
 * 积分操作符:∫
 */
_p[40] = {
    value: function(require) {
        var kity = _p.r(34), ScriptController = _p.r(37);
        return kity.createClass("IntegrationOperator", {
            base: _p.r(41),
            constructor: function(type) {
                this.callBase("Integration");
                // 默认是普通单重积分
                this.opType = type || 1;
            },
            setType: function(type) {
                this.opType = type | 0;
            },
            // 重置类型
            resetType: function() {
                this.opType = 1;
            },
            applyOperand: function(exp, sup, sub) {
                var opShape = this.getOperatorShape(), padding = 3, expBox = exp.getFixRenderBox(), space = new ScriptController(this, opShape, sup, sub, {
                    supOffset: 3,
                    subOffset: -15
                }).applySide(), diff = (space.height + space.top - expBox.height) / 2;
                opShape.translate(0, space.top);
                sup.translate(0, space.top);
                sub.translate(0, space.top);
                if (diff >= 0) {
                    exp.translate(space.width + padding, diff);
                } else {
                    diff = -diff;
                    opShape.translate(0, diff);
                    sup.translate(0, diff);
                    sub.translate(0, diff);
                    exp.translate(space.width + padding, 0);
                }
                this.parentExpression.expand(padding, padding * 2);
                this.parentExpression.translateElement(padding, padding);
            },
            getOperatorShape: function() {
                var pathData = "M1.318,48.226c0,0,0.044,0.066,0.134,0.134c0.292,0.313,0.626,0.447,1.006,0.447c0.246,0.022,0.358-0.044,0.604-0.268   c0.782-0.782,1.497-2.838,2.324-6.727c0.514-2.369,0.938-4.693,1.586-8.448C8.559,24.068,9.9,17.878,11.978,9.52   c0.917-3.553,1.922-7.576,3.866-8.983C16.247,0.246,16.739,0,17.274,0c1.564,0,2.503,1.162,2.592,2.57   c0,0.827-0.424,1.386-1.273,1.386c-0.671,0-1.229-0.514-1.229-1.251c0-0.805,0.514-1.095,1.185-1.274   c0.022,0-0.291-0.29-0.425-0.379c-0.201-0.134-0.514-0.224-0.737-0.224c-0.067,0-0.112,0-0.157,0.022   c-0.469,0.134-0.983,0.939-1.453,2.234c-0.537,1.475-0.961,3.174-1.631,6.548c-0.424,2.101-0.693,3.464-1.229,6.727   c-1.608,9.185-2.949,15.487-5.006,23.756c-0.514,2.034-0.849,3.24-1.207,4.335c-0.559,1.698-1.162,2.95-1.811,3.799   c-0.514,0.715-1.385,1.408-2.436,1.408c-1.363,0-2.391-1.185-2.458-2.592c0-0.804,0.447-1.363,1.273-1.363   c0.671,0,1.229,0.514,1.229,1.251C2.503,47.757,1.989,48.047,1.318,48.226z", group = new kity.Group(), opGroup = new kity.Group(), opShape = new kity.Path(pathData).fill("black"), opBox = new kity.Rect(0, 0, 0, 0).fill("transparent"), tmpShape = null;
                opGroup.addShape(opShape);
                group.addShape(opBox);
                group.addShape(opGroup);
                this.addOperatorShape(group);
                for (var i = 1; i < this.opType; i++) {
                    tmpShape = new kity.Use(opShape).translate(opShape.getWidth() / 2 * i, 0);
                    opGroup.addShape(tmpShape);
                }
                opGroup.scale(1.6);
                tmpShape = null;
                // 为操作符图形创建baseline和meanline方法
                group.getBaseline = function() {
                    return opGroup.getFixRenderBox().height;
                };
                group.getMeanline = function() {
                    return 10;
                };
                return group;
            }
        });
    }
};

/**
 * 操作符抽象类
 * @abstract
 */
_p[41] = {
    value: function(require) {
        var kity = _p.r(34), GTYPE = _p.r(6);
        return kity.createClass("Operator", {
            base: _p.r(46),
            constructor: function(operatorName) {
                this.callBase();
                this.type = GTYPE.OP;
                // 该操作符所属的表达式
                this.parentExpression = null;
                // 操作符名称
                this.operatorName = operatorName;
                // 操作符图形
                this.operatorShape = new kity.Group();
                this.addShape(this.operatorShape);
            },
            applyOperand: function() {
                throw new Error("applyOperand is abstract");
            },
            setParentExpression: function(exp) {
                this.parentExpression = exp;
            },
            getParentExpression: function() {
                return this.parentExpression;
            },
            clearParentExpression: function() {
                this.parentExpression = null;
            },
            // 提供给具体实现类附加其绘制的操作符图形的接口
            addOperatorShape: function(shpae) {
                return this.operatorShape.addShape(shpae);
            },
            getOperatorShape: function() {
                return this.operatorShape;
            }
        });
    }
};

/**
 * 开方操作符
 */
_p[42] = {
    value: function(require) {
        var kity = _p.r(34), // 符号图形属性
        // 线条宽度
        SHAPE_DATA_WIDTH = 1, // 计算公式
        radians = 2 * Math.PI / 360, sin15 = Math.sin(15 * radians), cos15 = Math.cos(15 * radians), tan15 = Math.tan(15 * radians);
        return kity.createClass("RadicalOperator", {
            base: _p.r(41),
            constructor: function() {
                this.callBase("Radical");
            },
            applyOperand: function(radicand, exponent) {
                generateOperator.call(this, radicand, exponent);
            }
        });
        // 根据给定的操作数生成操作符的pathData
        // radicand 表示被开方数
        // exponent 表示指数
        function generateOperator(radicand, exponent) {
            var decoration = generateDecoration(radicand), vLine = generateVLine(radicand), padding = 5, hLine = generateHLine(radicand);
            this.addOperatorShape(decoration);
            this.addOperatorShape(vLine);
            this.addOperatorShape(hLine);
            adjustmentPosition.call(this, mergeShape(decoration, vLine, hLine), this.operatorShape, radicand, exponent);
            this.parentExpression.expand(0, padding * 2);
            this.parentExpression.translateElement(0, padding);
        }
        // 生成根号中的左边装饰部分
        function generateDecoration(radicand) {
            var shape = new kity.Path(), // 命名为a以便于精简表达式
            a = SHAPE_DATA_WIDTH, h = radicand.getHeight() / 3, drawer = shape.getDrawer();
            // 根号尾部左上角开始
            drawer.moveTo(0, cos15 * a * 6);
            drawer.lineBy(sin15 * a, cos15 * a);
            drawer.lineBy(cos15 * a * 3, -sin15 * a * 3);
            drawer.lineBy(tan15 * h, h);
            drawer.lineBy(sin15 * a * 3, -cos15 * a * 3);
            drawer.lineBy(-sin15 * h, -h);
            drawer.close();
            return shape.fill("black");
        }
        // 根据操作数生成根号的竖直线部分
        function generateVLine(operand) {
            var shape = new kity.Path(), // * 0.9 是为了在视觉上使斜线部分不至于太高
            h = operand.getHeight() * .9, drawer = shape.getDrawer();
            drawer.moveTo(tan15 * h, 0);
            drawer.lineTo(0, h);
            drawer.lineBy(sin15 * SHAPE_DATA_WIDTH * 3, cos15 * SHAPE_DATA_WIDTH * 3);
            drawer.lineBy(tan15 * h + sin15 * SHAPE_DATA_WIDTH * 3, -(h + 3 * SHAPE_DATA_WIDTH * cos15));
            drawer.close();
            return shape.fill("black");
        }
        // 根据操作数生成根号的水平线部分
        function generateHLine(operand) {
            // 表达式宽度
            var w = operand.getWidth() + 2 * SHAPE_DATA_WIDTH;
            return new kity.Rect(w, 2 * SHAPE_DATA_WIDTH).fill("black");
        }
        // 合并根号的各个部分, 并返回根号的关键点位置数据
        function mergeShape(decoration, vLine, hLine) {
            var decoBox = decoration.getFixRenderBox(), vLineBox = vLine.getFixRenderBox();
            vLine.translate(decoBox.width - sin15 * SHAPE_DATA_WIDTH * 3, 0);
            decoration.translate(0, vLineBox.height - decoBox.height);
            vLineBox = vLine.getFixRenderBox();
            hLine.translate(vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, 0);
            // 返回关键点数据
            return {
                x: vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15,
                y: 0
            };
        }
        // 调整整个根号表达式的各个部分: 位置、操作符、被开方数、指数
        function adjustmentPosition(position, operator, radicand, exponent) {
            var exponentBox = null, opOffset = {
                x: 0,
                y: 0
            }, opBox = operator.getFixRenderBox();
            exponent.scale(.66);
            exponentBox = exponent.getFixRenderBox();
            if (exponentBox.width > 0 && exponentBox.height > 0) {
                opOffset.y = exponentBox.height - opBox.height / 2;
                // 指数不超出根号, 则移动指数
                if (opOffset.y < 0) {
                    exponent.translate(0, -opOffset.y);
                    opOffset.y = 0;
                }
                opOffset.x = exponentBox.width + opBox.height / 2 * tan15 - position.x;
            }
            operator.translate(opOffset.x, opOffset.y);
            radicand.translate(opOffset.x + position.x + SHAPE_DATA_WIDTH, opOffset.y + 2 * SHAPE_DATA_WIDTH);
        }
    }
};

/**
 * 上下标操作符
 */
_p[43] = {
    value: function(require) {
        var kity = _p.r(34), ScriptController = _p.r(37);
        return kity.createClass("ScriptOperator", {
            base: _p.r(41),
            constructor: function(operatorName) {
                this.callBase(operatorName || "Script");
            },
            applyOperand: function(operand, sup, sub) {
                var padding = 1, parent = this.parentExpression, space = new ScriptController(this, operand, sup, sub).applySide();
                this.getOperatorShape();
                space && parent.setOffset(space.top, space.bottom);
                parent.expand(4, padding * 2);
                parent.translateElement(2, padding);
            }
        });
    }
};

/**
 * 求和操作符:∑
 */
_p[44] = {
    value: function(require) {
        var kity = _p.r(34), ScriptController = _p.r(37);
        return kity.createClass("SummationOperator", {
            base: _p.r(41),
            constructor: function() {
                this.callBase("Summation");
                this.displayType = "equation";
            },
            applyOperand: function(expr, sup, sub) {
                var opShape = this.getOperatorShape(), expBox = expr.getFixRenderBox(), padding = 0, space = new ScriptController(this, opShape, sup, sub).applyUpDown(), diff = (space.height - space.top - space.bottom - expBox.height) / 2;
                if (diff >= 0) {
                    expr.translate(space.width + padding, diff + space.bottom);
                } else {
                    diff = -diff;
                    opShape.translate(0, diff);
                    sup.translate(0, diff);
                    sub.translate(0, diff);
                    expr.translate(space.width + padding, space.bottom);
                }
                this.parentExpression.setOffset(space.top, space.bottom);
                this.parentExpression.expand(padding, padding * 2);
                this.parentExpression.translateElement(padding, padding);
            },
            getOperatorShape: function() {
                var pathData = "M0.672,33.603c-0.432,0-0.648,0-0.648-0.264c0-0.024,0-0.144,0.24-0.432l12.433-14.569L0,0.96c0-0.264,0-0.72,0.024-0.792   C0.096,0.024,0.12,0,0.672,0h28.371l2.904,6.745h-0.6C30.531,4.8,28.898,3.72,28.298,3.336c-1.896-1.2-3.984-1.608-5.28-1.8   c-0.216-0.048-2.4-0.384-5.617-0.384H4.248l11.185,15.289c0.168,0.24,0.168,0.312,0.168,0.36c0,0.12-0.048,0.192-0.216,0.384   L3.168,31.515h14.474c4.608,0,6.96-0.624,7.464-0.744c2.76-0.72,5.305-2.352,6.241-4.848h0.6l-2.904,7.681H0.672z", operatorShape = new kity.Path(pathData).fill("black"), opBgShape = new kity.Rect(0, 0, 0, 0).fill("transparent"), group = new kity.Group(), opRenderBox = null;
                group.addShape(opBgShape);
                group.addShape(operatorShape);
                operatorShape.scale(1.6);
                this.addOperatorShape(group);
                opRenderBox = operatorShape.getFixRenderBox();
                if (this.displayType === "inline") {
                    operatorShape.translate(5, 15);
                    opBgShape.setSize(opRenderBox.width + 10, opRenderBox.height + 25);
                } else {
                    operatorShape.translate(2, 5);
                    opBgShape.setSize(opRenderBox.width + 4, opRenderBox.height + 8);
                }
                return group;
            }
        });
    }
};

/*!
 * 资源管理器
 * 负责管理资源的加载,并在资源ready之后提供Formula构造器
 */
_p[45] = {
    value: function(require) {
        var kity = _p.r(34), cbList = [], RES_CONF = _p.r(47).resource, FontInstall = _p.r(24), Formula = _p.r(31), // 资源管理器就绪状态
        __readyState = false, // 资源管理器是否已启动
        inited = false;
        return {
            // 初始化
            ready: function(cb, options) {
                if (!inited) {
                    inited = true;
                    init(options);
                }
                if (__readyState) {
                    window.setTimeout(function() {
                        cb(Formula);
                    }, 0);
                } else {
                    cbList.push(cb);
                }
            }
        };
        /**
     * 资源初始化
     */
        function init(options) {
            options = kity.Utils.extend({}, RES_CONF, options);
            if (!/^(https?:)?\/\//.test(options.path)) {
                options.path = getFullPath(options.path);
            }
            new FontInstall(document, options.path).mount(complete);
        }
        function complete() {
            kity.Utils.each(cbList, function(cb) {
                cb(Formula);
            });
        }
        function getFullPath(path) {
            var pathname = location.pathname.split("/"), pathPart;
            pathname.length -= 1;
            pathname = pathname.join("/") + "/";
            pathPart = [ location.protocol, "//", location.host, pathname, path.replace(/^\//, "") ];
            return pathPart.join("");
        }
    }
};

/*!
 * 所有符号的基类
 * @abstract
 */
_p[46] = {
    value: function(require) {
        var kity = _p.r(34), GTYPE = _p.r(6);
        return kity.createClass("SignGroup", {
            base: kity.Group,
            constructor: function() {
                this.callBase();
                this.box = new kity.Rect(0, 0, 0, 0);
                this.type = GTYPE.UNKNOWN;
                this.addShape(this.box);
                this.zoom = 1;
            },
            setZoom: function(zoom) {
                this.zoom = zoom;
            },
            getZoom: function() {
                return this.zoom;
            },
            setBoxSize: function(w, h) {
                return this.box.setSize(w, h);
            },
            setBoxWidth: function(w) {
                return this.box.setWidth(w);
            },
            setBoxHeight: function(h) {
                return this.box.setHeight(h);
            },
            getType: function() {
                return this.type;
            },
            getBaseHeight: function() {
                return this.getHeight();
            },
            getBaseWidth: function() {
                return this.getWidth();
            },
            addedCall: function() {}
        });
    }
};

/*!
 * 系统项目配置文件.
 */
_p[47] = {
    value: function(require) {
        return {
            zoom: .66,
            font: {
                meanline: Math.round(380 / 1e3 * 50),
                baseline: Math.round(800 / 1e3 * 50),
                baseHeight: 50,
                // 系统字体列表
                list: [ _p.r(29), _p.r(27), _p.r(28), _p.r(26), _p.r(30) ]
            },
            /*------------------------- 资源配置*/
            resource: {
                path: "src/resource/"
            },
            // 函数相关配置
            func: {
                // 上下标在函数名上下两侧的函数列表
                "ud-script": {
                    lim: true
                }
            }
        };
    }
};

/*!
 * 启动代码
 */
_p[48] = {
    value: function(require) {
        window.kf = {
            // base
            ResourceManager: _p.r(45),
            Operator: _p.r(41),
            // expression
            Expression: _p.r(21),
            CompoundExpression: _p.r(19),
            TextExpression: _p.r(22),
            EmptyExpression: _p.r(20),
            CombinationExpression: _p.r(12),
            FunctionExpression: _p.r(14),
            FractionExpression: _p.r(13),
            IntegrationExpression: _p.r(15),
            RadicalExpression: _p.r(16),
            ScriptExpression: _p.r(17),
            SuperscriptExpression: _p.r(9),
            SubscriptExpression: _p.r(8),
            SummationExpression: _p.r(18),
            // Brackets expressoin
            BracketsExpression: _p.r(11)
        };
    }
};

var moduleMapping = {
    "kf.start": 48
};

function use(name) {
    _p.r([ moduleMapping[name] ]);
}
/**
 * 模块暴露
 */

( function ( global ) {

    var oldGetRenderBox = kity.Shape.getRenderBox;

    kity.extendClass(kity.Shape, {
        getFixRenderBox: function () {
            return this.getRenderBox( this.container.container );
        },

        getTranslate: function () {
            return this.transform.translate;
        }
    });

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

} )( this );
})();
kityformula-editor.all.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/tinymce/plugins/kitymath/kityformula/js/kityformula-editor.all.min.js'
View Content
/*!
 * ====================================================
 * Kity Formula Editor - v1.0.0 - 2014-09-03
 * https://github.com/kitygraph/formula
 * GitHub: https://github.com/kitygraph/formula.git 
 * Copyright (c) 2014 Baidu Kity Group; Licensed MIT
 * ====================================================
 */
!function(){function a(a){b.r([c[a]])}var b={r:function(a){if(b[a].inited)return b[a].value;if("function"!=typeof b[a].value)return b[a].inited=!0,b[a].value;var c={exports:{}},d=b[a].value(null,c.exports,c);if(b[a].inited=!0,b[a].value=d,void 0!==d)return d;for(var e in c.exports)if(c.exports.hasOwnProperty(e))return b[a].inited=!0,b[a].value=c.exports,c.exports}};b[0]={value:function(){function a(d,e,f,g){return g=0|g,g>b?f:(g++,c.each(f,function(b,f){d?!b||"object"!=typeof b&&"function"!=typeof b?e[f]=b:(e[f]=e[f]||(c.isArray(b)?[]:{}),e[f]=a(d,e[f],b,g)):e[f]=b}),e)}var b=10,c={extend:function(b,d){var e=!1;if("boolean"==typeof b?(e=b,b=d,d=[].splice.call(arguments,2)):d=[].splice.call(arguments,1),!b)throw new Error("Utils: extend, target can not be empty");return c.each(d,function(c){(c&&"object"==typeof c||"function"==typeof c)&&a(e,b,c)}),b},contains:function(a,b){return a.contains?a.contains(b):a.compareDocumentPosition?!!(16&a.compareDocumentPosition(b)):void 0},getRect:function(a){return a.getBoundingClientRect()},isArray:function(a){return a&&"[object Array]"==={}.toString.call(a)},isString:function(a){return"string"==typeof a},proxy:function(a,b){return function(){return a.apply(b,arguments)}},each:function(a,b){if(a)if("length"in a&&"number"==typeof a.length)for(var c=0,d=a.length;d>c&&b.call(null,a[c],c,a)!==!1;c++);else for(var e in a)if(a.hasOwnProperty(e)&&b.call(null,a[e],e,a)===!1)break}};return c}},b[1]={value:function(){var a=b.r(20);return a.createClass("Component",{constructor:function(){}})}},b[2]={value:function(){function a(){return++d}var c={},d=0,e=!0,f=b.r(3),g=b.r(0),h=function(a){var b=a.type,d=a.target,f=this.__kfe_eid,h=/^(?:before|after)/.test(b),j=c[f][b];return h||(i.trigger(d,"before"+b),e!==!1)?(g.each(j,function(b){return b&&b.call(d,a)===!1?e=!1:void 0}),void(h||i.trigger(d,"after"+b))):(e=!0,!1)},i={addEvent:function(b,d,e){var f=!0,g=null;b.__kfe_eid||(f=!1,b.__kfe_eid=a(),c[b.__kfe_eid]={}),g=c[b.__kfe_eid],g[d]||(f=!1,g[d]=[]),g[d].push(e),f||b.addEventListener(d,h,!1)},trigger:function(a,b,c){c=c||f.createEvent(b,c),a.dispatchEvent(c)}};return i}},b[3]={value:function(){return{createEvent:function(a){var b=document.createEvent("Event");return b.initEvent(a,!0,!0),b}}}},b[4]={value:function(){var a={},c=b.r(0);return c.extend(a,c,b.r(2)),a}},b[5]={value:function(){var a=b.r(20),c=b.r(8),d=a.createClass("ControllerComponent",{constructor:function(a){this.kfEditor=a,this.components={},this.initComponents()},initComponents:function(){this.components.listener=new c(this,this.kfEditor)}});return d}},b[6]={value:function(){var a={32:"\\,","s+219":"\\{","s+221":"\\}",220:"\\backslash","s+51":"\\#","s+52":"\\$","s+53":"\\%","s+54":"\\^","s+55":"\\&","s+189":"\\_","s+192":"\\~"};return{getReplaceString:function(b){return a[b]||null}}}},b[7]={value:function(){var a=b.r(20),c=b.r(4),d=b.r(6),e={LEFT:37,RIGHT:39,DELETE:8,INPUT:229};return a.createClass("InputComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.inputBox=this.createInputBox(),this.initServices(),this.initCommands(),this.initEvent()},initServices:function(){this.kfEditor.registerService("control.update.input",this,{updateInput:this.updateInput}),this.kfEditor.registerService("control.insert.string",this,{insertStr:this.insertStr})},initCommands:function(){this.kfEditor.registerCommand("focus",this,this.focus)},createInputBox:function(){var a=this.kfEditor.getContainer(),b=this.kfEditor.getDocument().createElement("input");return b.className="kf-editor-input-box",b.type="text",b.isTrusted=!1,a.appendChild(b),b},focus:function(){var a=null;this.inputBox.focus(),this.kfEditor.requestService("syntax.has.cursor.info")||(a=this.kfEditor.requestService("syntax.get.root.group.info"),this.kfEditor.requestService("syntax.update.record.cursor",{groupId:a.id,startOffset:0,endOffset:a.content.length}),this.kfEditor.requestService("control.update.input")),this.kfEditor.requestService("control.reselect")},setUntrusted:function(){this.inputBox.isTrusted=!1},setTrusted:function(){this.inputBox.isTrusted=!0},updateInput:function(){var a=this.kfEditor.requestService("syntax.serialization");this.setUntrusted(),this.inputBox.value=a.str,this.inputBox.selectionStart=a.startOffset,this.inputBox.selectionEnd=a.endOffset,this.inputBox.focus(),this.setTrusted()},insertStr:function(a){var b=this.kfEditor.requestService("syntax.serialization"),c=b.str;c=c.substring(0,b.startOffset)+" "+a+" "+c.substring(b.endOffset),this.restruct(c),this.updateInput(),this.kfEditor.requestService("ui.update.canvas.view")},initEvent:function(){var a=this;c.addEvent(this.inputBox,"keydown",function(b){var c=!1;if(b.ctrlKey)return void a.processUserCtrl(b);switch(b.keyCode){case e.INPUT:return;case e.LEFT:b.preventDefault(),a.leftMove(),c=!0;break;case e.RIGHT:b.preventDefault(),a.rightMove(),c=!0;break;case e.DELETE:b.preventDefault(),a.delete(),c=!0}c&&a.kfEditor.requestService("ui.update.canvas.view"),a.pretreatmentInput(b)||b.preventDefault()}),c.addEvent(this.inputBox,"input",function(){a.processingInput()}),c.addEvent(this.inputBox,"blur",function(){a.kfEditor.requestService("ui.toolbar.disable"),a.kfEditor.requestService("ui.toolbar.close"),a.kfEditor.requestService("control.cursor.hide"),a.kfEditor.requestService("render.clear.select")}),c.addEvent(this.inputBox,"focus",function(){a.kfEditor.requestService("ui.toolbar.enable"),this.isTrusted&&a.kfEditor.requestService("control.reselect")}),c.addEvent(this.inputBox,"paste",function(a){a.preventDefault()})},hasRootplaceholder:function(){return this.kfEditor.requestService("syntax.has.root.placeholder")},leftMove:function(){this.hasRootplaceholder()||(this.kfEditor.requestService("syntax.cursor.move.left"),this.update())},rightMove:function(){this.hasRootplaceholder()||(this.kfEditor.requestService("syntax.cursor.move.right"),this.update())},"delete":function(){var a=null;this.hasRootplaceholder()||(a=this.kfEditor.requestService("syntax.delete.group"),a?(this.updateInput(),this.processingInput()):(this.updateInput(),this.kfEditor.requestService("control.reselect")))},processUserCtrl:function(a){switch(a.preventDefault(),a.keyCode){case 65:this.kfEditor.requestService("control.select.all");break;case 83:this.kfEditor.requestService("print.image")}},pretreatmentInput:function(a){var b=this.getKeyCode(a),c=d.getReplaceString(b);return null===c?!0:(this.insertStr(c),!1)},getKeyCode:function(a){return(a.shiftKey?"s+":"")+a.keyCode},processingInput:function(){this.restruct(this.inputBox.value),this.kfEditor.requestService("ui.update.canvas.view")},restruct:function(a){this.kfEditor.requestService("render.draw",a),this.kfEditor.requestService("control.reselect")},update:function(){this.updateInput(),this.kfEditor.requestService("control.reselect")}})}},b[8]={value:function(){var a=b.r(20),c=b.r(9),d=b.r(7),e=b.r(10);return a.createClass("MoveComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.components={},this.initComponents()},initComponents:function(){this.components.location=new c(this,this.kfEditor),this.components.selection=new e(this,this.kfEditor),this.components.input=new d(this,this.kfEditor)}})}},b[9]={value:function(){function a(a){return a.getBoundingClientRect()}var c=b.r(20);return c.createClass("LocationComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.paper=this.getPaper(),this.cursorShape=this.createCursor(),this.initServices(),this.initEvent()},getPaper:function(){return this.kfEditor.requestService("render.get.paper")},initServices:function(){this.kfEditor.registerService("control.cursor.relocation",this,{relocationCursor:this.updateCursor}),this.kfEditor.registerService("control.cursor.hide",this,{hideCursor:this.hideCursor}),this.kfEditor.registerService("control.reselect",this,{reselect:this.reselect}),this.kfEditor.registerService("control.get.cursor.location",this,{getCursorLocation:this.getCursorLocation})},createCursor:function(){var a=new c.Rect(1,0,0,0).fill("black");return a.setAttr("style","display: none"),this.paper.addShape(a),a},initEvent:function(){var a=this.kfEditor.request("ui.canvas.container.event"),b=this;a.on("mousedown",function(a){a.preventDefault(),b.updateCursorInfo(a),b.kfEditor.requestService("control.update.input"),b.reselect()})},updateCursorInfo:function(a){var b=null,c=null,d=-1;return this.kfEditor.requestService("syntax.has.root.placeholder")?(this.kfEditor.requestService("syntax.update.record.cursor",{groupId:this.kfEditor.requestService("syntax.get.root.group.info").id,startOffset:0,endOffset:1}),!1):(b=this.kfEditor.requestService("position.get.wrap",a.target),b&&this.kfEditor.requestService("syntax.is.placeholder.node",b.id)?(c=this.kfEditor.requestService("position.get.group.info",b),void this.kfEditor.requestService("syntax.update.record.cursor",c.group.id,c.index,c.index+1)):(c=this.kfEditor.requestService("position.get.group",a.target),null===c&&(c=this.kfEditor.requestService("syntax.get.root.group.info")),d=this.getIndex(a.clientX,c),void this.kfEditor.requestService("syntax.update.record.cursor",c.id,d)))},hideCursor:function(){this.cursorShape.setAttr("style","display: none")},reselect:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=null;return this.hideCursor(),this.kfEditor.requestService("syntax.is.select.placeholder")?(b=this.kfEditor.requestService("syntax.get.group.content",a.groupId),void this.kfEditor.requestService("render.select.group",b.content[a.startOffset].id)):void(a.startOffset===a.endOffset?(this.updateCursor(),this.kfEditor.requestService("render.tint.current.cursor")):this.kfEditor.requestService("render.select.current.cursor"))},updateCursor:function(){var b=this.kfEditor.requestService("syntax.get.record.cursor");if(b.startOffset!==b.endOffset)return void this.hideCursor();var c=this.kfEditor.requestService("syntax.get.group.content",b.groupId),d=0===b.endOffset,e=d?0:b.endOffset-1,f=c.content[e],g=a(this.paper.container.node),h=0,i=a(f),j=this.cursorShape.getTransform(this.cursorShape),k=this.kfEditor.requestService("render.get.canvas.zoom"),l=this.paper.getZoom();this.cursorShape.setHeight(i.height/k/l),h=d?i.left-2:i.left+i.width-2,h-=g.left,j.m.e=Math.floor(h/k/l)+.5,j.m.f=(i.top-g.top)/k/l,this.cursorShape.setMatrix(j),this.cursorShape.setAttr("style","display: block")},getCursorLocation:function(){var a=this.cursorShape.getRenderBox("paper");return{x:a.x,y:a.y}},getIndex:function(b,c){for(var d=-1,e=c.content,f=null,g=e.length-1,h=null;g>=0;g--)if(d=g,h=e[g],f=a(h),f.left<b){f.left+f.width/2<b&&(d+=1);break}return d}})}},b[10]={value:function(){var a=b.r(20),c=b.r(4),d=10;return a.createClass("SelectionComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b,this.isDrag=!1,this.isMousedown=!1,this.startPoint={x:-1,y:-1},this.startGroupIsPlaceholder=!1,this.startGroup={},this.initServices(),this.initEvent()},initServices:function(){this.kfEditor.registerService("control.select.all",this,{selectAll:this.selectAll})},initEvent:function(){var a=this.kfEditor.request("ui.canvas.container.event"),b=this;a.on("mousedown",function(a){return a.preventDefault(),b.kfEditor.requestService("syntax.has.root.placeholder")?!1:(b.isMousedown=!0,b.updateStartPoint(a.clientX,a.clientY),void b.updateStartGroup())}),a.on("mouseup",function(a){a.preventDefault(),b.stopUpdateSelection()}),a.on("mousemove",function(a){if(a.preventDefault(),b.isDrag){if(1!==a.which)return void b.stopUpdateSelection();b.updateSelection(a.target,a.clientX,a.clientY)}else b.isMousedown&&d<b.getDistance(a.clientX,a.clientY)&&(b.kfEditor.requestService("control.cursor.hide"),b.startUpdateSelection())}),a.on("dblclick",function(a){b.updateSelectionByTarget(a.target)})},getDistance:function(a,b){var c=Math.abs(a-this.startPoint.x),d=Math.abs(b-this.startPoint.y);return Math.max(c,d)},updateStartPoint:function(a,b){this.startPoint.x=a,this.startPoint.y=b},updateStartGroup:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor");this.startGroupIsPlaceholder=this.kfEditor.requestService("syntax.is.select.placeholder"),this.startGroup={groupInfo:this.kfEditor.requestService("syntax.get.group.content",a.groupId),offset:a.startOffset}},startUpdateSelection:function(){this.isDrag=!0,this.isMousedown=!1,this.clearSelection()},stopUpdateSelection:function(){this.isDrag=!1,this.isMousedown=!1,this.kfEditor.requestService("control.update.input")},clearSelection:function(){this.kfEditor.requestService("render.clear.select")},updateSelection:function(a,b){var d=b>this.startPoint.x,e={},f=null,g=!1,h=this.startGroup,i=null,j=this.getGroupInof(b,a);j.groupInfo.id===h.groupInfo.id?(e={groupId:j.groupInfo.id,startOffset:h.offset,endOffset:j.offset},this.startGroupIsPlaceholder&&(d?e.startOffset===e.endOffset&&(e.endOffset+=1):e.startOffset+=1)):c.contains(h.groupInfo.groupObj,j.groupInfo.groupObj)?e={groupId:h.groupInfo.id,startOffset:h.offset,endOffset:this.getIndex(h.groupInfo.groupObj,a,b)}:c.contains(j.groupInfo.groupObj,h.groupInfo.groupObj)?(e={groupId:j.groupInfo.id,startOffset:this.kfEditor.requestService("position.get.index",j.groupInfo.groupObj,h.groupInfo.groupObj),endOffset:j.offset},d||(e.startOffset+=1)):(f=this.getCommunityGroup(h.groupInfo,j.groupInfo),f.startOffset===f.endOffset?f.endOffset+=1:(i=f.group.content[f.endOffset],g=this.kfEditor.requestService("position.get.area",i,b),g&&(f.endOffset+=1),d||(f.startOffset+=1)),e={groupId:f.group.id,startOffset:f.startOffset,endOffset:f.endOffset}),this.kfEditor.requestService("syntax.update.record.cursor",e.groupId,e.startOffset,e.endOffset),this.kfEditor.requestService("control.reselect")},updateSelectionByTarget:function(a){var b=this.kfEditor.requestService("position.get.parent.group",a),c=null,d={};if(null!==b){if(this.kfEditor.requestService("syntax.is.root.node",b.id))return void this.selectAll();this.kfEditor.requestService("syntax.is.virtual.node",b.id)?(c=this.kfEditor.requestService("position.get.group.info",b.groupObj),d={groupId:c.group.id,startOffset:c.index,endOffset:c.index+1}):d={groupId:b.id,startOffset:0,endOffset:b.content.length},this.kfEditor.requestService("syntax.update.record.cursor",d),this.kfEditor.requestService("control.reselect"),this.kfEditor.requestService("control.update.input")}},selectAll:function(){var a=this.kfEditor.requestService("syntax.get.root.group.info"),b={groupId:a.id,startOffset:0,endOffset:a.content.length};this.kfEditor.requestService("syntax.update.record.cursor",b),this.kfEditor.requestService("control.reselect"),this.kfEditor.requestService("control.update.input")},getGroupInof:function(a,b){var c=this.kfEditor.requestService("position.get.group",b);null===c&&(c=this.kfEditor.requestService("syntax.get.root.group.info"));var d=this.kfEditor.requestService("position.get.location.info",a,c);return{groupInfo:c,offset:d}},getIndex:function(a,b,d){var e=this.kfEditor.requestService("position.get.index",a,b),f=this.kfEditor.requestService("syntax.get.group.content",a.id),g=f.content[e],h=c.getRect(g);return h.left+h.width/2<d&&(e+=1),e},getCommunityGroup:function(a,b){for(var d=null,e=a.groupObj,f=null;(d=this.kfEditor.requestService("position.get.group.info",e))&&(e=d.group.groupObj,!c.contains(d.group.groupObj,b.groupObj)););return f=d.group.groupObj,{group:d.group,startOffset:d.index,endOffset:this.kfEditor.requestService("position.get.index",f,b.groupObj)}}})}},b[11]={value:function(){return{GROUP:"kf-editor-group",VIRTUAL:"kf-editor-virtual-group"}}},b[12]={value:function(){function a(a){var b=this.services[a];if(!b)throw new Error("KFEditor: not found service, "+a);return b}var c=b.r(20),d=b.r(4),e={formula:{fontsize:50,autoresize:!1},ui:{zoom:!0,maxzoom:2,minzoom:1}},f={},g=b.r(19).ResourceManager,h=c.createClass("KFEditor",{constructor:function(a,b){this.options=d.extend(!0,{},e,b),this.FormulaClass=null,this._readyState=!1,this._callbacks=[],this.container=a,this.services={},this.commands={},this.initResource()},isReady:function(){return!!this._readyState},triggerReady:function(){for(var a=null,b=this;a=this._callbacks.shift();)a.call(b,b)},ready:function(a){this._readyState?a.call(this,this):this._callbacks.push(a)},getContainer:function(){return this.container},getDocument:function(){return this.container.ownerDocument},getFormulaClass:function(){return this.FormulaClass},getOptions:function(){return this.options},initResource:function(){var a=this;g.ready(function(b){a.FormulaClass=b,a.initComponents(),a._readyState=!0,a.triggerReady()},this.options.resource)},initComponents:function(){var a=this;d.each(f,function(b,c){new b(a,a.options[c])})},requestService:function(b){var c=a.call(this,b);return c.service[c.key].apply(c.provider,[].slice.call(arguments,1))},request:function(b){var c=a.call(this,b);return c.service},registerService:function(a,b,c){var e=null;for(e in c)c[e]&&c.hasOwnProperty(e)&&(c[e]=d.proxy(c[e],b));this.services[a]={provider:b,key:e,service:c}},registerCommand:function(a,b,c){this.commands[a]={executor:b,execFn:c}},execCommand:function(a){var b=this.commands[a];if(!b)throw new Error("KFEditor: not found command, "+a);return b.execFn.apply(b.executor,[].slice.call(arguments,1))}});return d.extend(h,{registerComponents:function(a,b){f[a]=b}}),h}},b[13]={value:function(){function a(a,b){var c=this;this._callbacks=[],this.editor=new d(a,b),this.editor.ready(function(){c._trigger()})}var c=b.r(20),d=b.r(12);return a.prototype._trigger=function(){var a=this.editor;c.Utils.each(this._callbacks,function(b){b.call(a,a)})},a.prototype.ready=function(a){this.editor.isReady()?a.call(this.editor,this.editor):this._callbacks.push(a)},{create:function(b,c){return new a(b,c)}}}},b[14]={value:function(){return window.jQuery}},b[15]={value:function(){return{selectColor:"rgba(42, 106, 189, 0.2)",allSelectColor:"rgba(42, 106, 189, 0.6)"}}},b[16]={value:function(){var a=b.r(20),c=b.r(19),d=b.r(18);return a.createClass("PlaceholderExpression",{base:c.CompoundExpression,constructor:function(){this.callBase(),this.setFlag("Placeholder"),this.label=null,this.box.setAttr("data-type",null),this.setOperator(new d)},setLabel:function(a){this.label=a},getLabel:function(){return this.label},setAttr:function(a,b){"label"===a?this.setLabel(b):(a.label&&(this.setLabel(a.label),delete a.label),this.callBase(a,b))},select:function(){this.getOperator().select()},selectAll:function(){this.getOperator().selectAll()},unselect:function(){this.getOperator().unselect()}})}},b[17]={value:function(){function a(a){c.PlaceholderExpression=b.r(16),c.Expression.prototype.select=function(){this.box.fill(d)},c.Expression.prototype.selectAll=function(){this.box.fill(e)},c.Expression.prototype.unselect=function(){this.box.fill("transparent")},a.getKFParser().expand({parse:{placeholder:{name:"placeholder",handler:function(a){return delete a.handler,a.operand=[],a},sign:!1}},reverse:{placeholder:function(){return"\\placeholder "}}})}var c=b.r(19),d=b.r(15).selectColor,e=b.r(15).allSelectColor;return{ext:a}}},b[18]={value:function(){function a(a,b){return null!==b?d(a,b):c(a)}function c(a){var b=35,c=50,d=null;return d=new e.Rect(b,c,0,0).stroke("black").fill("transparent"),d.setAttr("stroke-dasharray","5, 5"),a.addOperatorShape(d),d}function d(a,b){var c=new e.Text(b).fill(f),d=new e.Group,g=20,h=7,i=new e.Rect(0,0,0,0,h).stroke(f).fill("transparent"),j=null;return c.setFontSize(40),d.addShape(i),d.addShape(c),a.addOperatorShape(d),j=c.getFixRenderBox(),i.stroke(f).fill("transparent"),i.setSize(j.width+2*g,j.height+2*g),i.setRadius(h),i.setAttr("stroke-dasharray","5, 5"),c.setAttr({dx:0-j.x,dy:0-j.y}),c.translate(g,g),i}var e=b.r(20),f=b.r(29).rootPlaceholder.color,g=b.r(15).selectColor,h=b.r(15).allSelectColor;return e.createClass("PlaceholderOperator",{base:b.r(19).Operator,constructor:function(){this.opShape=null,this.callBase("Placeholder")},applyOperand:function(){this.opShape=a(this,this.parentExpression.getLabel()),this.parentExpression.expand(20,20),this.parentExpression.translateElement(10,10)},select:function(){this.opShape.fill(g)},selectAll:function(){this.opShape.fill(h)},unselect:function(){this.opShape.fill("transparent")}})}},b[19]={value:function(){return window.kf}},b[20]={value:function(){return window.kity}},b[21]={value:function(){function a(a,b,c){var i=null,j=!c;b.attr=b.attr||{},b.attr.id=a.getGroupId(),j?d(a,b):c.attr["data-root"]&&"placeholder"===b.name&&g(c.operand)&&(b.attr.label=o);for(var k=0,l=b.operand.length;l>k;k++)i=b.operand[k],h(b)?e(a,k,b,i):f(a,k,b,i);return b}function c(){return q+ ++s}function d(a,b){a.isResetId?b.attr["data-root"]="true":b.attr["data-type"]=r.VIRTUAL}function e(b,c,d,e){"brackets"===d.name&&2>c||("function"!==d.name||0!==c)&&(d.attr["data-type"]=r.VIRTUAL,e?"string"==typeof e?(d.operand[c]=j(b),d.operand[c].operand[0]=e):i(e)?(d.operand[c]=j(b),d.operand[c].operand[0]=a(b,e,d.operand[c])):d.operand[c]=a(b,e,d):d.operand[c]=e)}function f(b,c,d,e){d.attr["data-type"]=r.GROUP,d.operand[c]=e&&"string"!=typeof e?"text"===e.name?e:a(b,e,d):e}function g(a){var b=1;if(a.length>3)return!1;for(var c=0,d=a.length;d>c;c++)a[c]!==m&&a[c]&&"placeholder"===a[c].name&&b--;return!b}function h(a){return!!n[a.name]}function i(a){return"placeholder"===a.name}function j(a){return{name:p,attr:{"data-type":r.GROUP,id:a.getGroupId()},operand:[]}}var k=b.r(19).Parser,l=b.r(20),m=b.r(29).cursorCharacter,n=b.r(22),o=b.r(29).rootPlaceholder.content,p="combination",q="_kf_editor_",r=b.r(11),s=0,t=l.createClass("Parser",{constructor:function(a){this.kfEditor=a,this.callBase(),this.kfParser=k.use("latex"),this.initKFormulExtension(),this.pid=c(),this.groupRecord=0,this.tree=null,this.isResetId=!0,this.initServices()},parse:function(b,c){var d=null;return this.isResetId=!!c,this.isResetId&&this.resetGroupId(),d=this.kfParser.parse(b),a(this,d.tree),d},serialization:function(a){return this.kfParser.serialization(a)},initServices:function(){this.kfEditor.registerService("parser.parse",this,{parse:this.parse}),this.kfEditor.registerService("parser.latex.serialization",this,{serialization:this.serialization})},getKFParser:function(){return this.kfParser},initKFormulExtension:function(){b.r(17).ext(this)},resetGroupId:function(){this.groupRecord=0},getGroupId:function(){return this.pid+"_"+ ++this.groupRecord}});return t}},b[22]={value:function(){return{radical:!0,fraction:!0,summation:!0,integration:!0,placeholder:!0,script:!0,superscript:!0,subscript:!0,brackets:!0,"function":!0}}},b[23]={value:function(){function a(b,c,d){var e=null;return b.ownerSVGElement?(b=b.parentNode,e=b.tagName.toLowerCase(),b&&"body"!==e&&"svg"!==e?"kf-editor-group"===b.getAttribute("data-type")?b:c&&"kf-editor-virtual-group"===b.getAttribute("data-type")?b:d&&null!==b.getAttribute("data-flag")?b:a(b,c,d):null):null}var c=b.r(20),d=b.r(4),e=c.createClass("PositionComponenet",{constructor:function(a){this.kfEditor=a,this.initServices()},initServices:function(){this.kfEditor.registerService("position.get.group",this,{getGroupByTarget:this.getGroupByTarget}),this.kfEditor.registerService("position.get.index",this,{getIndexByTargetInGroup:this.getIndexByTargetInGroup}),this.kfEditor.registerService("position.get.location.info",this,{getLocationInfo:this.getLocationInfo}),this.kfEditor.registerService("position.get.parent.group",this,{getParentGroupByTarget:this.getParentGroupByTarget}),this.kfEditor.registerService("position.get.wrap",this,{getWrap:this.getWrap}),this.kfEditor.registerService("position.get.area",this,{getAreaByCursorInGroup:this.getAreaByCursorInGroup}),this.kfEditor.registerService("position.get.group.info",this,{getGroupInfoByNode:this.getGroupInfoByNode}),this.kfEditor.registerService("position.get.parent.info",this,{getParentInfoByNode:this.getParentInfoByNode})},getGroupByTarget:function(b){var c=a(b,!1,!1);return c?this.kfEditor.requestService("syntax.get.group.content",c.id):null},getIndexByTargetInGroup:function(a,b){var e=this.kfEditor.requestService("syntax.get.group.content",a.id),f=-1;return c.Utils.each(e.content,function(a,c){return f=c,d.contains(a,b)?!1:void 0}),f},getAreaByCursorInGroup:function(a,b){var c=d.getRect(a);return c.left+c.width/2<b},getLocationInfo:function(a,b){for(var c=-1,e=b.content,f=null,g=e.length-1,h=null;g>=0;g--)if(c=g,h=e[g],f=d.getRect(h),f.left<a){f.left+f.width/2<a&&(c+=1);break}return c},getParentGroupByTarget:function(b){var c=a(b,!0,!1);return c?this.kfEditor.requestService("syntax.get.group.content",c.id):null},getWrap:function(b){return a(b,!0,!0)},getGroupInfoByNode:function(b){var c={},e=a(b,!1,!1),f=null;if(!e)return null;f=this.kfEditor.requestService("syntax.get.group.content",e.id);for(var g=0,h=f.content.length;h>g&&(c.index=g,!d.contains(f.content[g],b));g++);return c.group=f,c},getParentInfoByNode:function(b){var c=a(b,!0,!1);return c=this.kfEditor.requestService("syntax.get.group.content",c.id),{group:c,index:c.content.indexOf(b)}}});return e}},b[24]={value:function(){var a=b.r(20);return a.createClass("Printer",{constructor:function(a){this.kfEditor=a,this.initServices(),this.initCommands()},initServices:function(){this.kfEditor.registerService("print.image",this,{printImage:this.printImage})},initCommands:function(){this.kfEditor.registerCommand("get.image.data",this,this.getImageData)},printImage:function(){var a=this.kfEditor.requestService("render.get.paper");this._formatCanvas(),a.toPNG(function(a){document.body.innerHTML='<img style="background: red;" src="'+a+'">'}),this._restoreCanvas()},getImageData:function(a){var b=this.kfEditor.requestService("render.get.canvas"),c=this.kfEditor.requestService("render.get.paper");this._formatCanvas(),c.toPNG(function(c){a({width:b.width,height:b.height,img:c})}),this._restoreCanvas()},_formatCanvas:function(){var a=this.kfEditor.requestService("render.get.canvas"),b=a.container.getRenderBox();a.node.setAttribute("width",b.width),a.node.setAttribute("height",b.height),this.kfEditor.requestService("render.clear.canvas.transform"),this.kfEditor.requestService("control.cursor.hide"),this.kfEditor.requestService("render.clear.select")},_restoreCanvas:function(){var a=this.kfEditor.requestService("render.get.canvas");a.node.setAttribute("width","100%"),a.node.setAttribute("height","100%"),this.kfEditor.requestService("render.revert.canvas.transform"),this.kfEditor.requestService("control.cursor.relocation"),this.kfEditor.requestService("render.reselect")}})}},b[25]={value:function(){var a=b.r(20),c=b.r(19).Assembly,d={autoresize:!1,fontsize:50,padding:[20,50]},e=a.createClass("RenderComponent",{base:b.r(1),constructor:function(b,c){this.callBase(),this.options=a.Utils.extend({},d,c),this.kfEditor=b,this.assembly=null,this.formula=null,this.relDisabled=!1,this.canvasZoom=1,this.record={select:{},cursor:{},canvas:{}},this.initCanvas(),this.initServices(),this.initCommands()},initCanvas:function(){var a=this.kfEditor.requestService("ui.get.canvas.container"),b=this.kfEditor.getFormulaClass();this.assembly=new c(new b(a,this.options)),this.formula=this.assembly.formula,this.setCanvasToCenter()},setCanvasOffset:function(a,b){var c=this.formula.getViewBox();b=void 0!==b?b:-c.height/2,this.formula.setViewBox(a,b,c.width,c.height)},setCanvasToCenter:function(){var a=this.formula.getViewBox();this.formula.setViewBox(-a.width/2,-a.height/2,a.width,a.height)},initServices:function(){this.kfEditor.registerService("render.get.canvas",this,{getCanvas:this.getCanvas}),this.kfEditor.registerService("render.get.content.size",this,{getContentSize:this.getContentSize}),this.kfEditor.registerService("render.clear.canvas.transform",this,{clearCanvasOffset:this.clearCanvasTransform}),this.kfEditor.registerService("render.set.canvas.offset",this,{setCanvasOffset:this.setCanvasOffset}),this.kfEditor.registerService("render.set.canvas.to.center",this,{setCanvasToCenter:this.setCanvasToCenter}),this.kfEditor.registerService("render.revert.canvas.transform",this,{revertCanvasTransform:this.revertCanvasTransform}),this.kfEditor.registerService("render.relocation",this,{relocation:this.relocation}),this.kfEditor.registerService("render.disable.relocation",this,{disableRelocation:this.disableRelocation}),this.kfEditor.registerService("render.enable.relocation",this,{enableRelocation:this.enableRelocation}),this.kfEditor.registerService("render.select.group.content",this,{selectGroupContent:this.selectGroupContent}),this.kfEditor.registerService("render.select.group",this,{selectGroup:this.selectGroup}),this.kfEditor.registerService("render.select.group.all",this,{selectAllGroup:this.selectAllGroup}),this.kfEditor.registerService("render.tint.current.cursor",this,{tintCurrentGroup:this.tintCurrentGroup}),this.kfEditor.registerService("render.select.current.cursor",this,{selectCurrentCursor:this.selectCurrentCursor}),this.kfEditor.registerService("render.reselect",this,{reselect:this.reselect}),this.kfEditor.registerService("render.clear.select",this,{clearSelect:this.clearSelect}),this.kfEditor.registerService("render.set.canvas.zoom",this,{setCanvasZoom:this.setCanvasZoom}),this.kfEditor.registerService("render.get.canvas.zoom",this,{getCanvasZoom:this.getCanvasZoom}),this.kfEditor.registerService("render.get.paper.offset",this,{getPaperOffset:this.getPaperOffset}),this.kfEditor.registerService("render.draw",this,{render:this.render}),this.kfEditor.registerService("render.insert.string",this,{insertString:this.insertString}),this.kfEditor.registerService("render.insert.group",this,{insertGroup:this.insertGroup}),this.kfEditor.registerService("render.get.paper",this,{getPaper:this.getPaper})},initCommands:function(){this.kfEditor.registerCommand("render",this,function(a){this.render(a),this.kfEditor.requestService("ui.update.canvas.view")}),this.kfEditor.registerCommand("getPaper",this,this.getPaper)},relocation:function(){this.relDisabled?this.relocationToLeft():this.relocationToCenter()},relocationToCenter:function(){var a=this.formula.container.getRenderBox();this.formula.container.setTranslate(-a.width/2,-a.height/2),this.setCanvasToCenter()},relocationToLeft:function(){var a=this.formula.container.getRenderBox();this.formula.container.setTranslate(0,-a.height/2),this.setCanvasOffset(0)},selectGroup:function(a){var b=this.kfEditor.requestService("syntax.get.group.object",a);this.clearSelect(),b.node.getAttribute("data-root")||(this.record.select.lastSelect=b,b.select())},selectGroupContent:function(a){null!==a.groupObj.getAttribute("data-placeholder")&&(a={id:a.content[0].id});var b=this.kfEditor.requestService("syntax.get.group.object",a.id);this.clearSelect(),this.record.select.lastSelect=b,b.node.getAttribute("data-root")||b.select()},selectAllGroup:function(a){null!==a.groupObj.getAttribute("data-placeholder")&&(a={id:a.content[0].id});var b=this.kfEditor.requestService("syntax.get.group.object",a.id);this.clearSelect(),this.record.select.lastSelect=b,b.selectAll()},selectCurrentCursor:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=this.kfEditor.requestService("syntax.get.group.object",a.groupId),c=null,d=-1,e=0,f=Math.min(a.startOffset,a.endOffset),g=Math.max(a.startOffset,a.endOffset);this.clearSelect(),this.record.select.lastSelect=b;for(var h=f,i=g;i>h;h++)c=b.getOperand(h).getRenderBox(b),-1==d&&(d=c.x),e+=c.width;b.setBoxWidth(e),b.selectAll(),b.getBox().setTranslate(d,0)},tintCurrentGroup:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor").groupId,b=this.kfEditor.requestService("syntax.get.group.object",a),c=this.kfEditor.requestService("syntax.is.placeholder.node",a);this.clearSelect(),b.node.getAttribute("data-root")||(c&&(b=this.kfEditor.requestService("syntax.get.group.object",b.operands[0].node.id)),this.record.select.lastSelect=b,b.select())},reselect:function(){var a=this.kfEditor.requestService("syntax.get.record.cursor"),b=null;b=this.kfEditor.requestService("syntax.get.group.object",a.groupId),this.clearSelect(),this.record.select.lastSelect=b,b.node.getAttribute("data-root")||b.select()
},clearSelect:function(){var a=null,b=this.record.select.lastSelect;b&&b.node.ownerSVGElement&&(b.unselect(),a=b.getRenderBox(b),b.setBoxWidth(a.width),b.getBox().setTranslate(0,0))},getPaper:function(){return this.formula},render:function(a){var b=this.kfEditor.requestService("parser.parse",a,!0),c=this.assembly.regenerateBy(b);this.kfEditor.requestService("syntax.update.objtree",c)},enableRelocation:function(){this.relDisabled=!1},disableRelocation:function(){this.relDisabled=!0},setCanvasZoom:function(a){var b=this.formula.getViewPort();this.canvasZoom=a,b.zoom=a,this.formula.setViewPort(b)},getCanvas:function(){return this.formula},getContentSize:function(){return this.formula.container.getRenderBox()},clearCanvasTransform:function(){var a=this.record.canvas;a.viewBox=this.formula.getViewBox(),a.contentOffset=this.formula.container.getTranslate(),this.setCanvasToCenter(),this.formula.node.removeAttribute("viewBox"),this.formula.container.setTranslate(0,0)},revertCanvasTransform:function(){var a=this.record.canvas,b=a.viewBox;return b?(this.formula.setViewBox(b.x,b.y,b.width,b.height),this.formula.container.setTranslate(a.contentOffset),a.viewBox=null,void(a.contentOffset=null)):!1},getCanvasZoom:function(){return this.canvasZoom}});return e}},b[26]={value:function(){var a=b.r(20);return a.createClass("DeleteComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b},deleteGroup:function(){var a=this.parentComponent.getCursorRecord(),b=this.parentComponent.getObjectTree(),c=b.mapping[a.groupId].strGroup;return a.startOffset!==a.endOffset?this.parentComponent.isSelectPlaceholder()?this.parentComponent.isRootTree(c)?!1:(a=this.selectParentContainer(a.groupId),this.parentComponent.updateCursor(a),!1):this.deleteSelection(c,a):0===a.startOffset?this.parentComponent.isRootTree(c)?!1:(a=this.selectParentContainer(a.groupId),this.parentComponent.updateCursor(a),!1):c.operand.length>1?(a=this.deletePrevGroup(c,a),this.parentComponent.updateCursor(a),a.startOffset===a.endOffset?!0:!1):(a.startOffset=0,a.endOffset=1,c.operand[0].attr&&this.parentComponent.isGroupNode(c.operand[0].attr.id)?(this.parentComponent.updateCursor(a),!1):(c.operand[0]={name:"placeholder",operand:[]},this.parentComponent.updateCursor(a),!0))},deletePrevGroup:function(a,b){var c=b.startOffset-1,d=a.operand[c];return this.parentComponent.isLeafTree(d)?(a.operand.splice(c,1),b.startOffset-=1,b.endOffset-=1):b.startOffset-=1,b},deleteSelection:function(a,b){return 0===b.startOffset&&b.endOffset===a.operand.length?(a.operand.length=1,a.operand[0]={name:"placeholder",operand:[]},b.endOffset=1):(a.operand.splice(b.startOffset,b.endOffset-b.startOffset),b.endOffset=b.startOffset),this.parentComponent.updateCursor(b),!0},selectParentContainer:function(a){var b=this.parentComponent.getGroupObject(a).node,c=this.kfEditor.requestService("position.get.group",b),d=this.kfEditor.requestService("position.get.index",c.groupObj,b);return{groupId:c.id,startOffset:d,endOffset:d+1}}})}},b[27]={value:function(){function a(a){var b=null,c=this.parentComponent,f=null;return f=c.getGroupContent(a.groupId),c.isSelectPlaceholder()?e(this,f.content[a.startOffset],p.LEFT):(a.startOffset===a.endOffset?a.startOffset>0?(b=f.content[a.startOffset-1],l(b)?a=d(this,b,p.LEFT):(a.startOffset-=1,m(b)||(a.endOffset=a.startOffset))):a=e(this,f.groupObj,p.LEFT):(a.startOffset=Math.min(a.startOffset,a.endOffset),a.endOffset=a.startOffset),a)}function c(a){var b=null,c=this.parentComponent,f=null;return f=c.getGroupContent(a.groupId),c.isSelectPlaceholder()?e(this,f.content[a.startOffset],p.RIGHT):(a.startOffset===a.endOffset?a.startOffset<f.content.length?(b=f.content[a.startOffset],l(b)?a=d(this,b,p.RIGHT):(a.startOffset+=1,m(b)||(a.endOffset=a.startOffset))):a=e(this,f.groupObj,p.RIGHT):(a.endOffset=Math.max(a.startOffset,a.endOffset),a.startOffset=a.endOffset),a)}function d(a,b,c){switch(c){case p.LEFT:return f(a,b);case p.RIGHT:return h(a,b)}throw new Error("undefined move direction!")}function e(a,b,c){switch(c){case p.LEFT:return g(a,b);case p.RIGHT:return i(a,b)}throw new Error("undefined move direction!")}function f(a,b){var c=a.parentComponent,d=null,e=null;if(m(b)||n(b))return g(a,b);if(l(b)){if(d=c.getGroupContent(b.id),e=d.content[d.content.length-1],n(e))return g(a,e);if(k(b))return m(e)?{groupId:b.id,startOffset:d.content.length-1,endOffset:d.content.length}:k(e)&&1===d.content.length?f(a,e):{groupId:b.id,startOffset:d.content.length,endOffset:d.content.length};for(;!k(e)&&!n(e)&&!m(e);)d=c.getGroupContent(e.id),e=d.content[d.content.length-1];return n(e)?g(a,e):m(e)?{groupId:e.id,startOffset:d.content.length,endOffset:d.content.length}:f(a,e)}return null}function g(a,b){var c=a.kfEditor,d=null;if(j(b))return null;for(d=c.requestService("position.get.parent.info",b);0===d.index;){if(j(d.group.groupObj))return{groupId:d.group.id,startOffset:0,endOffset:0};if(k(d.group.groupObj)&&d.group.content.length>1)return{groupId:d.group.id,startOffset:0,endOffset:0};d=c.requestService("position.get.parent.info",d.group.groupObj)}return k(d.group.groupObj)?{groupId:d.group.id,startOffset:d.index,endOffset:d.index}:(b=d.group.content[d.index-1],l(b)?k(b)?f(a,b):f(a,b):n(b)?g(a,b):{groupId:d.group.id,startOffset:d.index,endOffset:d.index})}function h(a,b){var c=a.parentComponent,d=null,e=null;if(l(b)){if(d=c.getGroupContent(b.id),e=d.content[0],k(b))return k(e)?h(a,e):m(e)?{groupId:b.id,startOffset:0,endOffset:1}:{groupId:b.id,startOffset:0,endOffset:0};for(;!k(e)&&!m(e)&&!n(e);)d=c.getGroupContent(e.id),e=d.content[0];return m(e)?{groupId:e.id,startOffset:0,endOffset:0}:n(e)?i(a,e):h(a,e)}return null}function i(a,b){var c=a.kfEditor,d=a.parentComponent,e=null,f=null;if(j(b))return null;for(e=c.requestService("position.get.parent.info",b);e.index===e.group.content.length-1;){if(j(e.group.groupObj))return{groupId:e.group.id,startOffset:e.group.content.length,endOffset:e.group.content.length};if(k(e.group.groupObj)&&e.group.content.length>1)return{groupId:e.group.id,startOffset:e.group.content.length,endOffset:e.group.content.length};e=c.requestService("position.get.parent.info",e.group.groupObj)}return b=e.group.content[e.index+1],n(b)?i(a,b):k(b)?(f=d.getGroupContent(b.id),d.isPlaceholder(f.content[0].id)?{groupId:b.id,startOffset:0,endOffset:1}:{groupId:b.id,startOffset:0,endOffset:0}):{groupId:e.group.id,startOffset:e.index+1,endOffset:e.index+1}}function j(a){return!!a.getAttribute("data-root")}function k(a){return"kf-editor-group"===a.getAttribute("data-type")}function l(a){var b=a.getAttribute("data-type");return"kf-editor-group"===b||"kf-editor-virtual-group"===b}function m(a){return"Placeholder"===a.getAttribute("data-flag")}function n(a){return"Empty"===a.getAttribute("data-flag")}var o=b.r(20),p={LEFT:"left",RIGHT:"right"};return o.createClass("MoveComponent",{constructor:function(a,b){this.parentComponent=a,this.kfEditor=b},leftMove:function(){var b=this.parentComponent.getCursorRecord();b=a.call(this,b),b&&this.parentComponent.updateCursor(b)},rightMove:function(){var a=this.parentComponent.getCursorRecord();a=c.call(this,a),a&&this.parentComponent.updateCursor(a)}})}},b[28]={value:function(){var a=b.r(20),c=b.r(27),d=b.r(26),e=b.r(29).cursorCharacter,f=b.r(11),g=a.createClass("SyntaxComponenet",{constructor:function(a){this.kfEditor=a,this.record={cursor:{group:null,startOffset:-1,endOffset:-1}},this.components={},this.objTree=null,this.initComponents(),this.initServices(),this.initCommands()},initComponents:function(){this.components.move=new c(this,this.kfEditor),this.components.delete=new d(this,this.kfEditor)},initServices:function(){this.kfEditor.registerService("syntax.update.objtree",this,{updateObjTree:this.updateObjTree}),this.kfEditor.registerService("syntax.get.objtree",this,{getObjectTree:this.getObjectTree}),this.kfEditor.registerService("syntax.get.group.object",this,{getGroupObject:this.getGroupObject}),this.kfEditor.registerService("syntax.is.root.node",this,{isRootNode:this.isRootNode}),this.kfEditor.registerService("syntax.is.group.node",this,{isGroupNode:this.isGroupNode}),this.kfEditor.registerService("syntax.is.virtual.node",this,{isVirtualNode:this.isVirtualNode}),this.kfEditor.registerService("syntax.is.placeholder.node",this,{isPlaceholder:this.isPlaceholder}),this.kfEditor.registerService("syntax.is.select.placeholder",this,{isSelectPlaceholder:this.isSelectPlaceholder}),this.kfEditor.registerService("syntax.has.root.placeholder",this,{hasRootplaceholder:this.hasRootplaceholder}),this.kfEditor.registerService("syntax.valid.brackets",this,{isBrackets:this.isBrackets}),this.kfEditor.registerService("syntax.get.group.content",this,{getGroupContent:this.getGroupContent}),this.kfEditor.registerService("syntax.get.root.group.info",this,{getRootGroupInfo:this.getRootGroupInfo}),this.kfEditor.registerService("syntax.get.root",this,{getRootObject:this.getRootObject}),this.kfEditor.registerService("syntax.update.record.cursor",this,{updateCursor:this.updateCursor}),this.kfEditor.registerService("syntax.update.selection",this,{updateSelection:this.updateSelection}),this.kfEditor.registerService("syntax.get.record.cursor",this,{getCursorRecord:this.getCursorRecord}),this.kfEditor.registerService("syntax.has.cursor.info",this,{hasCursorInfo:this.hasCursorInfo}),this.kfEditor.registerService("syntax.serialization",this,{serialization:this.serialization}),this.kfEditor.registerService("syntax.cursor.move.left",this,{leftMove:this.leftMove}),this.kfEditor.registerService("syntax.cursor.move.right",this,{rightMove:this.rightMove}),this.kfEditor.registerService("syntax.delete.group",this,{deleteGroup:this.deleteGroup})},initCommands:function(){this.kfEditor.registerCommand("get.source",this,this.getSource),this.kfEditor.registerCommand("content.is.empty",this,this.isEmpty)},updateObjTree:function(a){var b=a.select;b&&b.groupId&&this.updateCursor(b.groupId,b.startOffset,b.endOffset),this.objTree=a},hasCursorInfo:function(){return null!==this.record.cursor.group},isRootNode:function(a){return this.objTree.mapping.root.strGroup.attr.id===a},isGroupNode:function(a){var b=this.objTree.mapping[a].strGroup.attr["data-type"];return b===f.GROUP||b===f.VIRTUAL},isVirtualNode:function(a){return this.objTree.mapping[a].strGroup.attr["data-type"]===f.VIRTUAL},isPlaceholder:function(a){var b=this.objTree.mapping[a];return b?(b=b.objGroup.node,"Placeholder"===b.getAttribute("data-flag")):!1},isBrackets:function(a){return!!this.objTree.mapping[a].objGroup.node.getAttribute("data-brackets")},hasRootplaceholder:function(){return"placeholder"===this.objTree.mapping.root.strGroup.operand[0].name},isSelectPlaceholder:function(){var a=this.record.cursor,b=null;return a.endOffset-a.startOffset!==1?!1:(b=this.getGroupContent(a.groupId),this.isPlaceholder(b.content[a.startOffset].id)?!0:!1)},isLeafTree:function(a){return"string"==typeof a},isRootTree:function(a){return a.attr&&a.attr["data-root"]},getObjectTree:function(){return this.objTree},getGroupObject:function(a){return this.objTree.mapping[a].objGroup||null},getCursorRecord:function(){return a.Utils.extend({},this.record.cursor)||null},getGroupContent:function(b){var c=this.objTree.mapping[b],d=[],e=c.objGroup.operands,f=e.length-1,g="rtl"!==c.strGroup.traversal;return a.Utils.each(e,function(a,b){g?d.push(a.node):d[f-b]=a.node}),{id:b,traversal:c.strGroup.traversal||"ltr",groupObj:c.objGroup.node,content:d}},getRootObject:function(){return this.objTree.mapping.root.objGroup},getRootGroupInfo:function(){var a=this.objTree.mapping.root.strGroup.attr.id;return this.getGroupContent(a)},updateSelection:function(a){var b=this.objTree.mapping[a.id],c=b.strGroup,d=null,f=null,g=null,h=-1,i=-1;if(d=a,f=b,"combination"===c.name)this.record.cursor={groupId:d.id,startOffset:0,endOffset:c.operand.length},c.operand.unshift(e),c.operand.push(e);else{for(;"combination"!==f.strGroup.name||1===d.content;)a=d,b=f,d=this.kfEditor.requestService("position.get.parent.group",b.objGroup.node),f=this.objTree.mapping[d.id];var j=[].indexOf.call(d.content,a.groupObj);this.record.cursor={groupId:d.id,startOffset:j,endOffset:j+1},f.strGroup.operand.splice(j+1,0,e),f.strGroup.operand.splice(j,0,e)}return g=this.kfEditor.requestService("parser.latex.serialization",this.objTree.parsedTree),h=g.indexOf(e),g=g.replace(e,""),i=g.indexOf(e),f.strGroup.operand.splice(this.record.cursor.startOffset,1),f.strGroup.operand.splice(this.record.cursor.endOffset,1),{str:g,startOffset:h,endOffset:i}},getSource:function(){return this.serialization().str.replace(e,"").replace(e,"")},isEmpty:function(){return this.hasRootplaceholder()},serialization:function(){var a=this.record.cursor,b=this.objTree.mapping[a.groupId],c=b.strGroup,d=null,f=-1,g=-1;return f=Math.min(a.endOffset,a.startOffset),g=Math.max(a.endOffset,a.startOffset),c.operand.splice(g,0,e),c.operand.splice(f,0,e),g+=1,d=this.kfEditor.requestService("parser.latex.serialization",this.objTree.parsedTree),c.operand.splice(g,1),c.operand.splice(f,1),f=d.indexOf(e),a.startOffset===a.endOffset&&(d=d.replace(e,"")),g=d.lastIndexOf(e),{str:d,startOffset:f,endOffset:g}},updateCursor:function(a,b,c){var d=null;1===arguments.length&&(c=a.endOffset,b=a.startOffset,a=a.groupId),void 0===c&&(c=b),b>c&&(d=c,c=b,b=d),this.record.cursor={groupId:a,startOffset:b,endOffset:c}},leftMove:function(){this.components.move.leftMove()},rightMove:function(){this.components.move.rightMove()},deleteGroup:function(){return this.components.delete.deleteGroup()},insertSubtree:function(a){var b=this.record.cursor,c=0,d=0,e=null,f=0;this.isPlaceholder(b.groupId)?this.replaceTree(a):(c=Math.min(b.startOffset,b.endOffset),d=Math.max(b.startOffset,b.endOffset),f=d-c,e=this.objTree.mapping[b.groupId].strGroup,e.operand.splice(c,f,a),b.startOffset+=1,b.endOffset=b.startOffset)},replaceTree:function(a){var b=this.record.cursor,c=this.objTree.mapping[b.groupId].objGroup.node,d=this.kfEditor.requestService("position.get.parent.info",c),e=this.objTree.mapping[d.group.id].strGroup;e.operand[d.index]=a,b.groupId=d.group.id,b.startOffset=d.index+1,b.endOffset=d.index+1}});return g}},b[29]={value:function(){return{cursorCharacter:"\uf155",rootPlaceholder:{color:"#666",content:"\u5728\u6b64\u5904\u952e\u5165\u516c\u5f0f",fontsize:16},scrollbar:{padding:5,step:150}}}},b[30]={value:function(){return{"\\pm":{x:5,y:0},"\\infty":{x:42,y:0},"=":{x:79,y:0},"\\sim":{x:116,y:0},"\\times":{x:153,y:0},"\\div":{x:190,y:0},"!":{x:227,y:0},"<":{x:264,y:0},"\\ll":{x:301,y:0},">":{x:338,y:0},"\\gg":{x:375,y:0},"\\leq":{x:412,y:0},"\\geq":{x:449,y:0},"\\mp":{x:486,y:0},"\\cong":{x:523,y:0},"\\equiv":{x:560,y:0},"\\propto":{x:597,y:0},"\\approx":{x:634,y:0},"\\forall":{x:671,y:0},"\\partial":{x:708,y:0},"\\surd":{x:745,y:0},"\\cup":{x:782,y:0},"\\cap":{x:819,y:0},"\\varnothing":{x:856,y:0},"%":{x:893,y:0},"\\circ":{x:930,y:0},"\\exists":{x:967,y:0},"\\nexists":{x:1004,y:0},"\\in":{x:1041,y:0},"\\ni":{x:1078,y:0},"\\gets":{x:5,y:37},"\\uparrow":{x:42,y:37},"\\to":{x:79,y:37},"\\downarrow":{x:116,y:37},"\\leftrightarrow":{x:153,y:37},"\\therefore":{x:190,y:37},"\\because":{x:227,y:37},"+":{x:264,y:37},"-":{x:301,y:37},"\\neg":{x:338,y:37},"\\ast":{x:375,y:37},"\\cdot":{x:412,y:37},"\\vdots":{x:449,y:37},"\\ddots":{x:486,y:37},"\\aleph":{x:523,y:37},"\\beth":{x:560,y:37},"\\blacksquare":{x:597,y:37},"\\alpha":{x:634,y:37},"\\beta":{x:671,y:37},"\\gamma":{x:708,y:37},"\\delta":{x:745,y:37},"\\epsilon":{x:782,y:37},"\\zeta":{x:819,y:37},"\\eta":{x:856,y:37},"\\theta":{x:893,y:37},"\\iota":{x:930,y:37},"\\kappa":{x:967,y:37},"\\lambda":{x:1004,y:37},"\\mu":{x:1041,y:37},"\\nu":{x:1078,y:37},"\\xi":{x:5,y:74},"\\omicron":{x:42,y:74},"\\pi":{x:79,y:74},"\\rho":{x:116,y:74},"\\sigma":{x:153,y:74},"\\tau":{x:190,y:74},"\\upsilon":{x:227,y:74},"\\phi":{x:264,y:74},"\\chi":{x:301,y:74},"\\psi":{x:338,y:74},"\\omega":{x:375,y:74},"\\Alpha":{x:412,y:74},"\\Beta":{x:449,y:74},"\\Gamma":{x:486,y:74},"\\Delta":{x:523,y:74},"\\Epsilon":{x:560,y:74},"\\Zeta":{x:597,y:74},"\\Eta":{x:634,y:74},"\\Theta":{x:671,y:74},"\\Iota":{x:708,y:74},"\\Kappa":{x:745,y:74},"\\Lambda":{x:782,y:74},"\\Mu":{x:819,y:74},"\\Nu":{x:856,y:74},"\\Xi":{x:893,y:74},"\\Omicron":{x:930,y:74},"\\Pi":{x:967,y:74},"\\Rho":{x:1004,y:74},"\\Sigma":{x:1041,y:74},"\\Tau":{x:1078,y:74},"\\Upsilon":{x:5,y:111},"\\Phi":{x:42,y:111},"\\Chi":{x:79,y:111},"\\Psi":{x:116,y:111},"\\Omega":{x:153,y:111},"\\digamma":{x:190,y:111},"\\varepsilon":{x:227,y:111},"\\varkappa":{x:264,y:111},"\\varphi":{x:301,y:111},"\\varpi":{x:338,y:111},"\\varrho":{x:375,y:111},"\\varsigma":{x:412,y:111},"\\vartheta":{x:449,y:111},"\\neq":{x:486,y:111},"\\nless":{x:523,y:111},"\\ngtr":{x:560,y:111},"\\nleq":{x:597,y:111},"\\ngeq":{x:634,y:111},"\\nsim":{x:671,y:111},"\\lneqq":{x:708,y:111},"\\gneqq":{x:745,y:111},"\\nprec":{x:782,y:111},"\\nsucc":{x:819,y:111},"\\notin":{x:856,y:111},"\\nsubseteq":{x:893,y:111},"\\nsupseteq":{x:930,y:111},"\\subsetneq":{x:967,y:111},"\\supsetneq":{x:1004,y:111},"\\lnsim":{x:1041,y:111},"\\gnsim":{x:1078,y:111},"\\precnsim":{x:5,y:148},"\\succnsim":{x:42,y:148},"\\ntriangleleft":{x:79,y:148},"\\ntriangleright":{x:116,y:148},"\\ntrianglelefteq":{x:153,y:148},"\\ntrianglerighteq":{x:190,y:148},"\\nmid":{x:227,y:148},"\\nparallel":{x:264,y:148},"\\nvdash":{x:301,y:148},"\\nVdash":{x:338,y:148},"\\nvDash":{x:375,y:148},"\\nVDash":{x:412,y:148},"\\daleth":{x:449,y:148},"\\gimel":{x:486,y:148},"\\complement":{x:523,y:148},"\\ell":{x:560,y:148},"\\eth":{x:597,y:148},"\\hbar":{x:634,y:148},"\\hslash":{x:671,y:148},"\\mho":{x:708,y:148},"\\wp":{x:745,y:148},"\\circledS":{x:782,y:148},"\\Bbbk":{x:819,y:148},"\\Finv":{x:856,y:148},"\\Game":{x:893,y:148},"\\Im":{x:930,y:148},"\\Re":{x:967,y:148},"\\updownarrow":{x:1004,y:148},"\\Leftarrow":{x:1041,y:148},"\\Rightarrow":{x:1078,y:148},"\\Uparrow":{x:5,y:185},"\\Downarrow":{x:42,y:185},"\\Leftrightarrow":{x:79,y:185},"\\Updownarrow":{x:116,y:185},"\\longleftarrow":{x:153,y:185},"\\longrightarrow":{x:190,y:185},"\\longleftrightarrow":{x:227,y:185},"\\Longleftarrow":{x:264,y:185},"\\Longrightarrow":{x:301,y:185},"\\Longleftrightarrow":{x:338,y:185},"\\nearrow":{x:375,y:185},"\\nwarrow":{x:412,y:185},"\\searrow":{x:449,y:185},"\\swarrow":{x:486,y:185},"\\nleftarrow":{x:523,y:185},"\\nrightarrow":{x:560,y:185},"\\nLeftarrow":{x:597,y:185},"\\nRightarrow":{x:634,y:185},"\\nLeftrightarrow":{x:671,y:185},"\\leftharpoonup":{x:708,y:185},"\\leftharpoondown":{x:745,y:185},"\\rightharpoonup":{x:782,y:185},"\\rightharpoondown":{x:819,y:185},"\\upharpoonleft":{x:856,y:185},"\\upharpoonright":{x:893,y:185},"\\downharpoonleft":{x:930,y:185},"\\downharpoonright":{x:967,y:185},"\\leftrightharpoons":{x:1004,y:185},"\\rightleftharpoons":{x:1041,y:185},"\\leftleftarrows":{x:1078,y:185},"\\rightrightarrows":{x:5,y:222},"\\upuparrows":{x:42,y:222},"\\downdownarrows":{x:79,y:222},"\\leftrightarrows":{x:116,y:222},"\\rightleftarrows":{x:153,y:222},"\\looparrowleft":{x:190,y:222},"\\looparrowright":{x:227,y:222},"\\leftarrowtail":{x:264,y:222},"\\rightarrowtail":{x:301,y:222},"\\Lsh":{x:338,y:222},"\\Rsh":{x:375,y:222},"\\Lleftarrow":{x:412,y:222},"\\Rrightarrow":{x:449,y:222},"\\curvearrowleft":{x:486,y:222},"\\curvearrowright":{x:523,y:222},"\\circlearrowleft":{x:560,y:222},"\\circlearrowright":{x:597,y:222},"\\multimap":{x:634,y:222},"\\leftrightsquigarrow":{x:671,y:222},"\\twoheadleftarrow":{x:708,y:222},"\\twoheadrightarrow":{x:745,y:222},"\\rightsquigarrow":{x:782,y:222},"\\mathcal{A}":{x:819,y:222},"\\mathcal{B}":{x:856,y:222},"\\mathcal{C}":{x:893,y:222},"\\mathcal{D}":{x:930,y:222},"\\mathcal{E}":{x:967,y:222},"\\mathcal{F}":{x:1004,y:222},"\\mathcal{G}":{x:1041,y:222},"\\mathcal{H}":{x:1078,y:222},"\\mathcal{I}":{x:5,y:259},"\\mathcal{J}":{x:42,y:259},"\\mathcal{K}":{x:79,y:259},"\\mathcal{L}":{x:116,y:259},"\\mathcal{M}":{x:153,y:259},"\\mathcal{N}":{x:190,y:259},"\\mathcal{O}":{x:227,y:259},"\\mathcal{P}":{x:264,y:259},"\\mathcal{Q}":{x:301,y:259},"\\mathcal{R}":{x:338,y:259},"\\mathcal{S}":{x:375,y:259},"\\mathcal{T}":{x:412,y:259},"\\mathcal{U}":{x:449,y:259},"\\mathcal{V}":{x:486,y:259},"\\mathcal{W}":{x:523,y:259},"\\mathcal{X}":{x:560,y:259},"\\mathcal{Y}":{x:597,y:259},"\\mathcal{Z}":{x:634,y:259},"\\mathfrak{A}":{x:671,y:259},"\\mathfrak{B}":{x:708,y:259},"\\mathfrak{C}":{x:745,y:259},"\\mathfrak{D}":{x:782,y:259},"\\mathfrak{E}":{x:819,y:259},"\\mathfrak{F}":{x:856,y:259},"\\mathfrak{G}":{x:893,y:259},"\\mathfrak{H}":{x:930,y:259},"\\mathfrak{I}":{x:967,y:259},"\\mathfrak{J}":{x:1004,y:259},"\\mathfrak{K}":{x:1041,y:259},"\\mathfrak{L}":{x:1078,y:259},"\\mathfrak{M}":{x:5,y:296},"\\mathfrak{N}":{x:42,y:296},"\\mathfrak{O}":{x:79,y:296},"\\mathfrak{P}":{x:116,y:296},"\\mathfrak{Q}":{x:153,y:296},"\\mathfrak{R}":{x:190,y:296},"\\mathfrak{S}":{x:227,y:296},"\\mathfrak{T}":{x:264,y:296},"\\mathfrak{U}":{x:301,y:296},"\\mathfrak{V}":{x:338,y:296},"\\mathfrak{W}":{x:375,y:296},"\\mathfrak{X}":{x:412,y:296},"\\mathfrak{Y}":{x:449,y:296},"\\mathfrak{Z}":{x:486,y:296},"\\mathfrak{a}":{x:523,y:296},"\\mathfrak{b}":{x:560,y:296},"\\mathfrak{c}":{x:597,y:296},"\\mathfrak{d}":{x:634,y:296},"\\mathfrak{e}":{x:671,y:296},"\\mathfrak{f}":{x:708,y:296},"\\mathfrak{g}":{x:745,y:296},"\\mathfrak{h}":{x:782,y:296},"\\mathfrak{i}":{x:819,y:296},"\\mathfrak{j}":{x:856,y:296},"\\mathfrak{k}":{x:893,y:296},"\\mathfrak{l}":{x:930,y:296},"\\mathfrak{m}":{x:967,y:296},"\\mathfrak{n}":{x:1004,y:296},"\\mathfrak{o}":{x:1041,y:296},"\\mathfrak{p}":{x:1078,y:296},"\\mathfrak{q}":{x:5,y:333},"\\mathfrak{r}":{x:42,y:333},"\\mathfrak{s}":{x:79,y:333},"\\mathfrak{t}":{x:116,y:333},"\\mathfrak{u}":{x:153,y:333},"\\mathfrak{v}":{x:190,y:333},"\\mathfrak{w}":{x:227,y:333},"\\mathfrak{x}":{x:264,y:333},"\\mathfrak{y}":{x:301,y:333},"\\mathfrak{z}":{x:338,y:333},"\\mathbb{A}":{x:375,y:333},"\\mathbb{B}":{x:412,y:333},"\\mathbb{C}":{x:449,y:333},"\\mathbb{D}":{x:486,y:333},"\\mathbb{E}":{x:523,y:333},"\\mathbb{F}":{x:560,y:333},"\\mathbb{G}":{x:597,y:333},"\\mathbb{H}":{x:634,y:333},"\\mathbb{I}":{x:671,y:333},"\\mathbb{J}":{x:708,y:333},"\\mathbb{K}":{x:745,y:333},"\\mathbb{L}":{x:782,y:333},"\\mathbb{M}":{x:819,y:333},"\\mathbb{N}":{x:856,y:333},"\\mathbb{O}":{x:893,y:333},"\\mathbb{P}":{x:930,y:333},"\\mathbb{Q}":{x:967,y:333},"\\mathbb{R}":{x:1004,y:333},"\\mathbb{S}":{x:1041,y:333},"\\mathbb{T}":{x:1078,y:333},"\\mathbb{U}":{x:5,y:370},"\\mathbb{V}":{x:42,y:370},"\\mathbb{W}":{x:79,y:370},"\\mathbb{X}":{x:116,y:370},"\\mathbb{Y}":{x:153,y:370},"\\mathbb{Z}":{x:190,y:370},"\\mathrm{A}":{x:227,y:370},"\\mathrm{B}":{x:264,y:370},"\\mathrm{C}":{x:301,y:370},"\\mathrm{D}":{x:338,y:370},"\\mathrm{E}":{x:375,y:370},"\\mathrm{F}":{x:412,y:370},"\\mathrm{G}":{x:449,y:370},"\\mathrm{H}":{x:486,y:370},"\\mathrm{I}":{x:523,y:370},"\\mathrm{J}":{x:560,y:370},"\\mathrm{K}":{x:597,y:370},"\\mathrm{L}":{x:634,y:370},"\\mathrm{M}":{x:671,y:370},"\\mathrm{N}":{x:708,y:370},"\\mathrm{O}":{x:745,y:370},"\\mathrm{P}":{x:782,y:370},"\\mathrm{Q}":{x:819,y:370},"\\mathrm{R}":{x:856,y:370},"\\mathrm{S}":{x:893,y:370},"\\mathrm{T}":{x:930,y:370},"\\mathrm{U}":{x:967,y:370},"\\mathrm{V}":{x:1004,y:370},"\\mathrm{W}":{x:1041,y:370},"\\mathrm{X}":{x:1078,y:370},"\\mathrm{Y}":{x:5,y:407},"\\mathrm{Z}":{x:42,y:407},"\\mathrm{a}":{x:79,y:407},"\\mathrm{b}":{x:116,y:407},"\\mathrm{c}":{x:153,y:407},"\\mathrm{d}":{x:190,y:407},"\\mathrm{e}":{x:227,y:407},"\\mathrm{f}":{x:264,y:407},"\\mathrm{g}":{x:301,y:407},"\\mathrm{h}":{x:338,y:407},"\\mathrm{i}":{x:375,y:407},"\\mathrm{j}":{x:412,y:407},"\\mathrm{k}":{x:449,y:407},"\\mathrm{l}":{x:486,y:407},"\\mathrm{m}":{x:523,y:407},"\\mathrm{n}":{x:560,y:407},"\\mathrm{o}":{x:597,y:407},"\\mathrm{p}":{x:634,y:407},"\\mathrm{q}":{x:671,y:407},"\\mathrm{r}":{x:708,y:407},"\\mathrm{s}":{x:745,y:407},"\\mathrm{t}":{x:782,y:407},"\\mathrm{u}":{x:819,y:407},"\\mathrm{v}":{x:856,y:407},"\\mathrm{w}":{x:893,y:407},"\\mathrm{x}":{x:930,y:407},"\\mathrm{y}":{x:967,y:407},"\\mathrm{z}":{x:1004,y:407}}}},b[31]={value:function(){var a=b.r(4),c=b.r(20),d={min:1,max:2},e=c.createClass("ScrollZoomController",{constructor:function(b,c,e,f){this.kfEditor=c,this.target=e,this.zoom=1,this.step=.05,this.options=a.extend({},d,f),this.initEvent()},initEvent:function(){var b=this.kfEditor,c=this,d=this.options.min,e=this.options.max,f=this.step;a.addEvent(this.target,"mousewheel",function(a){a.preventDefault(),a.wheelDelta<0?c.zoom-=c.zoom*f:c.zoom+=c.zoom*f,c.zoom=Math.max(c.zoom,d),c.zoom=Math.min(c.zoom,e),b.requestService("render.set.canvas.zoom",c.zoom)})}});return e}},b[32]={value:function(){return{VIEW_STATE:{NO_OVERFLOW:0,OVERFLOW:1},scrollbar:{step:50,thumbMinSize:50}}}},b[33]={value:function(){return{"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}":{pos:{x:0,y:0},size:{width:310,height:73}},"{\\placeholder/\\placeholder}":{pos:{x:315,y:0},size:{width:56,height:75}},"\\frac \\placeholder\\placeholder":{pos:{x:376,y:0},size:{width:56,height:75}},"a^2+b^2=c^2":{pos:{x:437,y:0},size:{width:310,height:73}},"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}":{pos:{x:752,y:0},size:{width:310,height:73}},"\\frac {dy}{dx}":{pos:{x:1067,y:0},size:{width:56,height:75}},"\\frac {\\Delta y}{\\Delta x}":{pos:{x:1128,y:0},size:{width:56,height:75}},"\\frac {\\delta y}{\\delta x}":{pos:{x:1189,y:0},size:{width:56,height:75}},"\\frac \\pi 2":{pos:{x:1250,y:0},size:{width:56,height:75}},"\\placeholder^\\placeholder":{pos:{x:1311,y:0},size:{width:56,height:75}},"\\placeholder^\\placeholder_\\placeholder":{pos:{x:1372,y:0},size:{width:56,height:75}},"\\placeholder_\\placeholder":{pos:{x:1433,y:0},size:{width:56,height:75}},"{^\\placeholder_\\placeholder\\placeholder}":{pos:{x:1494,y:0},size:{width:56,height:75}},"e^{-i\\omega t}":{pos:{x:1555,y:0},size:{width:56,height:75}},"x^2":{pos:{x:1616,y:0},size:{width:56,height:75}},"{}^n_1Y":{pos:{x:1677,y:0},size:{width:56,height:75}},"\\sqrt \\placeholder":{pos:{x:1738,y:0},size:{width:56,height:75}},"\\sqrt [\\placeholder] \\placeholder":{pos:{x:1799,y:0},size:{width:56,height:75}},"\\sqrt [2] \\placeholder":{pos:{x:1860,y:0},size:{width:56,height:75}},"\\sqrt [3] \\placeholder":{pos:{x:1921,y:0},size:{width:56,height:75}},"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}":{pos:{x:1982,y:0},size:{width:137,height:75}},"\\sqrt {a^2+b^2}":{pos:{x:2124,y:0},size:{width:137,height:75}},"\\int \\placeholder":{pos:{x:2266,y:0},size:{width:56,height:75}},"\\int^\\placeholder_\\placeholder\\placeholder":{pos:{x:2327,y:0},size:{width:56,height:75}},"\\iint\\placeholder":{pos:{x:2388,y:0},size:{width:56,height:75}},"\\iint^\\placeholder_\\placeholder\\placeholder":{pos:{x:2449,y:0},size:{width:56,height:75}},"\\iiint\\placeholder":{pos:{x:2510,y:0},size:{width:56,height:75}},"\\iiint^\\placeholder_\\placeholder\\placeholder":{pos:{x:2571,y:0},size:{width:56,height:75}},"\\sum\\placeholder":{pos:{x:2632,y:0},size:{width:56,height:75}},"\\sum^\\placeholder_\\placeholder\\placeholder":{pos:{x:2693,y:0},size:{width:56,height:75}},"\\sum_\\placeholder\\placeholder":{pos:{x:2754,y:0},size:{width:56,height:75}},"\\left(\\placeholder\\right)":{pos:{x:2815,y:0},size:{width:56,height:75}},"\\left[\\placeholder\\right]":{pos:{x:2876,y:0},size:{width:56,height:75}},"\\left\\{\\placeholder\\right\\}":{pos:{x:2937,y:0},size:{width:56,height:75}},"\\left|\\placeholder\\right|":{pos:{x:2998,y:0},size:{width:56,height:75}},"\\sin\\placeholder":{pos:{x:3059,y:0},size:{width:56,height:75}},"\\cos\\placeholder":{pos:{x:3120,y:0},size:{width:56,height:75}},"\\tan\\placeholder":{pos:{x:3181,y:0},size:{width:56,height:75}},"\\csc\\placeholder":{pos:{x:3242,y:0},size:{width:56,height:75}},"\\sec\\placeholder":{pos:{x:3303,y:0},size:{width:56,height:75}},"\\cot\\placeholder":{pos:{x:3364,y:0},size:{width:56,height:75}},"\\sin\\theta":{pos:{x:3425,y:0},size:{width:56,height:75}},"\\cos{2x}":{pos:{x:3486,y:0},size:{width:56,height:75}},"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}":{pos:{x:3547,y:0},size:{width:137,height:75}}}}},b[34]={value:function(){function a(a){var b=[],c=a.path,d=a.values;return e.Utils.each(d,function(a){var d=a,e=a;"string"!=typeof a?(d=a.img,e=a.key):e="\\"+a,b.push({item:{show:""+c+d.toLowerCase()+".png",val:e}})}),b}var c=b.r(41),d=b.r(40),e=b.r(20),f=[{type:c.DRAPDOWN_BOX,options:{button:{label:"\u9884\u8bbe<br/>",className:"yushe-btn",icon:"assets/images/toolbar/button/fx.png",iconSize:{w:40}},box:{width:367,group:[{title:"\u9884\u8bbe\u516c\u5f0f",items:[{title:"\u9884\u8bbe\u516c\u5f0f",content:[{label:"\u4e8c\u6b21\u516c\u5f0f",item:{show:"assets/images/toolbar/ys/1.png",val:"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}"}},{label:"\u4e8c\u9879\u5f0f\u5b9a\u7406",item:{show:"assets/images/toolbar/ys/2.png",val:"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}"}},{label:"\u52fe\u80a1\u5b9a\u7406",item:{show:"assets/images/toolbar/ys/3.png",val:"a^2+b^2=c^2"}}]}]}]}}},{type:c.DELIMITER},{type:c.AREA,options:{box:{fixOffset:!0,width:527,type:d.OVERLAP,group:[{title:"\u57fa\u7840\u6570\u5b66",items:[]},{title:"\u5e0c\u814a\u5b57\u6bcd",items:[]},{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",items:[]},{title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",items:[]},{title:"\u7bad\u5934",items:[]},{title:"\u624b\u5199\u4f53",items:[]}]}}},{type:c.DELIMITER},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5206\u6570<br/>",icon:"assets/images/toolbar/button/frac.png"},box:{width:332,group:[{title:"\u5206\u6570",items:[{title:"\u5206\u6570",content:[{item:{show:"assets/images/toolbar/frac/1.png",val:"\\frac \\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/frac/2.png",val:"{\\placeholder/\\placeholder}"}}]},{title:"\u5e38\u7528\u5206\u6570",content:[{item:{show:"assets/images/toolbar/frac/c1.png",val:"\\frac {dy}{dx}"}},{item:{show:"assets/images/toolbar/frac/c2.png",val:"\\frac {\\Delta y}{\\Delta x}"}},{item:{show:"assets/images/toolbar/frac/c4.png",val:"\\frac {\\delta y}{\\delta x}"}},{item:{show:"assets/images/toolbar/frac/c5.png",val:"\\frac \\pi 2"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u4e0a\u4e0b\u6807<br/>",icon:"assets/images/toolbar/button/script.png"},box:{width:332,group:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",items:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{show:"assets/images/toolbar/script/1.png",val:"\\placeholder^\\placeholder"}},{item:{show:"assets/images/toolbar/script/2.png",val:"\\placeholder_\\placeholder"}},{item:{show:"assets/images/toolbar/script/3.png",val:"\\placeholder^\\placeholder_\\placeholder"}},{item:{show:"assets/images/toolbar/script/4.png",val:"{^\\placeholder_\\placeholder\\placeholder}"}}]},{title:"\u5e38\u7528\u7684\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{show:"assets/images/toolbar/script/c1.png",val:"e^{-i\\omega t}"}},{item:{show:"assets/images/toolbar/script/c2.png",val:"x^2"}},{item:{show:"assets/images/toolbar/script/c3.png",val:"{}^n_1Y"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u6839\u5f0f<br/>",icon:"assets/images/toolbar/button/sqrt.png"},box:{width:342,group:[{title:"\u6839\u5f0f",items:[{title:"\u6839\u5f0f",content:[{item:{show:"assets/images/toolbar/sqrt/1.png",val:"\\sqrt \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/2.png",val:"\\sqrt [\\placeholder] \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/3.png",val:"\\sqrt [2] \\placeholder"}},{item:{show:"assets/images/toolbar/sqrt/4.png",val:"\\sqrt [3] \\placeholder"}}]},{title:"\u5e38\u7528\u6839\u5f0f",content:[{item:{show:"assets/images/toolbar/sqrt/c1.png",val:"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}"}},{item:{show:"assets/images/toolbar/sqrt/c2.png",val:"\\sqrt {a^2+b^2}"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u79ef\u5206<br/>",icon:"assets/images/toolbar/button/int.png"},box:{width:332,group:[{title:"\u79ef\u5206",items:[{title:"\u79ef\u5206",content:[{item:{show:"assets/images/toolbar/int/1.png",val:"\\int \\placeholder"}},{item:{show:"assets/images/toolbar/int/2.png",val:"\\int^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/int/3.png",val:"\\iint\\placeholder"}},{item:{show:"assets/images/toolbar/int/4.png",val:"\\iint^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/int/5.png",val:"\\iiint\\placeholder"}},{item:{show:"assets/images/toolbar/int/6.png",val:"\\iiint^\\placeholder_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5927\u578b<br/>\u8fd0\u7b97\u7b26",icon:"assets/images/toolbar/button/sum.png"},box:{width:332,group:[{title:"\u6c42\u548c",items:[{title:"\u6c42\u548c",content:[{item:{show:"assets/images/toolbar/large/1.png",val:"\\sum\\placeholder"}},{item:{show:"assets/images/toolbar/large/2.png",val:"\\sum^\\placeholder_\\placeholder\\placeholder"}},{item:{show:"assets/images/toolbar/large/3.png",val:"\\sum_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u62ec\u53f7<br/>",icon:"assets/images/toolbar/button/brackets.png"},box:{width:332,group:[{title:"\u65b9\u62ec\u53f7",items:[{title:"\u65b9\u62ec\u53f7",content:[{item:{show:"assets/images/toolbar/brackets/1.png",val:"\\left(\\placeholder\\right)"}},{item:{show:"assets/images/toolbar/brackets/2.png",val:"\\left[\\placeholder\\right]"}},{item:{show:"assets/images/toolbar/brackets/3.png",val:"\\left\\{\\placeholder\\right\\}"}},{item:{show:"assets/images/toolbar/brackets/4.png",val:"\\left|\\placeholder\\right|"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u51fd\u6570<br/>",icon:"assets/images/toolbar/button/sin.png"},box:{width:340,group:[{title:"\u51fd\u6570",items:[{title:"\u4e09\u89d2\u51fd\u6570",content:[{item:{show:"assets/images/toolbar/func/1.png",val:"\\sin\\placeholder"}},{item:{show:"assets/images/toolbar/func/2.png",val:"\\cos\\placeholder"}},{item:{show:"assets/images/toolbar/func/3.png",val:"\\tan\\placeholder"}},{item:{show:"assets/images/toolbar/func/4.png",val:"\\csc\\placeholder"}},{item:{show:"assets/images/toolbar/func/5.png",val:"\\sec\\placeholder"}},{item:{show:"assets/images/toolbar/func/6.png",val:"\\cot\\placeholder"}}]},{title:"\u5e38\u7528\u51fd\u6570",content:[{item:{show:"assets/images/toolbar/func/c1.png",val:"\\sin\\theta"}},{item:{show:"assets/images/toolbar/func/c2.png",val:"\\sin{2x}"}},{item:{show:"assets/images/toolbar/func/c3.png",val:"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}"}}]}]}]}}}];
return function(){var b=["pm","infty",{key:"=",img:"eq"},"sim","times","div",{key:"!",img:"tanhao"},{key:"<",img:"lt"},"ll",{key:">",img:"gt"},"gg","leq","geq","mp","cong","equiv","propto","approx","forall","partial","surd","cup","cap","varnothing",{key:"%",img:"baifenhao"},"circ","exists","nexists","in","ni","gets","uparrow","to","downarrow","leftrightarrow","therefore","because",{key:"+",img:"plus"},{key:"-",img:"minus"},"neg","ast","cdot","vdots","ddots","aleph","beth","blacksquare"],c=f[2].options.box.group[0].items;c.push({title:"\u57fa\u7840\u6570\u5b66",content:a({path:"assets/images/toolbar/char/math/",values:b})})}(),function(){var b=[{title:"\u5c0f\u5199",values:["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"]},{title:"\u5927\u5199",values:["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"]},{title:"\u53d8\u4f53",values:["digamma","varepsilon","varkappa","varphi","varpi","varrho","varsigma","vartheta"]}],c=f[2].options.box.group[1].items;c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/greek/lower/",values:b[0].values})}),c.push({title:b[1].title,content:a({path:"assets/images/toolbar/char/greek/upper/",values:b[1].values})}),c.push({title:b[2].title,content:a({path:"assets/images/toolbar/char/greek/misc/",values:b[2].values})})}(),function(){var b=[{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",values:["neq","nless","ngtr","nleq","ngeq","nsim","lneqq","gneqq","nprec","nsucc","notin","nsubseteq","nsupseteq","subsetneq","supsetneq","lnsim","gnsim","precnsim","succnsim","ntriangleleft","ntriangleright","ntrianglelefteq","ntrianglerighteq","nmid","nparallel","nvdash",{key:"\\nVdash",img:"nvdash-1"},{key:"\\nvDash",img:"nvdash-2"},{key:"\\nVDash",img:"nvdash-3"},"nexists"]}],c=f[2].options.box.group[2].items;c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/not/",values:b[0].values})})}(),function(){var b=["aleph","beth","daleth","gimel","complement","ell","eth","hbar","hslash","mho","partial","wp","circledS","Bbbk","Finv","Game","Im","Re"],c=f[2].options.box.group[3].items;c.push({title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",content:a({path:"assets/images/toolbar/alphabetic/",values:b})})}(),function(){var b=["gets","to","uparrow","downarrow","leftrightarrow","updownarrow",{key:"\\Leftarrow",img:"u-leftarrow"},{key:"\\Rightarrow",img:"u-rightarrow"},{key:"\\Uparrow",img:"u-uparrow"},{key:"\\Downarrow",img:"u-downarrow"},{key:"\\Leftrightarrow",img:"u-leftrightarrow"},{key:"\\Updownarrow",img:"u-updownarrow"},"longleftarrow","longrightarrow","longleftrightarrow",{key:"\\Longleftarrow",img:"u-longleftarrow"},{key:"\\Longrightarrow",img:"u-longrightarrow"},{key:"\\Longleftrightarrow",img:"u-longleftrightarrow"},"nearrow","nwarrow","searrow","swarrow","nleftarrow","nrightarrow",{key:"\\nLeftarrow",img:"u-nleftarrow"},{key:"\\nRightarrow",img:"u-nrightarrow"},{key:"\\nLeftrightarrow",img:"u-nleftrightarrow"},"leftharpoonup","leftharpoondown","rightharpoonup","rightharpoondown","upharpoonleft","upharpoonright","downharpoonleft","downharpoonright","leftrightharpoons","rightleftharpoons","leftleftarrows","rightrightarrows","upuparrows","downdownarrows","leftrightarrows","rightleftarrows","looparrowleft","looparrowright","leftarrowtail","rightarrowtail",{key:"\\Lsh",img:"u-lsh"},{key:"\\Rsh",img:"u-rsh"},{key:"\\Lleftarrow",img:"u-lleftarrow"},{key:"\\Rrightarrow",img:"u-rrightarrow"},"curvearrowleft","curvearrowright","circlearrowleft","circlearrowright","multimap","leftrightsquigarrow","twoheadleftarrow","twoheadrightarrow","rightsquigarrow"],c=f[2].options.box.group[4].items;c.push({title:"\u7bad\u5934",content:a({path:"assets/images/toolbar/arrow/",values:b})})}(),function(){var b=[{title:"\u624b\u5199\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u82b1\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]},{title:"\u53cc\u7ebf",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u7f57\u9a6c",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]}],c=f[2].options.box.group[5].items;e.Utils.each(b[0].values,function(a,c){b[0].values[c]={key:"\\mathcal{"+a+"}",img:a.toLowerCase()}}),e.Utils.each(b[1].values,function(a,c){b[1].values[c]={key:"\\mathfrak{"+a+"}",img:a.replace(/[A-Z]/,function(a){return"u"+a.toLowerCase()})}}),e.Utils.each(b[2].values,function(a,c){b[2].values[c]={key:"\\mathbb{"+a+"}",img:a.toLowerCase()}}),e.Utils.each(b[3].values,function(a,c){b[3].values[c]={key:"\\mathrm{"+a+"}",img:a.replace(/[A-Z]/,function(a){return"u"+a.toLowerCase()})}}),c.push({title:b[0].title,content:a({path:"assets/images/toolbar/char/cal/",values:b[0].values})}),c.push({title:b[1].title,content:a({path:"assets/images/toolbar/char/frak/",values:b[1].values})}),c.push({title:b[2].title,content:a({path:"assets/images/toolbar/char/bb/",values:b[2].values})}),c.push({title:b[3].title,content:a({path:"assets/images/toolbar/char/rm/",values:b[3].values})})}(),window.iconConfig=f,f}},b[35]={value:function(){function a(a,b){var c=[];return g.Utils.each(a,function(a){a.length>1&&(a="\\"+a),c.push({key:a,img:b,pos:e[a]})}),c}var c=b.r(41),d=b.r(40),e=b.r(30),f=b.r(33),g=b.r(20),h=[{type:c.DRAPDOWN_BOX,options:{button:{label:"\u9884\u8bbe<br/>",className:"yushe-btn",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:0,y:0},iconSize:{w:40}},box:{width:367,group:[{title:"\u9884\u8bbe\u516c\u5f0f",items:[{title:"\u9884\u8bbe\u516c\u5f0f",content:[{label:"\u4e8c\u6b21\u516c\u5f0f",item:{val:"x=\\frac {-b\\pm\\sqrt {b^2-4ac}}{2a}"}},{label:"\u4e8c\u9879\u5f0f\u5b9a\u7406",item:{val:"{\\left(x+a\\right)}^2=\\sum^n_{k=0}{\\left(^n_k\\right)x^ka^{n-k}}"}},{label:"\u52fe\u80a1\u5b9a\u7406",item:{val:"a^2+b^2=c^2"}}]}]}]}}},{type:c.DELIMITER},{type:c.AREA,options:{box:{fixOffset:!0,width:527,type:d.OVERLAP,group:[{title:"\u57fa\u7840\u6570\u5b66",items:[]},{title:"\u5e0c\u814a\u5b57\u6bcd",items:[]},{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",items:[]},{title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",items:[]},{title:"\u7bad\u5934",items:[]},{title:"\u624b\u5199\u4f53",items:[]}]}}},{type:c.DELIMITER},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5206\u6570<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:45,y:0}},box:{width:332,group:[{title:"\u5206\u6570",items:[{title:"\u5206\u6570",content:[{item:{val:"\\frac \\placeholder\\placeholder"}},{item:{val:"{\\placeholder/\\placeholder}"}}]},{title:"\u5e38\u7528\u5206\u6570",content:[{item:{val:"\\frac {dy}{dx}"}},{item:{val:"\\frac {\\Delta y}{\\Delta x}"}},{item:{val:"\\frac {\\delta y}{\\delta x}"}},{item:{val:"\\frac \\pi 2"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u4e0a\u4e0b\u6807<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:82,y:0}},box:{width:332,group:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",items:[{title:"\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{val:"\\placeholder^\\placeholder"}},{item:{val:"\\placeholder_\\placeholder"}},{item:{val:"\\placeholder^\\placeholder_\\placeholder"}},{item:{val:"{^\\placeholder_\\placeholder\\placeholder}"}}]},{title:"\u5e38\u7528\u7684\u4e0a\u6807\u548c\u4e0b\u6807",content:[{item:{val:"e^{-i\\omega t}"}},{item:{val:"x^2"}},{item:{val:"{}^n_1Y"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u6839\u5f0f<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:119,y:0}},box:{width:342,group:[{title:"\u6839\u5f0f",items:[{title:"\u6839\u5f0f",content:[{item:{val:"\\sqrt \\placeholder"}},{item:{val:"\\sqrt [\\placeholder] \\placeholder"}},{item:{val:"\\sqrt [2] \\placeholder"}},{item:{val:"\\sqrt [3] \\placeholder"}}]},{title:"\u5e38\u7528\u6839\u5f0f",content:[{item:{val:"\\frac {-b\\pm\\sqrt{b^2-4ac}}{2a}"}},{item:{val:"\\sqrt {a^2+b^2}"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u79ef\u5206<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:156,y:0}},box:{width:332,group:[{title:"\u79ef\u5206",items:[{title:"\u79ef\u5206",content:[{item:{val:"\\int \\placeholder"}},{item:{val:"\\int^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\iint\\placeholder"}},{item:{val:"\\iint^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\iiint\\placeholder"}},{item:{val:"\\iiint^\\placeholder_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u5927\u578b<br/>\u8fd0\u7b97\u7b26",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:193,y:0}},box:{width:332,group:[{title:"\u6c42\u548c",items:[{title:"\u6c42\u548c",content:[{item:{val:"\\sum\\placeholder"}},{item:{val:"\\sum^\\placeholder_\\placeholder\\placeholder"}},{item:{val:"\\sum_\\placeholder\\placeholder"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u62ec\u53f7<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:230,y:0}},box:{width:332,group:[{title:"\u65b9\u62ec\u53f7",items:[{title:"\u65b9\u62ec\u53f7",content:[{item:{val:"\\left(\\placeholder\\right)"}},{item:{val:"\\left[\\placeholder\\right]"}},{item:{val:"\\left\\{\\placeholder\\right\\}"}},{item:{val:"\\left|\\placeholder\\right|"}}]}]}]}}},{type:c.DRAPDOWN_BOX,options:{button:{label:"\u51fd\u6570<br/>",icon:{src:"kityformula/assets/images/toolbar/btn.png",x:267,y:0}},box:{width:340,group:[{title:"\u51fd\u6570",items:[{title:"\u4e09\u89d2\u51fd\u6570",content:[{item:{val:"\\sin\\placeholder"}},{item:{val:"\\cos\\placeholder"}},{item:{val:"\\tan\\placeholder"}},{item:{val:"\\csc\\placeholder"}},{item:{val:"\\sec\\placeholder"}},{item:{val:"\\cot\\placeholder"}}]},{title:"\u5e38\u7528\u51fd\u6570",content:[{item:{val:"\\sin\\theta"}},{item:{val:"\\cos{2x}"}},{item:{val:"\\tan\\theta=\\frac {\\sin\\theta}{\\cos\\theta}"}}]}]}]}}}];return function(){var a=[],b="kityformula/assets/images/toolbar/other.png",d=[];g.Utils.each(h,function(b){b.type!==c.DELIMITER&&(b=b.options.box.group,a=a.concat(b))}),g.Utils.each(a,function(a){a=a.items;for(var b=0,c=a.length;c>b;b++)d=d.concat(a[b].content)}),g.Utils.each(d,function(a){var c=f[a.item.val];c&&(a.item.img=b,a.item.pos=c.pos,a.item.size=c.size)})}(),function(){var b=["pm","infty","=","sim","times","div","!","<","ll",">","gg","leq","geq","mp","cong","equiv","propto","approx","forall","partial","surd","cup","cap","varnothing","%","circ","exists","nexists","in","ni","gets","uparrow","to","downarrow","leftrightarrow","therefore","because","+","-","neg","ast","cdot","vdots","aleph","beth","blacksquare"],c=h[2].options.box.group[0].items;c.push({title:"\u57fa\u7840\u6570\u5b66",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u5c0f\u5199",values:["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"]},{title:"\u5927\u5199",values:["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"]},{title:"\u53d8\u4f53",values:["digamma","varepsilon","varkappa","varphi","varpi","varrho","varsigma","vartheta"]}],c=h[2].options.box.group[1].items;c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[1].title,content:a(b[1].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[2].title,content:a(b[2].values,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u6c42\u53cd\u5173\u7cfb\u8fd0\u7b97\u7b26",values:["neq","nless","ngtr","nleq","ngeq","nsim","lneqq","gneqq","nprec","nsucc","notin","nsubseteq","nsupseteq","subsetneq","supsetneq","lnsim","gnsim","precnsim","succnsim","ntriangleleft","ntriangleright","ntrianglelefteq","ntrianglerighteq","nmid","nparallel","nvdash","nVdash","nvDash","nVDash","nexists"]}],c=h[2].options.box.group[2].items;c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=["aleph","beth","daleth","gimel","complement","ell","eth","hbar","hslash","mho","partial","wp","circledS","Bbbk","Finv","Game","Im","Re"],c=h[2].options.box.group[3].items;c.push({title:"\u5b57\u6bcd\u7c7b\u7b26\u53f7",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=["gets","to","uparrow","downarrow","leftrightarrow","updownarrow","Leftarrow","Rightarrow","Uparrow","Downarrow","Leftrightarrow","Updownarrow","longleftarrow","longrightarrow","longleftrightarrow","Longleftarrow","Longrightarrow","Longleftrightarrow","nearrow","nwarrow","searrow","swarrow","nleftarrow","nrightarrow","nLeftarrow","nRightarrow","nLeftrightarrow","leftharpoonup","leftharpoondown","rightharpoonup","rightharpoondown","upharpoonleft","upharpoonright","downharpoonleft","downharpoonright","leftrightharpoons","rightleftharpoons","leftleftarrows","rightrightarrows","upuparrows","downdownarrows","leftrightarrows","rightleftarrows","looparrowleft","looparrowright","leftarrowtail","rightarrowtail","Lsh","Rsh","Lleftarrow","Rrightarrow","curvearrowleft","curvearrowright","circlearrowleft","circlearrowright","multimap","leftrightsquigarrow","twoheadleftarrow","twoheadrightarrow","rightsquigarrow"],c=h[2].options.box.group[4].items;c.push({title:"\u7bad\u5934",content:a(b,"kityformula/assets/images/toolbar/char.png")})}(),function(){var b=[{title:"\u624b\u5199\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u82b1\u4f53",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]},{title:"\u53cc\u7ebf",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]},{title:"\u7f57\u9a6c",values:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]}],c=h[2].options.box.group[5].items;g.Utils.each(b[0].values,function(a,c){b[0].values[c]="mathcal{"+a+"}"}),g.Utils.each(b[1].values,function(a,c){b[1].values[c]="mathfrak{"+a+"}"}),g.Utils.each(b[2].values,function(a,c){b[2].values[c]="mathbb{"+a+"}"}),g.Utils.each(b[3].values,function(a,c){b[3].values[c]="mathrm{"+a+"}"}),c.push({title:b[0].title,content:a(b[0].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[1].title,content:a(b[1].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[2].title,content:a(b[2].values,"kityformula/assets/images/toolbar/char.png")}),c.push({title:b[3].title,content:a(b[3].values,"kityformula/assets/images/toolbar/char.png")})}(),h}},b[36]={value:function(){function a(a,b,f){switch(a){case i.DRAPDOWN_BOX:return c(b,f);case i.DELIMITER:return d(b);case i.AREA:return e(b,f)}}function c(a,b){return new g.DrapdownBox(a,b)}function d(a){return new g.Delimiter(a)}function e(a,b){return new g.Area(a,b)}var f=b.r(20),g=b.r(48),h=b.r(47),i=b.r(41),j=f.createClass("Tollbar",{constructor:function(a,b,c){this.kfEditor=b,this.uiComponent=a,this.elementList=c,this.elements=[],this.initToolbarElements(),this.initServices(),this.initEvent()},initServices:function(){this.kfEditor.registerService("ui.toolbar.disable",this,{disableToolbar:this.disableToolbar}),this.kfEditor.registerService("ui.toolbar.enable",this,{enableToolbar:this.enableToolbar}),this.kfEditor.registerService("ui.toolbar.close",this,{closeToolbar:this.closeToolbar})},initEvent:function(){var a=this;h.on(this.uiComponent.toolbarContainer,"mousedown",function(a){a.preventDefault()}),h.on(this.uiComponent.toolbarContainer,"mousewheel",function(a){a.preventDefault()}),h.on(this.kfEditor.getContainer(),"mousedown",function(){a.notify("closeAll")}),h.subscribe("data.select",function(b){a.insertSource(b)})},insertSource:function(a){this.kfEditor.requestService("control.insert.string",a)},disableToolbar:function(){f.Utils.each(this.elements,function(a){a.disable&&a.disable()})},enableToolbar:function(){f.Utils.each(this.elements,function(a){a.enable&&a.enable()})},getContainer:function(){return this.kfEditor.requestService("ui.get.canvas.container")},closeToolbar:function(){this.closeElement()},notify:function(a){switch(a){case"closeAll":case"closeOther":return void this.closeElement(arguments[1])}},closeElement:function(a){f.Utils.each(this.elements,function(b){b!=a&&b.hide&&b.hide()})},initToolbarElements:function(){var b=this.elements,c=this.uiComponent.toolbarContainer.ownerDocument,d=this;f.Utils.each(this.elementList,function(e){var f=a(e.type,c,e.options);b.push(f),d.appendElement(f)})},appendElement:function(a){a.setToolbar(this),a.attachTo(this.uiComponent.toolbarContainer)}});return j}},b[37]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=66,e=b.r(47),f=b.r(38),g=a.createClass("Area",{constructor:function(a,b){this.options=b,this.doc=a,this.toolbar=null,this.disabled=!0,this.panelIndex=0,this.maxPanelIndex=0,this.currentItemCount=0,this.lineMaxCount=9,this.element=this.createArea(),this.container=this.createContainer(),this.panel=this.createPanel(),this.buttonContainer=this.createButtonContainer(),this.button=this.createButton(),this.mountPoint=this.createMountPoint(),this.moveDownButton=this.createMoveDownButton(),this.moveUpButton=this.createMoveUpButton(),this.boxObject=this.createBox(),this.mergeElement(),this.mount(),this.setListener(),this.initEvent()},initEvent:function(){var a=this;e.on(this.button,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.showMount(),a.toolbar.notify("closeOther",a))}),e.on(this.moveDownButton,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.nextPanel(),a.toolbar.notify("closeOther",a))}),e.on(this.moveUpButton,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1!==b.which||a.disabled||(a.prevPanel(),a.toolbar.notify("closeOther",a))}),e.delegate(this.container,".kf-editor-ui-area-item","mousedown",function(b){b.preventDefault(),1!==b.which||a.disabled||e.publish("data.select",this.getAttribute("data-value"))}),this.boxObject.initEvent()},disable:function(){this.disabled=!0,this.boxObject.disable(),e.getClassList(this.element).remove(c+"enabled")},enable:function(){this.disabled=!1,this.boxObject.enable(),e.getClassList(this.element).add(c+"enabled")},setListener:function(){var a=this;this.boxObject.setSelectHandler(function(b){e.publish("data.select",b),a.hide()}),this.boxObject.setChangeHandler(function(){a.updateContent()})},createArea:function(){var a=e.ele(this.doc,"div",{className:c+"area"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a},checkMaxPanelIndex:function(){this.maxPanelIndex=Math.ceil(this.currentItemCount/this.lineMaxCount/2)},updateContent:function(){var b=this.boxObject.getOverlapContent(),d=0,e=null,f=0,g=0,h=this.lineMaxCount,i=[];this.panel.innerHTML="",a.Utils.each(b,function(b){var j=b.content;a.Utils.each(j,function(a){f=Math.floor(d/h),g=d%h,d++,e="top: "+(33*f+5)+"px; left: "+(32*g+5)+"px;",i.push('<div class="'+c+'area-item" data-value="'+a.key+'" style="'+e+'"><div class="'+c+'area-item-inner"><div class="'+c+'area-item-img" style="background: url('+a.img+") no-repeat "+-a.pos.x+"px "+-a.pos.y+'px;"></div></div></div>')})}),this.currentItemCount=d,this.panelIndex=0,this.panel.style.top=0,this.panel.innerHTML=i.join(""),this.checkMaxPanelIndex(),this.updatePanelButtonState()},mount:function(){this.boxObject.mountTo(this.mountPoint)},showMount:function(){this.mountPoint.style.display="block",this.boxObject.updateSize()},hideMount:function(){this.mountPoint.style.display="none"},hide:function(){this.hideMount(),this.boxObject.hide()},createButton:function(){return e.ele(this.doc,"div",{className:c+"area-button"})},createMoveDownButton:function(){return e.ele(this.doc,"div",{className:c+"movedown-button",content:""})},createMoveUpButton:function(){return e.ele(this.doc,"div",{className:c+"moveup-button",content:""})},createMountPoint:function(){return e.ele(this.doc,"div",{className:c+"area-mount"})},createBox:function(){return new f(this.doc,this.options.box)},createContainer:function(){return e.ele(this.doc,"div",{className:c+"area-container"})},createPanel:function(){return e.ele(this.doc,"div",{className:c+"area-panel"})},createButtonContainer:function(){return e.ele(this.doc,"div",{className:c+"area-button-container"})},mergeElement:function(){this.buttonContainer.appendChild(this.moveUpButton),this.buttonContainer.appendChild(this.moveDownButton),this.buttonContainer.appendChild(this.button),this.container.appendChild(this.panel),this.element.appendChild(this.container),this.element.appendChild(this.buttonContainer),this.element.appendChild(this.mountPoint)},disablePanelUp:function(){this.disabledUp=!0,e.getClassList(this.moveUpButton).add("kf-editor-ui-disabled")},enablePanelUp:function(){this.disabledUp=!1,e.getClassList(this.moveUpButton).remove("kf-editor-ui-disabled")},disablePanelDown:function(){this.disabledDown=!0,e.getClassList(this.moveDownButton).add("kf-editor-ui-disabled")},enablePanelDown:function(){this.disabledDown=!1,e.getClassList(this.moveDownButton).remove("kf-editor-ui-disabled")},updatePanelButtonState:function(){0===this.panelIndex?this.disablePanelUp():this.enablePanelUp(),this.panelIndex+1>=this.maxPanelIndex?this.disablePanelDown():this.enablePanelDown()},nextPanel:function(){this.disabledDown||this.panelIndex+1>=this.maxPanelIndex||(this.panelIndex++,this.panel.style.top=-this.panelIndex*d+"px",this.updatePanelButtonState())},prevPanel:function(){this.disabledUp||0!==this.panelIndex&&(this.panelIndex--,this.panel.style.top=-this.panelIndex*d+"px",this.updatePanelButtonState())},setToolbar:function(a){this.toolbar=a,this.boxObject.setToolbar(a)},attachTo:function(a){a.appendChild(this.element),this.updateContent(),this.updatePanelButtonState()}});return g}},b[38]={value:function(){function a(a,b,c){var d=[];return h.Utils.each(b,function(b){d.push(new q(c,a,b))}),d}function c(a){return j.ele(a,"div",{className:i+"overlap-container"})}function d(a,b){return new m(a,{className:"overlap-button",label:"",fixOffset:b.fixOffset})}function e(a,b){return new n(a,b)}function f(a){return a.getBoundingClientRect()}function g(a){var b="background: url( "+a.img+" ) no-repeat ";return b+=-a.pos.x+"px ",b+=-a.pos.y+"px;",b+=" width: "+a.size.width+"px;",b+=" height: "+a.size.height+"px;"}var h=b.r(20),i="kf-editor-ui-",j=b.r(47),k=b.r(40),l=b.r(42),m=b.r(39),n=b.r(45),o=20,p=h.createClass("Box",{constructor:function(a,b){this.options=b,this.toolbar=null,this.options.type=this.options.type||k.DETACHED,this.doc=a,this.itemPanels=null,this.overlapButtonObject=null,this.overlapIndex=-1,this.element=this.createBox(),this.groupContainer=this.createGroupContainer(),this.itemGroups=this.createItemGroup(),this.mergeElement()},createBox:function(){var a=j.ele(this.doc,"div",{className:i+"box"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a},setToolbar:function(a){this.toolbar=a,this.overlapButtonObject&&this.overlapButtonObject.setToolbar(a)},updateSize:function(){var a=j.getRectBox(this.toolbar.getContainer()),b=30,c=j.getRectBox(this.element);if(this.options.type===k.DETACHED){if(c.bottom<=a.bottom)return void(this.element.scrollTop=0);this.element.style.height=c.height-(c.bottom-a.bottom+b)+"px"}else{var d=this.getCurrentItemPanel(),e=null;if(d.scrollTop=0,c.bottom<=a.bottom)return;e=f(d),d.style.height=a.bottom-e.top-b+"px"}},initEvent:function(){var a="."+i+"box-item",b=this;j.delegate(this.groupContainer,a,"mousedown",function(a){a.preventDefault(),1===a.which&&b.onselectHandler&&b.onselectHandler(this.getAttribute("data-value"))}),j.on(this.element,"mousedown",function(a){a.stopPropagation(),a.preventDefault()}),j.on(this.element,"mousewheel",function(a){a.preventDefault(),a.stopPropagation(),b.scroll(a.originalEvent.wheelDelta)})},getNode:function(){return this.element},setSelectHandler:function(a){this.onselectHandler=a},scroll:function(a){0>a?this.scrollDown():(this.scrollUp(),this.element.scrollTop-=20)},scrollDown:function(){this.options.type===k.DETACHED?this.element.scrollTop+=o:this.getCurrentItemPanel().scrollTop+=o},scrollUp:function(){this.options.type===k.DETACHED?this.element.scrollTop-=o:this.getCurrentItemPanel().scrollTop-=o},setChangeHandler:function(a){this.onchangeHandler=a},onchangeHandler:function(){},createGroupContainer:function(){return j.ele(this.doc,"div",{className:i+"box-container"})},getPositionInfo:function(){return j.getRectBox(this.element)},createItemGroup:function(){var a=this.createGroup();switch(this.options.type){case k.DETACHED:return a.items[0];case k.OVERLAP:return this.createOverlapGroup(a)}return null},enable:function(){this.overlapButtonObject&&this.overlapButtonObject.enable()},disable:function(){this.overlapButtonObject&&this.overlapButtonObject.disable()},hide:function(){this.overlapButtonObject&&this.overlapButtonObject.hideMount()},getOverlapContent:function(){return this.options.type!==k.OVERLAP?null:this.options.group[this.overlapIndex].items},createOverlapGroup:function(a){var b=a.title,f=this,g=c(this.doc),k=d(this.doc,{fixOffset:this.options.fixOffset}),l=e(this.doc,{width:150,items:b}),m=j.ele(this.doc,"div",{className:i+"wrap-group"});return this.overlapButtonObject=k,k.mount(l),k.initEvent(),l.initEvent(),h.Utils.each(a.items,function(b,c){var d=m.cloneNode(!1);h.Utils.each(b,function(a){d.appendChild(a)}),a.items[c]=d}),this.itemPanels=a.items,l.setSelectHandler(function(c,d){f.overlapIndex=c,k.setLabel(b[c]),k.hideMount(),a.items[d].style.display="none",a.items[c].style.display="block",c!==d&&f.updateSize(),f.onchangeHandler(c)}),g.appendChild(k.getNode()),h.Utils.each(a.items,function(a,b){b>0&&(a.style.display="none"),g.appendChild(a)}),l.select(0),[g]},getCurrentItemPanel:function(){return this.itemPanels[this.overlapIndex]},getGroupList:function(){var a=[];return h.Utils.each(this.options.group,function(b){a.push(b.title)}),{width:150,items:a}},createGroup:function(){var b=this.doc,c=[],d={title:[],items:[]},e=null,f=null,g=k.DETACHED===this.options.type?l.BIG:l.SMALL,m=null;return e=j.ele(this.doc,"div",{className:i+"box-group"}),m=e.cloneNode(!1),m.className=i+"box-group-item-container",h.Utils.each(this.options.group,function(k){d.title.push(k.title||""),c=[],h.Utils.each(k.items,function(d){e=e.cloneNode(!1),m=m.cloneNode(!1),f=j.ele(b,"div",{className:i+"box-group-title",content:d.title}),e.appendChild(f),e.appendChild(m),h.Utils.each(a(b,d.content,g),function(a){a.appendTo(m)}),c.push(e)}),d.items.push(c)}),d},mergeElement:function(){var a=this.groupContainer;this.element.appendChild(a),h.Utils.each(this.itemGroups,function(b){a.appendChild(b)})},mountTo:function(a){a.appendChild(this.element)},appendTo:function(a){a.appendChild(this.element)}}),q=h.createClass("BoxItem",{constructor:function(a,b,c){this.type=a,this.doc=b,this.options=c,this.element=this.createItem(),this.labelNode=this.createLabel(),this.contentNode=this.createContent(),this.mergeElement()},getNode:function(){return this.element},createItem:function(){var a=j.ele(this.doc,"div",{className:i+"box-item"});return a},createLabel:function(){var a=null;if("label"in this.options)return a=j.ele(this.doc,"div",{className:i+"box-item-label",content:this.options.label})},getContent:function(){},createContent:function(){switch(this.type){case l.BIG:return this.createBigContent();case l.SMALL:return this.createSmallContent()}},createBigContent:function(){var a=this.doc,b=j.ele(a,"div",{className:i+"box-item-content"}),c=i+"box-item-val",d=this.options.item,e=null,f=g(d);return e=j.ele(a,"div",{className:c}),e.innerHTML='<div class="'+i+'item-image" style="'+f+'"></div>',this.element.setAttribute("data-value",d.val),b.appendChild(e),b},createSmallContent:function(){var a=this.doc,b=j.ele(a,"div",{className:i+"box-item-content"}),c=i+"box-item-val",d=this.options,e=null;return e=j.ele(a,"div",{className:c}),e.style.background="url( "+d.img+" )",e.style.backgroundPosition=-d.pos.x+"px "+-d.pos.y+"px",this.element.setAttribute("data-value",d.key),b.appendChild(e),b},mergeElement:function(){this.labelNode&&this.element.appendChild(this.labelNode),this.element.appendChild(this.contentNode)},appendTo:function(a){a.appendChild(this.element)}});return p}},b[39]={value:function(){function a(a){var b="url( "+a.src+" ) no-repeat ";return b+=-a.x+"px ",b+=-a.y+"px"}var c=b.r(20),d="kf-editor-ui-",e=7,f={iconSize:{w:32,h:32}},g=b.r(47),h=c.createClass("Button",{constructor:function(a,b){this.options=c.Utils.extend({},f,b),this.eventState=!1,this.toolbar=null,this.displayState=!1,this.fixOffset=b.fixOffset||!1,this.doc=a,this.element=this.createButton(),this.disabled=!0,this.mountElement=null,this.icon=this.createIcon(),this.label=this.createLabel(),this.sign=this.createSign(),this.mountPoint=this.createMountPoint(),this.mergeElement()},initEvent:function(){var a=this;this.eventState||(this.eventState=!0,g.on(this.element,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),1===b.which&&(a.disabled||(a.toggleSelect(),a.toggleMountElement()))}))},setToolbar:function(a){this.toolbar=a},toggleMountElement:function(){this.displayState?this.hideMount():this.showMount()},setLabel:function(a){var b="";this.sign&&(b='<div class="'+d+'button-sign"></div>'),this.label.innerHTML=a+b},toggleSelect:function(){g.getClassList(this.element).toggle(d+"button-in")},unselect:function(){g.getClassList(this.element).remove(d+"button-in")},select:function(){g.getClassList(this.element).add(d+"button-in")},show:function(){this.select(),this.showMount()},hide:function(){this.unselect(),this.hideMount()},showMount:function(){if(this.displayState=!0,this.mountPoint.style.display="block",this.fixOffset){var a=this.element.getBoundingClientRect();this.mountElement.setOffset(a.left+e,a.bottom)}var b=this.toolbar.getContainer(),c=null,d=g.getRectBox(b),f=this.mountElement.getPositionInfo();f.right>d.right&&(c=g.getRectBox(this.element),this.mountPoint.style.left=c.right-f.right-1+"px"),this.mountElement.updateSize&&this.mountElement.updateSize()},hideMount:function(){this.displayState=!1,this.mountPoint.style.display="none"},getNode:function(){return this.element},mount:function(a){this.mountElement=a,a.mountTo(this.mountPoint)},createButton:function(){var a=g.ele(this.doc,"div",{className:d+"button"});return this.options.className&&(a.className+=" "+d+this.options.className),a},createIcon:function(){if(!this.options.icon)return null;var b=g.ele(this.doc,"div",{className:d+"button-icon"});return"string"==typeof this.options.icon?b.style.backgroundImage="url("+this.options.icon+") no-repeat":b.style.background=a(this.options.icon),this.options.iconSize.w&&(b.style.width=this.options.iconSize.w+"px"),this.options.iconSize.h&&(b.style.height=this.options.iconSize.h+"px"),b},createLabel:function(){var a=g.ele(this.doc,"div",{className:d+"button-label",content:this.options.label});return a},createSign:function(){return this.options.sign===!1?null:g.ele(this.doc,"div",{className:d+"button-sign"})},createMountPoint:function(){return g.ele(this.doc,"div",{className:d+"button-mount-point"})},disable:function(){this.disabled=!0,g.getClassList(this.element).remove(d+"enabled")
},enable:function(){this.disabled=!1,g.getClassList(this.element).add(d+"enabled")},mergeElement:function(){this.icon&&this.element.appendChild(this.icon),this.element.appendChild(this.label),this.sign&&this.label.appendChild(this.sign),this.element.appendChild(this.mountPoint)}});return h}},b[40]={value:function(){return{DETACHED:1,OVERLAP:2}}},b[41]={value:function(){return{DRAPDOWN_BOX:1,AREA:2,DELIMITER:3}}},b[42]={value:function(){return{BIG:1,SMALL:2}}},b[43]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=b.r(47),e=a.createClass("Delimiter",{constructor:function(a){this.doc=a,this.element=this.createDilimiter()},setToolbar:function(){},createDilimiter:function(){var a=d.ele(this.doc,"div",{className:c+"delimiter"});return a.appendChild(d.ele(this.doc,"div",{className:c+"delimiter-line"})),a},attachTo:function(a){a.appendChild(this.element)}});return e}},b[44]={value:function(){var a=b.r(20),c=b.r(47),d=b.r(39),e=b.r(38),f=a.createClass("DrapdownBox",{constructor:function(a,b){this.options=b,this.toolbar=null,this.doc=a,this.buttonElement=this.createButton(),this.element=this.buttonElement.getNode(),this.boxElement=this.createBox(),this.buttonElement.mount(this.boxElement),this.initEvent()},initEvent:function(){var a=this;c.on(this.element,"mousedown",function(b){b.preventDefault(),b.stopPropagation(),a.toolbar.notify("closeOther",a)}),this.buttonElement.initEvent(),this.boxElement.initEvent(),this.boxElement.setSelectHandler(function(b){c.publish("data.select",b),a.buttonElement.hide()})},disable:function(){this.buttonElement.disable()},enable:function(){this.buttonElement.enable()},setToolbar:function(a){this.toolbar=a,this.buttonElement.setToolbar(a),this.boxElement.setToolbar(a)},createButton:function(){return new d(this.doc,this.options.button)},show:function(){this.buttonElement.show()},hide:function(){this.buttonElement.hide()},createBox:function(){return new e(this.doc,this.options.box)},attachTo:function(a){a.appendChild(this.element)}});return f}},b[45]={value:function(){var a=b.r(20),c="kf-editor-ui-",d=b.r(47),e=a.createClass("List",{constructor:function(a,b){this.options=b,this.doc=a,this.onselectHandler=null,this.currentSelect=-1,this.element=this.createBox(),this.itemGroups=this.createItems(),this.mergeElement()},onselectHandler:function(){},setSelectHandler:function(a){this.onselectHandler=a},createBox:function(){var a=d.ele(this.doc,"div",{className:c+"list"}),b=d.ele(this.doc,"div",{className:c+"list-bg"});return"width"in this.options&&(a.style.width=this.options.width+"px"),a.appendChild(b),a},select:function(a){var b=this.currentSelect;-1===b&&(b=a),this.unselect(b),this.currentSelect=a,d.getClassList(this.itemGroups.items[a]).add(c+"list-item-select"),this.onselectHandler(a,b)},unselect:function(a){d.getClassList(this.itemGroups.items[a]).remove(c+"list-item-select")},setOffset:function(a,b){this.element.style.left=a+"px",this.element.style.top=b+"px"},initEvent:function(){var a="."+c+"list-item",b=this;d.delegate(this.itemGroups.container,a,"mousedown",function(a){a.preventDefault(),1===a.which&&b.select(this.getAttribute("data-index"))}),d.on(this.element,"mousedown",function(a){a.stopPropagation(),a.preventDefault()})},getPositionInfo:function(){return d.getRectBox(this.element)},createItems:function(){var b=this.doc,e=null,f=null,g=null,h=[],i=null;return e=d.ele(this.doc,"div",{className:c+"list-item"}),i=e.cloneNode(!1),i.className=c+"list-item-container",a.Utils.each(this.options.items,function(a,j){f=e.cloneNode(!1),g=e.cloneNode(!1),g.className=c+"list-item-icon",f.appendChild(g),f.appendChild(d.ele(b,"text",a)),f.setAttribute("data-index",j),h.push(f),i.appendChild(f)}),{container:i,items:h}},mergeElement:function(){this.element.appendChild(this.itemGroups.container)},mountTo:function(a){a.appendChild(this.element)}});return e}},b[46]={value:function(){function a(a,b,c){var d=a.createElement(b),e='<div class="$1"></div><div class="$2"></div>';return d.className=r+c,"thumb"===c&&(c=r+c,d.innerHTML=e.replace("$1",c+"-left").replace("$2",c+"-right")),d}function c(a){return a.getBoundingClientRect()}function d(a){q.addEvent(a,"mousedown",function(a){a.preventDefault()})}function d(a){q.addEvent(a.container,"mousedown",function(a){a.preventDefault()})}function e(a){q.addEvent(a.widgets.track,"mousedown",function(b){h(this,a,b)})}function f(a){q.addEvent(a.widgets.leftButton,"mousedown",function(){j(a,-p.step)}),q.addEvent(a.widgets.rightButton,"mousedown",function(){j(a,p.step)})}function g(a){var b=!1,c=0,d=0,e=a.values.trackWidth;q.addEvent(a.widgets.thumb,"mousedown",function(e){e.preventDefault(),e.stopPropagation(),b=!0,c=e.clientX,d=a.thumbLocationX}),q.addEvent(a.container.ownerDocument,"mouseup",function(){b=!1,c=0,d=0}),q.addEvent(a.container.ownerDocument,"mousemove",function(f){if(b){var g=f.clientX-c,h=d+g,j=a.values.thumbWidth;0>h?h=0:h+j>e&&(h=e-j),i(a,h)}})}function h(a,b,d){var e=c(a),f=b.values,g=f.viewWidth/(f.contentWidth-f.viewWidth)*f.trackWidth,h=d.clientX-e.left;h>f.offset?f.offset+g>f.trackWidth?k(b,f.trackWidth):k(b,f.offset+g):f.offset-g<0?k(b,0):k(b,f.offset-g)}function i(a,b){var c=a.values,d=c.trackWidth-c.thumbWidth,e=Math.floor(b/d*c.trackWidth);a.updateOffset(e),a.thumbLocationX=b,a.widgets.thumb.style.left=b+"px"}function j(a,b){var c=a.leftOverflow+b;0>c?c=0:c>a.values.scrollWidth&&(c=a.values.scrollWidth),m(a,c)}function k(a,b){var c=a.values,d=b/c.trackWidth,e=c.trackWidth-c.thumbWidth,f=0;f=Math.floor(d*e),0>b&&(b=0,f=0),a.updateOffset(b),a.widgets.thumb.style.left=f+"px",a.thumbLocationX=f}function l(a,b){var c=a.values,d=0,e=0;d=b/(c.contentWidth-c.viewWidth),e=Math.floor(d*c.trackWidth),k(a,e)}function m(a,b){var c=a.values,d=b/(c.contentWidth-c.viewWidth);k(a,d*c.trackWidth)}var n=b.r(20),o=b.r(32).scrollbar,p=b.r(29).scrollbar,q=b.r(4),r="kf-editor-ui-";return n.createClass("Scrollbar",{constructor:function(a,b){this.uiComponent=a,this.kfEditor=b,this.widgets=null,this.container=this.uiComponent.scrollbarContainer,this.state=!1,this.values={offset:0,left:0,viewWidth:0,contentWidth:0,trackWidth:0,thumbWidth:0,scrollWidth:0},this.thumbLocationX=0,this.leftOverflow=0,this.rightOverflow=0,this.isExpand=!0,this.initWidget(),this.mountWidget(),this.initSize(),this.hide(),this.initServices(),this.initEvent(),this.updateHandler=function(){}},initWidget:function(){var b=this.container.ownerDocument;this.widgets={leftButton:a(b,"div","left-button"),rightButton:a(b,"div","right-button"),track:a(b,"div","track"),thumb:a(b,"div","thumb"),thumbBody:a(b,"div","thumb-body")}},initSize:function(){var a=c(this.widgets.leftButton).width,b=c(this.widgets.rightButton).width;this.values.viewWidth=c(this.container).width,this.values.trackWidth=this.values.viewWidth-a-b,this.widgets.track.style.width=this.values.trackWidth+"px"},initServices:function(){this.kfEditor.registerService("ui.show.scrollbar",this,{showScrollbar:this.show}),this.kfEditor.registerService("ui.hide.scrollbar",this,{hideScrollbar:this.hide}),this.kfEditor.registerService("ui.update.scrollbar",this,{updateScrollbar:this.update}),this.kfEditor.registerService("ui.set.scrollbar.update.handler",this,{setUpdateHandler:this.setUpdateHandler}),this.kfEditor.registerService("ui.relocation.scrollbar",this,{relocation:this.relocation})},initEvent:function(){d(this),e(this),g(this),f(this)},mountWidget:function(){var a=this.widgets,b=this.container;for(var c in a)a.hasOwnProperty(c)&&b.appendChild(a[c]);a.thumb.appendChild(a.thumbBody),a.track.appendChild(a.thumb)},show:function(){this.state=!0,this.container.style.display="block"},hide:function(){this.state=!1,this.container.style.display="none"},update:function(a){var b=this.values.trackWidth,c=0;return this.isExpand=a>this.values.contentWidth,this.values.contentWidth=a,this.values.scrollWidth=a-this.values.viewWidth,b>=a?void this.hide():(c=Math.max(Math.ceil(b*b/a),o.thumbMinSize),this.values.thumbWidth=c,this.widgets.thumb.style.width=c+"px",void(this.widgets.thumbBody.style.width=c-10+"px"))},setUpdateHandler:function(a){this.updateHandler=a},updateOffset:function(a){var b=this.values;b.offset=a,b.left=a/b.trackWidth,this.leftOverflow=b.left*(b.contentWidth-b.viewWidth),this.rightOverflow=b.contentWidth-b.viewWidth-this.leftOverflow,this.updateHandler(b.left,b.offset,b)},relocation:function(){var a=this.kfEditor.requestService("control.get.cursor.location"),b=p.padding,c=this.values.contentWidth,d=this.values.viewWidth,e=this.values.left*(c-d),f=0;a.x<e?(a.x<0&&(a.x=0),l(this,a.x)):a.x+b>e+d?(a.x+=b,a.x>c&&(a.x=c),f=a.x-d,l(this,f)):this.isExpand?m(this,this.leftOverflow):m(this,c-d-this.rightOverflow)}})}},b[47]={value:function(){function a(a){this.node=a,this.classes=a.className.replace(/^\s+|\s+$/g,"").split(/\s+/)}var c=b.r(14),d=b.r(20),e={},f={ele:function(a,b,c){var d=null;return"text"===b?a.createTextNode(c):(d=a.createElement(b),c.className&&(d.className=c.className),c.content&&(d.innerHTML=c.content),d)},getRectBox:function(a){return a.getBoundingClientRect()},on:function(a,b,d){return c(a).on(b,d),this},delegate:function(a,b,d,e){return c(a).delegate(b,d,e),this},publish:function(a,b){var c=e[a];c&&(b=[].slice.call(arguments,1),d.Utils.each(c,function(a){a.apply(null,b)}))},subscribe:function(a,b){e[a]||(e[a]=[]),e[a].push(b)},getClassList:function(b){return b.classList||new a(b)}};return a.prototype={constructor:a,contains:function(a){return-1!==this.classes.indexOf(a)},add:function(a){return-1==this.classes.indexOf(a)&&this.classes.push(a),this._update(),this},remove:function(a){var b=this.classes.indexOf(a);return-1!==b&&(this.classes.splice(b,1),this._update()),this},toggle:function(a){var b=this.contains(a)?"remove":"add";return this[b](a)},_update:function(){this.node.className=this.classes.join(" ")}},f}},b[48]={value:function(){return{DrapdownBox:b.r(44),Delimiter:b.r(43),Area:b.r(37)}}},b[49]={value:function(){function a(a){return h.ele(a,"div",{className:"kf-editor-toolbar"})}function c(a){return h.ele(a,"div",{className:"kf-editor-inner-toolbar"})}function d(a){var b=a.createElement("div");return b.className="kf-editor-edit-area",b.style.width="80%",b.style.height="800px",b}function e(a){var b=a.createElement("div");return b.className="kf-editor-canvas-container",b}function f(a){var b=a.createElement("div");return b.className="kf-editor-edit-scrollbar",b}var g=b.r(20),h=b.r(47),i=b.r(4),j=b.r(32).VIEW_STATE,k=b.r(46),l=b.r(36),m=(b.r(31),b.r(35)),n=g.createClass("UIComponent",{constructor:function(b,g){var h=null;this.options=g,this.container=b.getContainer(),h=this.container.ownerDocument,this.components={},this.canvasRect=null,this.viewState=j.NO_OVERFLOW,this.kfEditor=b,this.toolbarWrap=a(h),this.toolbarContainer=c(h),this.editArea=d(h),this.canvasContainer=e(h),this.scrollbarContainer=f(h),this.toolbarWrap.appendChild(this.toolbarContainer),this.container.appendChild(this.toolbarWrap),this.editArea.appendChild(this.canvasContainer),this.container.appendChild(this.editArea),this.container.appendChild(this.scrollbarContainer),this.initComponents(),this.initServices(),this.initEvent(),this.updateContainerSize(this.container,this.toolbarWrap,this.editArea,this.canvasContainer),this.initScrollEvent()},initComponents:function(){this.components.toolbar=new l(this,this.kfEditor,m),this.components.scrollbar=new k(this,this.kfEditor)},updateContainerSize:function(a,b,c){var d=a.getBoundingClientRect(),e=b.getBoundingClientRect();c.style.width=d.width+"px",c.style.height=d.bottom-e.bottom+"px"},initServices:function(){this.kfEditor.registerService("ui.get.canvas.container",this,{getCanvasContainer:this.getCanvasContainer}),this.kfEditor.registerService("ui.update.canvas.view",this,{updateCanvasView:this.updateCanvasView}),this.kfEditor.registerService("ui.canvas.container.event",this,{on:this.addEvent,off:this.removeEvent,trigger:this.trigger,fire:this.trigger})},initEvent:function(){},initScrollEvent:function(){var a=this;this.kfEditor.requestService("ui.set.scrollbar.update.handler",function(b,c,d){c=Math.floor(b*(d.contentWidth-d.viewWidth)),a.kfEditor.requestService("render.set.canvas.offset",c)})},getCanvasContainer:function(){return this.canvasContainer},addEvent:function(a,b){i.addEvent(this.canvasContainer,a,b)},removeEvent:function(){},trigger:function(a){i.trigger(this.canvasContainer,a)},updateCanvasView:function(){var a=this.kfEditor.requestService("render.get.canvas"),b=a.getContentContainer(),c=null;null===this.canvasRect&&(this.canvasRect=this.canvasContainer.getBoundingClientRect()),c=b.getRenderBox("paper"),c.width>this.canvasRect.width?(this.viewState===j.NO_OVERFLOW&&(this.toggleViewState(),this.kfEditor.requestService("ui.show.scrollbar"),this.kfEditor.requestService("render.disable.relocation")),this.kfEditor.requestService("render.relocation"),this.kfEditor.requestService("ui.update.scrollbar",c.width),this.kfEditor.requestService("ui.relocation.scrollbar")):(this.viewState===j.OVERFLOW&&(this.toggleViewState(),this.kfEditor.requestService("ui.hide.scrollbar"),this.kfEditor.requestService("render.enable.relocation")),this.kfEditor.requestService("render.relocation"))},toggleViewState:function(){this.viewState=this.viewState===j.NO_OVERFLOW?j.OVERFLOW:j.NO_OVERFLOW}});return n}},b[50]={value:function(){var a=b.r(12),c=b.r(13);a.registerComponents("ui",b.r(49)),a.registerComponents("parser",b.r(21)),a.registerComponents("render",b.r(25)),a.registerComponents("position",b.r(23)),a.registerComponents("syntax",b.r(28)),a.registerComponents("control",b.r(5)),a.registerComponents("print",b.r(24)),kf.EditorFactory=c}};var c={"kf.start":50};!function(){try{a("kf.start")}catch(b){}}(this)}();
kitygraph.all.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/tinymce/plugins/kitymath/kityformula/js/kitygraph.all.js'
View Content
/*!
 * ====================================================
 * kity - v2.0.5 - 2015-11-12
 * https://github.com/fex-team/kity
 * GitHub: https://github.com/fex-team/kity.git 
 * Copyright (c) 2015 Baidu FEX; Licensed BSD
 * ====================================================
 */

(function () {
var _p = {
    r: function(index) {
        if (_p[index].inited) {
            return _p[index].value;
        }
        if (typeof _p[index].value === "function") {
            var module = {
                exports: {}
            }, returnValue = _p[index].value(null, module.exports, module);
            _p[index].inited = true;
            _p[index].value = returnValue;
            if (returnValue !== undefined) {
                return returnValue;
            } else {
                for (var key in module.exports) {
                    if (module.exports.hasOwnProperty(key)) {
                        _p[index].inited = true;
                        _p[index].value = module.exports;
                        return module.exports;
                    }
                }
            }
        } else {
            _p[index].inited = true;
            return _p[index].value;
        }
    }
};

//src/animate/animator.js
/**
 * @fileOverview
 *
 * 提供基本的动画支持
 */
_p[0] = {
    value: 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 = _p.r(8);
        var easingTable = _p.r(1);
        /**
     * @class kity.Animator
     * @catalog animate
     * @description 表示一个动画启动器,可以作用于不同的对象进行动画
     */
        var Animator = _p.r(11).createClass("Animator", {
            /**
         * @constructor
         * @for kity.Animator
         * @catalog animate
         *
         * @grammar new kity.Animator(beginValue, finishValue, setter)
         * @grammar new kity.Animator(option)
         *
         * @param  {any}      beginValue|opt.beginValue
         *     动画的起始值,允许的类型有数字、数组、字面量、kity.Point、kity.Vector、kity.Box、kity.Matrix
         *
         * @param  {any}      finishValue|opt.beginValue
         *     动画的结束值,类型应于起始值相同
         *
         * @param  {Function} setter|opt.setter
         *     值的使用函数,接受三个参数: function(target, value, timeline)
         *         target   {object}        动画的目标
         *         value    {any}           动画的当前值
         *         timeline {kity.Timeline} 动画当前的时间线对象
         */
            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;
                }
            },
            /**
         * @method start()
         * @for kity.Animator
         * @description 使用当前的动画器启动在指定目标上启动动画
         *
         * @grammar start(target, duration, easing, delay, callback) => {kity.Timeline}
         * @grammar start(target, option) => {kity.Timeline}
         *
         * @param  {object} target
         *     启动动画的目标
         *
         * @param  {Number|String} duration|option.duration
         *     [Optional] 动画的持续时间,如 300、"300ms"、"1.5min"
         *
         * @param  {String|Function} easing|option.easing
         *     [Optional] 动画使用的缓动函数,如 "ease"、"linear"、"swing"
         *
         * @param  {Number|String} delay|option.delay
         *     [Optional] 动画的播放延迟时间
         *
         * @param  {Function} callback|option.callback
         *     [Optional] 动画结束后的回调函数
         *
         * @example
         *
         * ```js
         * var turnRed = new kity.Animator(
         *     new kity.Color('yellow'),
         *     new kity.Color('red'),
         *     function(target, value) {
         *         target.fill(value);
         *     });
         *
         * turnRed.start(rect, 300, 'ease', function() {
         *     console.log('I am red!');
         * });
         * ```
         */
            start: function(target, duration, easing, delay, callback) {
                if (arguments.length === 2 && typeof duration == "object") {
                    easing = duration.easing;
                    delay = duration.delay;
                    callback = duration.callback;
                    duration = duration.duration;
                }
                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;
            },
            /**
         * @method create()
         * @for kity.Animator
         * @description 使用当前的动画器为指定目标创建时间线
         *
         * @grammar create(target, duration, easing, callback) => {kity.Timeline}
         *
         * @param  {object}            target   要创建的时间线的目标
         * @param  {Number|String}     duration 要创建的时间线的长度,如 300、"5s"、"0.5min"
         * @param  {String|Function}   easing   要创建的时间线的缓动函数,如 'ease'、'linear'、'swing'
         * @param  {Function}          callback 时间线播放结束之后的回调函数
         *
         * @example
         *
         * ```js
         * var expand = new kity.Animator({
         *     beginValue: function(target) {
         *         return target.getBox();
         *     },
         *     finishValue: function(target) {
         *         return target.getBox().expand(100, 100, 100, 100);
         *     },
         *     setter: function(target, value) {
         *         target.setBox(value)
         *     }
         * });
         *
         * var timeline = expand.create(rect, 300);
         * timeline.repeat(3).play();
         * ```
         */
            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;
            },
            /**
         * @method reverse()
         * @for kity.Animator
         * @grammar reverse() => {kity.Animator}
         * @description 创建一个与当前动画器相反的动画器
         *
         * @example
         *
         * ```js
         * var turnYellow = turnRed.reverse();
         * ```
         */
            reverse: function() {
                return new Animator(this.finishValue, this.beginValue, this.setter);
            }
        });
        Animator.DEFAULT_DURATION = 300;
        Animator.DEFAULT_EASING = "linear";
        var Shape = _p.r(60);
        _p.r(11).extendClass(Shape, {
            /**
         * @method animate()
         * @for kity.Shape
         * @description 在图形上播放使用指定的动画器播放动画,如果图形当前有动画正在播放,则会加入播放队列
         *
         * @grammar animate(animator, duration, easing, delay, callback)
         *
         * @param  {object}            animator 播放动画使用的动画器
         * @param  {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param  {Number|String}     delay    动画播放前的延时
         * @param  {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param  {Function}          callback 播放结束之后的回调函数
         *
         * @example
         *
         * ```js
         * rect.animate(turnRed, 300); // turnRect 是一个动画器
         * rect.animate(expand, 500);  // turnRect 播放结束后播放 expand
         * ```
         */
            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;
            },
            /**
         * @method timeline()
         * @for kity.Shape
         * @description 获得当前正在播放的动画的时间线
         *
         * @grammar timeline() => {kity.Timeline}
         *
         * @example
         *
         * ```js
         * rect.timeline().repeat(2);
         * ```
         */
            timeline: function() {
                return this._KityAnimateQueue[0].t;
            },
            /**
         * @method stop()
         * @for kity.Shape
         * @description 停止当前正在播放的动画
         *
         * @grammar stop() => {this}
         *
         * @example
         *
         * ```js
         * rect.stop(); // 停止 rect 上的动画
         * ```
         */
            stop: function() {
                var queue = this._KityAnimateQueue;
                if (queue) {
                    while (queue.length) {
                        queue.shift().t.stop();
                    }
                }
                return this;
            }
        });
        return Animator;
    }
};

//src/animate/easing.js
/**
 * 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
 * ======================================================== */
_p[1] = {
    value: 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;
    }
};

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 *
 * Open source under the BSD License.
 *
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
//src/animate/frame.js
/**
 * @fileOverview
 *
 * 提供动画帧的基本支持
 */
_p[2] = {
    value: function(require, exports) {
        // 原生动画帧方法 polyfill
        var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(fn) {
            return setTimeout(fn, 1e3 / 60);
        };
        var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || window.clearTimeout;
        // 上一个请求的原生动画帧 id
        var frameRequestId;
        // 等待执行的帧动作的集合,这些帧的方法将在下个原生动画帧同步执行
        var pendingFrames = [];
        /**
     * 添加一个帧到等待集合中
     *
     * 如果添加的帧是序列的第一个,至少有一个帧需要被执行,则会请求一个原生动画帧来执行
     */
        function pushFrame(frame) {
            if (pendingFrames.push(frame) === 1) {
                frameRequestId = requestAnimationFrame(executePendingFrames);
            }
        }
        /**
     * 执行所有等待帧
     */
        function executePendingFrames() {
            var frames = pendingFrames;
            pendingFrames = [];
            while (frames.length) {
                executeFrame(frames.pop());
            }
            frameRequestId = 0;
        }
        /**
     * @method kity.requestFrame
     * @catalog animate
     * @grammar kity.requestFrame(action) => {frame}
     * @description 请求一个帧,执行指定的动作。动作回调提供一些有用的信息
     *
     * @param {Function} action
     *
     *     要执行的动作,该动作回调有一个参数 frame,其中:
     *
     *     frame.time {Number}
     *         动作执行时的时间戳(ms)
     *
     *     frame.index {Number}
     *         当前执行的帧的编号(首帧为 0)
     *
     *     frame.dur {Number}
     *         上一帧至当前帧经过的时间,单位 ms
     *
     *     frame.elapsed {Number}
     *         从首帧开始到当前帧经过的时间,单位 ms
     *
     *     frame.action {Number}
     *         指向当前的帧处理函数
     *
     *     frame.next()
     *         表示下一帧继续执行。如果不调用该方法,将不会执行下一帧。
     *
     * @example
     *
     * ```js
     * kity.requestFrame(function(frame) {
     *     console.log('平均帧率:' + frame.elapsed / (frame.index + 1));
     *
     *     // 更新或渲染动作
     *
     *     frame.next(); //继续执行下一帧
     * });
     * ```
     */
        function requestFrame(action) {
            var frame = initFrame(action);
            pushFrame(frame);
            return frame;
        }
        /**
     * @method kity.releaseFrame
     * @catalog animate
     * @grammar kity.releaseFrame(frame)
     * @description 释放一个已经请求过的帧,如果该帧在等待集合里,将移除,下个动画帧不会执行释放的帧
     *
     * @param {frame} frame 使用 kity.requestFrame() 返回的帧
     *
     * @example
     *
     * ```js
     * var frame = kity.requestFrame(function() {....});
     * kity.releaseFrame(frame);
     * ```
     */
        function releaseFrame(frame) {
            var index = pendingFrames.indexOf(frame);
            if (~index) {
                pendingFrames.splice(index, 1);
            }
            if (pendingFrames.length === 0) {
                cancelAnimationFrame(frameRequestId);
            }
        }
        /**
     * 初始化一个帧,主要用于后续计算
     */
        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;
    }
};

//src/animate/motionanimator.js
/**
 * @fileOverview
 *
 * 路径动画器,可以让一个物体沿着某个轨迹运动
 */
_p[3] = {
    value: function(require) {
        var Animator = _p.r(0);
        var g = _p.r(34);
        var Path = _p.r(46);
        var Shape = _p.r(60);
        /**
     * @class kity.MotionAnimator
     * @catalog animate
     * @base kity.Animator
     * @description 路径动画器,可以让一个物体沿着某个轨迹运动
     *
     * @example
     *
     * ```js
     * var motionAnimator = new MotionAnimator('M0,0C100,0,100,0,100,100L200,200');
     * motionAnimator.start(rect, 3000);
     * ```
     */
        var MotionAnimator = _p.r(11).createClass("MotionAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.MotionAnimator
         * @grammar new kity.MotionAnimator(path, doRotate)
         * @param {kity.Path|String|PathSegment} path 运动的轨迹,或者是 kity.Path 对象
         * @param {boolean} doRotate 是否让运动的目标沿着路径的切线方向旋转
         */
            constructor: function(path, doRotate) {
                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);
                        if (this.doRotate) target.setRotate(point.tan.getAngle());
                    }
                });
                /**
             * @property doRotate
             * @for kity.MotionAnimator
             * @type {boolean}
             * @description 是否让运动的目标沿着路径的切线方向旋转
             *
             * @example
             *
             * ```js
             * motionAnimator.doRotate = true; // 目标沿着切线方向旋转
             * ```
             */
                this.doRotate = doRotate;
                /**
             * @property motionPath
             * @for kity.MotionAnimator
             * @type  {kity.Path|String|PathSegment}
             * @description 运动沿着的路径,可以在动画过程中更新
             */
                this.motionPath = path;
            }
        });
        _p.r(11).extendClass(Shape, {
            /**
         * @method motion()
         * @catalog animate
         * @for kity.Shape
         * @description 让图形沿着指定的路径运动
         *
         * @grammar motion(path, duration, easing, delay, callback) => this
         *
         * @param {kity.Path|String|PathSegment} path 运动的轨迹,或者是 kity.Path 对象
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            motion: function(path, duration, easing, delay, callback) {
                return this.animate(new MotionAnimator(path), duration, easing, delay, callback);
            }
        });
        return MotionAnimator;
    }
};

//src/animate/opacityanimator.js
/**
 * @fileOverview
 *
 * 透明度动画器,让图形动画过度到指定的透明度。
 */
_p[4] = {
    value: function(require) {
        var Animator = _p.r(0);
        /**
     * @class kity.OpacityAnimator
     * @catalog animate
     * @base kity.Animator
     * @description 透明度动画器,让图形动画过度到指定的透明度
     */
        var OpacityAnimator = _p.r(11).createClass("OpacityAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.OpacityAnimator
         * @grammar new kity.OpacityAnimator(opacity)
         *
         * @param  {Number} opacity 目标透明度,取值范围 0 - 1
         */
            constructor: function(opacity) {
                this.callBase({
                    beginValue: function(target) {
                        return target.getOpacity();
                    },
                    finishValue: opacity,
                    setter: function(target, value) {
                        target.setOpacity(value);
                    }
                });
            }
        });
        var Shape = _p.r(60);
        _p.r(11).extendClass(Shape, {
            /**
         * @method fxOpacity()
         * @catalog animate
         * @for kity.Shape
         * @description 让图形的透明度以动画的形式过渡到指定的值
         *
         * @grammar fxOpacity(opacity, duration, easing, delay, callback) => {this}
         *
         * @param {Number}            opacity  动画的目标透明度
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fxOpacity: function(opacity, duration, easing, delay, callback) {
                return this.animate(new OpacityAnimator(opacity), duration, easing, delay, callback);
            },
            /**
         * @method fadeTo()
         * @catalog animate
         * @for kity.Shape
         * @description 让图形的透明度以动画的形式过渡到指定的值
         *
         * @grammar fadeTo(opacity, duration, easing, delay, callback) => {this}
         *
         * @param {Number}            opacity  动画的目标透明度
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fadeTo: function() {
                return this.fxOpacity.apply(this, arguments);
            },
            /**
         * @method fadeIn()
         * @catalog animate
         * @for kity.Shape
         * @description 让图形淡入
         *
         * @grammar fadeIn(duration, easing, delay, callback) => {this}
         *
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fadeIn: function() {
                return this.fxOpacity.apply(this, [ 1 ].concat([].slice.call(arguments)));
            },
            /**
         * @method fadeOut()
         * @catalog animate
         * @for kity.Shape
         * @description 让图形淡出
         *
         * @grammar fadeIn(duration, easing, delay, callback) => {this}
         *
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fadeOut: function() {
                return this.fxOpacity.apply(this, [ 0 ].concat([].slice.call(arguments)));
            }
        });
        return OpacityAnimator;
    }
};

//src/animate/pathanimator.js
/**
 * @fileOverview
 *
 * 路径补间动画器,让图形从一个形状变为另一个形状
 */
_p[5] = {
    value: function(require) {
        var Animator = _p.r(0);
        var g = _p.r(34);
        /**
     * @catalog animate
     *
     * @class kity.PathAnimator
     * @base kity.Animator
     * @description 路径补间动画器,让图形从一个形状变为另一个形状
     *
     * @example
     *
     * ```js
     * var path = new kity.Path('M0,0L0,100');
     * var pa = new kity.PathAnimator('M0,0C100,0,100,0,100,100');
     * pa.start(path, 300);
     * ```
     */
        var PathAnimator = _p.r(11).createClass("OpacityAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.PathAnimator
         *
         * @grammar new kity.Path.Animator(path)
         *
         * @param  {String|PathSegment} path 目标形状的路径数据
         *
         */
            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 = _p.r(46);
        _p.r(11).extendClass(Path, {
            /**
         * @catalog animate
         *
         * @method fxPath()
         * @for kity.Shape
         * @description 以动画的形式把路径变换为新路径
         *
         * @grammar fxPath(path, duration, easing, delay, callback) => {this}
         *
         * @param {String|PathSegment}   path     要变换新路径
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fxPath: function(path, duration, easing, delay, callback) {
                return this.animate(new PathAnimator(path), duration, easing, delay, callback);
            }
        });
        return PathAnimator;
    }
};

//src/animate/rotateanimator.js
/**
 * @fileOverview
 *
 * 提供支持目标旋转的动画器
 */
_p[6] = {
    value: function(require) {
        var Animator = _p.r(0);
        /**
     * @class kity.RotateAnimator
     * @base Animator
     * @description 提供支持目标旋转的动画器
     */
        var RotateAnimator = _p.r(11).createClass("RotateAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.RotateAnimator
         *
         * @grammar new kity.RotateAnimator(deg, ax, ay)
         *
         * @param  {Number} deg 要旋转的角度
         */
            constructor: function(deg) {
                this.callBase({
                    beginValue: 0,
                    finishValue: deg,
                    setter: function(target, value, timeline) {
                        var delta = timeline.getDelta();
                        target.rotate(delta, ax, ay);
                    }
                });
            }
        });
        var Shape = _p.r(60);
        _p.r(11).extendClass(Shape, {
            /**
         * @method fxRotate()
         * @for kity.Shape
         * @description 让目标以动画旋转指定的角度
         *
         * @grammar fxRotate(deg, duration, easing, delay) => {this}
         *
         * @param {Number}            deg      要旋转的角度
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fxRotate: function(deg, duration, easing, delay, callback) {
                return this.animate(new RotateAnimator(deg), duration, easing, delay, callback);
            }
        });
        return RotateAnimator;
    }
};

//src/animate/scaleanimator.js
/**
 * @fileOverview
 *
 * 提供支持目标缩放的动画器
 */
_p[7] = {
    value: function(require) {
        var Animator = _p.r(0);
        /**
     * @class kity.ScaleAnimator
     * @base kity.Animator
     * @description 提供支持目标缩放的动画器
     */
        var ScaleAnimator = _p.r(11).createClass("ScaleAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.ScaleAnimator
         *
         * @grammar new kity.ScaleAnimator(sx, sy)
         * @param  {Number} sx x 轴的缩放比例
         * @param  {Number} sy y 轴的缩放比例
         */
            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 = _p.r(60);
        _p.r(11).extendClass(Shape, {
            /**
         * @method fxScale
         * @for kity.Shape
         * @description 动画缩放当前的图形
         *
         * @grammar fxScale(sx, sy, duration, easing, delay, callback) => {this}
         *
         * @param {Number} sx x 轴的缩放比例
         * @param {Number} sy y 轴的缩放比例
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fxScale: function(sx, sy, duration, easing, delay, callback) {
                return this.animate(new ScaleAnimator(sx, sy), duration, easing, delay, callback);
            }
        });
        return ScaleAnimator;
    }
};

//src/animate/timeline.js
/**
 * @fileOverview
 *
 * 动画时间线的实现
 */
_p[8] = {
    value: function(require) {
        var EventHandler = _p.r(33);
        var utils = _p.r(12);
        var frame = _p.r(2);
        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];
                }
            }
        }
        /**
     * @class kity.Timeline
     * @catalog animate
     * @mixins EventHandler
     * @description 动画时间线
     */
        var Timeline = _p.r(11).createClass("Timeline", {
            mixins: [ EventHandler ],
            /**
         * @constructor
         * @for kity.Timeline
         * @private
         * @description 时间线应该由动画器进行构造,不应手动创建
         *
         */
            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";
            },
            /**
         * @private
         *
         * 让时间线进入下一帧
         */
            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();
            },
            /**
         * @method getPlayTime()
         * @for kity.Timeline
         * @grammar getPlayTime() => {Number}
         * @description 获得当前播放的时间,取值区间为 [0, duration]
         */
            getPlayTime: function() {
                return this.rollbacking ? this.duration - this.time : this.time;
            },
            /**
         * @method getTimeProportion()
         * @for kity.Timeline
         * @grammar getTimeProportion() => {Number}
         * @description 获得当前播放时间的比例,取值区间为 [0, 1]
         */
            getTimeProportion: function() {
                return this.getPlayTime() / this.duration;
            },
            /**
         * @method getValueProportion()
         * @for kity.Timeline
         * @grammar getValueProportion() => {Number}
         * @description 获得当前播放时间对应值的比例,取值区间为 [0, 1];该值实际上是时间比例值经过缓动函数计算之后的值。
         */
            getValueProportion: function() {
                return this.easing(this.getPlayTime(), 0, 1, this.duration);
            },
            /**
         * @method getValue()
         * @for kity.Timeline
         * @grammar getValue() => {any}
         * @description 返回当前播放时间对应的值。
         */
            getValue: function() {
                var b = this.beginValue;
                var f = this.finishValue;
                var p = this.getValueProportion();
                return getPercentValue(b, f, p);
            },
            /**
         * @private
         *
         * 把值通过动画器的 setter 设置到目标上
         */
            setValue: function(value) {
                this.lastValue = this.currentValue;
                this.currentValue = value;
                this.setter.call(this.target, this.target, value, this);
            },
            /**
         * @method getDelta()
         * @for kity.Timeline
         * @grammar getDelta() => {any}
         * @description 返回当前值和上一帧的值的差值
         */
            getDelta: function() {
                this.lastValue = this.lastValue === undefined ? this.beginValue : this.lastValue;
                return getDelta(this.lastValue, this.currentValue);
            },
            /**
         * @method play()
         * @for kity.Timeline
         * @grammar play() => {this}
         * @description 让时间线播放,如果时间线还没开始,或者已停止、已结束,则重头播放;如果是已暂停,从暂停的位置继续播放
         */
            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.setValue(this.beginValue);
                    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();
                }
                /**
             * @event play
             * @for kity.Timeline
             * @description 在时间线播放后触发
             *
             * @param {String} event.lastStatus
             *        表示播放前的上一个状态,可能取值为 'ready'、'finished'、'stoped'、'paused'
             */
                this.fire("play", new TimelineEvent(this, "play", {
                    lastStatus: lastStatus
                }));
                return this;
            },
            /**
         * @method pause()
         * @for kity.Timeline
         * @description 暂停当前的时间线
         *
         * @grammar pause() => {this}
         */
            pause: function() {
                this.status = "paused";
                /**
             * @event pause
             * @for kity.Timeline
             * @description 暂停事件,在时间线暂停时触发
             */
                this.fire("pause", new TimelineEvent(this, "pause"));
                frame.releaseFrame(this.frame);
                return this;
            },
            /**
         * @method stop()
         * @for kity.Timeline
         * @description 停止当前时间线
         *
         * @grammar stop() => {this}
         */
            stop: function() {
                this.status = "stoped";
                this.setValue(this.finishValue);
                this.rollbacking = false;
                /**
             * @event stop
             * @for kity.Timeline
             * @description 停止时间,在时间线停止时触发
             */
                this.fire("stop", new TimelineEvent(this, "stop"));
                frame.releaseFrame(this.frame);
                return this;
            },
            /**
         * @private
         *
         * 播放结束之后的处理
         */
            timeUp: function() {
                if (this.repeatOption) {
                    this.time = 0;
                    if (this.rollback) {
                        if (this.rollbacking) {
                            this.decreaseRepeat();
                            this.rollbacking = false;
                        } else {
                            this.rollbacking = true;
                            /**
                         * @event rollback
                         * @for kity.Timeline
                         * @description 回滚事件,在时间线回滚播放开始的时候触发
                         */
                            this.fire("rollback", new TimelineEvent(this, "rollback"));
                        }
                    } else {
                        this.decreaseRepeat();
                    }
                    if (!this.repeatOption) {
                        this.finish();
                    } else {
                        /**
                     * @event repeat
                     * @for kity.Timeline
                     * @description 循环事件,在时间线循环播放开始的时候触发
                     */
                        this.fire("repeat", new TimelineEvent(this, "repeat"));
                    }
                } else {
                    this.finish();
                }
            },
            /**
         * @private
         *
         * 决定播放结束的处理
         */
            finish: function() {
                this.setValue(this.finishValue);
                this.status = "finished";
                /**
             * @event finish
             * @for kity.Timeline
             * @description 结束事件,在时间线播放结束后触发(包括重复和回滚都结束)
             */
                this.fire("finish", new TimelineEvent(this, "finish"));
                frame.releaseFrame(this.frame);
            },
            /**
         * @private
         *
         *  循环次数递减
         */
            decreaseRepeat: function() {
                if (this.repeatOption !== true) {
                    this.repeatOption--;
                }
            },
            /**
         * @method repeat()
         * @for kity.Timeline
         * @description 设置时间线的重复选项
         *
         * @grammar repeat(repeat, rollback) => {this}
         *
         * @param  {Number|Boolean} repeat
         *     是否重复播放,设置为 true 无限循环播放,设置数值则循环指定的次数
         * @param  {Boolean} rollback
         *     指示是否要回滚播放。
         *     如果设置为真,一次事件到 duration 则一个来回算一次循环次数,否则播放完成一次算一次循环次数
         *
         */
            repeat: function(repeat, rollback) {
                this.repeatOption = repeat;
                this.rollback = rollback;
                return this;
            }
        });
        Timeline.requestFrame = frame.requestFrame;
        Timeline.releaseFrame = frame.releaseFrame;
        return Timeline;
    }
};

//src/animate/translateanimator.js
/**
 * @fileOverview
 *
 * 提供让图形移动的动画器
 */
_p[9] = {
    value: function(require) {
        var Animator = _p.r(0);
        /**
     * @class kity.TranslateAnimator
     * @base kity.Animator
     * @description 提供让图形移动的动画器
     */
        var TranslateAnimator = _p.r(11).createClass("TranslateAnimator", {
            base: Animator,
            /**
         * @constructor
         * @for kity.TranslateAnimator
         * @grammar new kity.TranslateAnimator(x, y)
         * @param  {Number} x x 方向上需要移动的距离
         * @param  {Number} y y 方向上需要移动的距离
         */
            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 = _p.r(60);
        _p.r(11).extendClass(Shape, {
            /**
         * @method fxTranslate()
         * @for kity.Shape
         * @description 让目标以动画平移指定的距离
         *
         * @grammar fxTranslate(x, y, duration, easing, delay, callback) => {this}
         *
         * @param {Number} x x 方向上需要移动的距离
         * @param {Number} y y 方向上需要移动的距离
         * @param {Number|String}     duration 动画的播放长度,如 300、"5s"、"0.5min"
         * @param {Number|String}     delay    动画播放前的延时
         * @param {String|Function}   easing   动画播放使用的缓动函数,如 'ease'、'linear'、'swing'
         * @param {Function}          callback 播放结束之后的回调函数
         */
            fxTranslate: function(x, y, duration, easing, delay, callback) {
                return this.animate(new TranslateAnimator(x, y), duration, easing, delay, callback);
            }
        });
        return TranslateAnimator;
    }
};

//src/core/browser.js
/**
 * @fileOverview
 *
 * 提供浏览器判断的一些字段
 */
_p[10] = {
    value: function() {
        /**
     * @class kity.Browser
     * @catalog core
     * @static
     * @description 提供浏览器信息
     */
        var browser = function() {
            var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser;
            // 浏览器对象
            browser = {
                /**
             * @property platform
             * @description 获取浏览器所在系统,"Win"->Windows;"Mac"->Mac;"Lux"->Linux
             * @type {String}
             */
                platform: function(navigator) {
                    var _p = {
                        win32: "Win",
                        macintel: "Mac"
                    };
                    return _p[navigator.platform.toLowerCase()] || "Lux";
                }(navigator),
                /**
             * 猎豹,区分两种不同内核
             */
                lb: function(agent) {
                    if (~agent.indexOf("lbbrowser")) {
                        return ~agent.indexOf("msie") ? "ie" : "chrome";
                    }
                    return false;
                }(agent),
                /**
             * 搜狗
             */
                sg: /se[\s\S]+metasr/.test(agent),
                /**
             * 百度
             */
                bd: !!~agent.indexOf("bidubrowser"),
                /**
             * edge浏览器
             */
                edge: !!~agent.indexOf("edge"),
                /**
             * chrome初始化为false
             * @type {Boolean}
             */
                chrome: false,
                /**
             * @property opera
             * @for kity.Browser
             * @description 判断是否为 Opera 浏览器
             * @type {boolean}
             */
                opera: !!opera && opera.version,
                /**
             * @property webkit
             * @for kity.Browser
             * @description 判断是否为 Webkit 内核的浏览器
             * @type {boolean}
             */
                webkit: agent.indexOf(" applewebkit/") > -1,
                /**
             * @property mac
             * @for kity.Browser
             * @description 判断是否为 Mac 下的浏览器
             * @type {boolean}
             */
                mac: agent.indexOf("macintosh") > -1
            };
            /**
         * @property ie
         * @for kity.Browser
         * @description 判断是否为 IE 浏览器
         * @type {boolean}
         */
            browser.ie = !browser.lb && /(msie\s|trident.*rv:)([\w.]+)/.test(agent);
            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;
                }
            }
            // 排除其他chrome内核的浏览器的干扰
            if (/chrome\/(\d+\.\d)/i.test(agent) && !browser.bd && !browser.opera && !browser.lb && !browser.sg && !browser.edge) {
                /**
             * @property chrome
             * @for kity.Browser
             * @description 判断是否为 Chrome 浏览器
             * @type {boolean}
             */
                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]);
            // 搜狗版本号无从得知
            // 猎豹版本号无从得知
            // 百度
            if (browser.bd) version = parseFloat(agent.match(/bidubrowser\/(\d+)/)[1]);
            // Opera 9.50+
            if (browser.opera) version = parseFloat(agent.match(/opr\/(\d+)/)[1]);
            // edge
            if (browser.edge) version = parseFloat(agent.match(/edge\/(\d+)/)[1]);
            /**
         * @property version
         * @for kity.Browser
         * @description 获取当前浏览器的版本
         * @type {Number}
         */
            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;
    }
};

//src/core/class.js
/**
 * @fileOverview
 *
 * 提供 Kity 的 OOP 支持
 */
_p[11] = {
    value: function(require, exports) {
        /**
     * @class kity.Class
     * @catalog core
     * @description 所有 kity 类的基类
     * @abstract
     */
        function Class() {}
        exports.Class = Class;
        Class.__KityClassName = "Class";
        /**
     * @method base()
     * @for kity.Class
     * @protected
     * @grammar base(name, args...) => {any}
     * @description 调用父类指定名称的函数
     * @param {string} name 函数的名称
     * @param {parameter} args... 传递给父类函数的参数
     *
     * @example
     *
     * ```js
     * var Person = kity.createClass('Person', {
     *     toString: function() {
     *         return 'I am a person';
     *     }
     * });
     *
     * var Male = kity.createClass('Male', {
     *     base: Person,
     *
     *     toString: function() {
     *         return 'I am a man';
     *     },
     *
     *     speak: function() {
     *         return this.base('toString') + ',' + this.toString();
     *     }
     * })
     * ```
     */
        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));
        };
        /**
     * @method callBase()
     * @for kity.Class
     * @protected
     * @grammar callBase(args...) => {any}
     * @description 调用父类同名函数
     * @param {parameter} args... 传递到父类同名函数的参数
     *
     * @example
     *
     * ```js
     * var Animal = kity.createClass('Animal', {
     *     constructor: function(name) {
     *         this.name = name;
     *     },
     *     toString: function() {
     *         return 'I am an animal name ' + this.name;
     *     }
     * });
     *
     * var Dog = kity.createClass('Dog', {
     *     constructor: function(name) {
     *         this.callBase(name);
     *     },
     *     toString: function() {
     *         return this.callBase() + ', a dog';
     *     }
     * });
     *
     * var dog = new Dog('Dummy');
     * console.log(dog.toString()); // "I am an animal name Dummy, a dog";
     * ```
     */
        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);
            }
        };
        /**
     * @method pipe()
     * @for kity.Class
     * @grammar pipe() => {this}
     * @description 以当前对象为上线文以及管道函数的第一个参数,执行一个管道函数
     * @param  {Function} fn 进行管道操作的函数
     *
     * @example
     *
     * ```js
     * var rect = new kity.Rect().pipe(function() {
     *     this.setWidth(500);
     *     this.setHeight(300);
     * });
     * ```
     */
        Class.prototype.pipe = function(fn) {
            if (typeof fn == "function") {
                fn.call(this, this);
            }
            return this;
        };
        /**
     * @method getType()
     * @for kity.Class
     * @grammar getType() => {string}
     * @description 获得对象的类型
     *
     * @example
     *
     * ```js
     * var rect = new kity.Rect();
     * var circle = new kity.Circle();
     *
     * console.log(rect.getType()); // "Rect"
     * console.log(rect.getType()); // "Circle"
     * ```
     */
        Class.prototype.getType = function() {
            return this.__KityClassName;
        };
        /**
     * @method getClass()
     * @for kity.Class
     * @grammar getClass() => {Class}
     * @description 获得对象的类
     *
     * @example
     *
     * ```js
     * var rect = new kity.Rect();
     *
     * console.log(rect.getClass() === kity.Rect); // true
     * console.log(rect instanceof kity.Rect); // true
     * ```
     */
        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 = eval("(function " + classname + "( __inherit__flag ) {" + "if( __inherit__flag != KITY_INHERIT_FLAG ) {" + "KityClass.__KityConstructor.apply(this, arguments);" + "}" + "this.__KityClassName = KityClass.__KityClassName;" + "})");
            KityClass.__KityConstructor = constructor;
            KityClass.prototype = new BaseClass(KITY_INHERIT_FLAG);
            for (var methodName in BaseClass.prototype) {
                if (BaseClass.prototype.hasOwnProperty(methodName) && methodName.indexOf("__Kity") !== 0) {
                    KityClass.prototype[methodName] = BaseClass.prototype[methodName];
                }
            }
            KityClass.prototype.constructor = KityClass;
            return KityClass;
        }
        function mixin(NewClass, mixins) {
            if (false === mixins instanceof Array) {
                return NewClass;
            }
            var i, length = mixins.length, proto, method;
            NewClass.__KityMixins = {
                constructor: []
            };
            for (i = 0; i < length; i++) {
                proto = mixins[i].prototype;
                for (method in proto) {
                    if (false === proto.hasOwnProperty(method) || method.indexOf("__Kity") === 0) {
                        continue;
                    }
                    if (method === "constructor") {
                        // constructor 特殊处理
                        NewClass.__KityMixins.constructor.push(proto[method]);
                    } else {
                        NewClass.prototype[method] = NewClass.__KityMixins[method] = proto[method];
                    }
                }
            }
            return NewClass;
        }
        function extend(BaseClass, extension) {
            if (extension.__KityClassName) {
                extension = extension.prototype;
            }
            for (var methodName in extension) {
                if (extension.hasOwnProperty(methodName) && methodName.indexOf("__Kity") && methodName != "constructor") {
                    var method = BaseClass.prototype[methodName] = extension[methodName];
                    method.__KityMethodClass = BaseClass;
                    method.__KityMethodName = methodName;
                }
            }
            return BaseClass;
        }
        /**
     * @method kity.createClass()
     * @grammar kity.createClass(classname, defines) => {Class}
     * @description 创建一个类
     * @param  {string} classname 类名,用于调试的时候查看,可选
     * @param  {object} defines   类定义
     *      defines.base {Class}
     *          定义的类的基类,如果不配置,则表示基类为 kity.Class
     *      defines.mixins {Class[]}
     *          定义的类要融合的类列表
     *      defines.constructor {Function}
     *          定义类的构造函数,如果父类显式定义了构造函数,需要在构造函数中使用 callBase() 方法调用父类的构造函数
     *      defines.* {Function}
     *          定义类的其它函数
     *
     * @example 创建一个类
     *
     * ```js
     * var Animal = kity.createClass('Animal', {
     *     constructor: function(name) {
     *         this.name = name;
     *     },
     *     toString: function() {
     *         return this.name;
     *     }
     * });
     *
     * var a = new Animal('kity');
     * console.log(a.toString()); // "kity"
     * ```
     *
     * @example 继承一个类
     *
     * ```js
     * var Cat = kity.createClass('Cat', {
     *     base: Animal,
     *     constructor: function(name, color) {
     *         // 调用父类构造函数
     *         this.callBase(name);
     *     },
     *     toString: function() {
     *         return 'A ' + this.color + ' cat, ' + this.callBase();
     *     }
     * });
     *
     * var cat = new Cat('kity', 'black');
     * console.log(cat.toString()); // "A black cat, kity"
     * ```
     *
     * @example 混合类的能力
     * ```js
     * var Walkable = kity.createClass('Walkable', {
     *     constructor: function() {
     *         this.speed = 'fast';
     *     },
     *     walk: function() {
     *         console.log('I am walking ' + this.speed);
     *     }
     * });
     *
     * var Dog = kity.createClass('Dog', {
     *     base: Animal,
     *     mixins: [Walkable],
     *     constructor: function(name) {
     *         this.callBase(name);
     *         this.callMixins();
     *     }
     * });
     *
     * var dog = new Dog('doggy');
     * console.log(dog.toString() + ' say:');
     * dog.walk();
     * ```
     */
        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;
        };
        /**
     * @method kity.extendClass()
     * @grammar kity.extendClass(clazz, extension) => {Class}
     * @description 拓展一个已有的类
     *
     * @example
     *
     * ```js
     * kity.extendClass(Dog, {
     *     spark: function() {
     *         console.log('wao wao wao!');
     *     }
     * });
     *
     * new Dog().spark(); // "wao wao wao!";
     * ```
     */
        exports.extendClass = extend;
    }
};

//src/core/utils.js
/**
 * @fileOverview
 *
 * 一些常用的工具方法
 */
_p[12] = {
    value: function() {
        /**
     * @class kity.Utils
     * @catalog core
     * @static
     * @description 提供常用的工具方法
     */
        var utils = {
            /**
         * @method each()
         * @for kity.Utils
         * @grammar each(obj, interator, context)
         * @param  {Object|Array} obj 要迭代的对象或数组
         * @param  {Function} iterator 迭代函数
         * @param  {Any} context  迭代函数的上下文
         *
         * @example 迭代数组
         *
         * ```js
         * kity.Utils.each([1, 2, 3, 4, 5], function(value, index, array) {
         *     console.log(value, index);
         * });
         * // 1, 0
         * // 2, 1
         * // 3, 2
         * // 4, 3
         * // 5, 4
         * ```
         *
         * @example 迭代对象
         *
         * ```js
         * var obj = {
         *     name: 'kity',
         *     version: '1.2.1'
         * };
         * var param = [];
         * kity.Utils.each(obj, function(value, key, obj) {
         *     param.push(key + '=' + value);
         * });
         * console.log(param.join('&')); // "name=kity&version=1.2.1"
         * ```
         */
            each: function each(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;
                            }
                        }
                    }
                }
            },
            /**
         * @method extend()
         * @for kity.Utils
         * @grammar extend(target, sources..., notCover) => {object}
         * @description 把源对象的属性合并到目标对象上
         * @param {object} target 目标对象
         * @param {parameter} sources 源对象
         * @param {boolean} notCover 是否不要覆盖源对象已有的属性
         *
         * @example
         *
         * ```js
         * var a = {
         *     key1: 'a1',
         *     key2: 'a2'
         * };
         *
         * var b = {
         *     key2: 'b2',
         *     key3: 'b3'
         * };
         *
         * var c = {
         *     key4: 'c4'
         * };
         *
         * var d = kity.extend(a, b, c);
         *
         * console.log(d === a); // true
         * console.log(a); // {key1: 'a1', key2: 'b2', key3: 'b3', key4: 'c4'}
         * ```
         */
            extend: function extend(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;
            },
            /**
         * @method deepExtend()
         * @for kity.Utils
         * @grammar deepExtend(target, sources..., notCover)
         * @description 把源对象的属性合并到目标对象上,如果属性是对象,会递归合并
         * @param {object} target 目标对象
         * @param {parameter} sources 源对象
         * @param {boolean} notCover 是否不要覆盖源对象已有的属性
         */
            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;
            },
            /**
         * @method clone()
         * @for kity.Utils
         * @grammar clone(obj) => {object}
         * @description 返回一个对象的克隆副本(非深度复制)
         * @param  {object} obj 要克隆的对象
         *
         * @example
         *
         * ```js
         * var source = {
         *     key1: {
         *         key2: 'value2'
         *     },
         *     key3: 'value3'
         * };
         *
         * var target = kity.Utils.clone(source);
         *
         * console.log(target === source); // false
         * console.log(target.key1 === source.key1); // true
         * console.log(target.key3 === source.key3); // true
         * ```
         */
            clone: function clone(obj) {
                var cloned = {};
                for (var m in obj) {
                    if (obj.hasOwnProperty(m)) {
                        cloned[m] = obj[m];
                    }
                }
                return cloned;
            },
            /**
         * @method copy()
         * @for kity.Utils
         * @grammar copy(obj) => {object}
         * @description 返回一个对象的拷贝副本(深度复制)
         * @param  {object} obj 要拷贝的对象
         *
         * @example
         *
         * ```js
         * var source = {
         *     key1: {
         *         key2: 'value2'
         *     },
         *     key3: 'value3'
         * };
         *
         * var target = kity.Utils.copy(source);
         *
         * console.log(target === source); // false
         * console.log(target.key1 === source.key1); // false
         * console.log(target.key3 === source.key3); // true,因为是值类型
         * ```
         */
            copy: function copy(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;
            },
            /**
         * @method flatten()
         * @for kity.Utils
         * @grammar flatten(arr) => {Array}
         * @description 返回给定数组的扁平化版本
         * @param  {Array} arr 要扁平化的数组
         *
         * @example
         *
         * ```js
         * var flattened = kity.Utils.flatten([[1, 2], [2, 3], [[4, 5], [6, 7]]]);
         * console.log(flattened); // [1, 2, 3, 4, 5, 6, 7];
         * ```
         */
            flatten: function flatten(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;
            },
            /**
         * @method paralle()
         * @for kity.Utils
         * @grammar paralle() => {Any}
         *
         * @description 平行地对 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 操作函数
         *
         *
         *
         * @example
         *
         * ```js
         * var a = {
         *     value1: 1,
         *     value2: 2,
         *     value3: [3, 4, 5]
         * };
         *
         * var b = {
         *     value1: 2,
         *     value2: 3,
         *     value3: [4, 5, 6]
         * };
         *
         * var c = kity.Utils.paralle(a, b, function(v1, v2) {
         *     return v1 + v2;
         * });
         *
         * console.log(c.value1); // 3
         * console.log(c.value2); // 5
         * console.log(c.value3); // [7, 9, 11]
         *
         * ```
         */
            paralle: function paralle(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 parallelize(op) {
                return function(v1, v2) {
                    return utils.paralle(v1, v2, op);
                };
            }
        };
        /**
     * @method isString()
     * @for kity.Utils
     * @grammar isString(unknown) => {boolean}
     * @description 判断一个值是否为字符串类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isFunction()
     * @for kity.Utils
     * @grammar isFunction(unknown) => {boolean}
     * @description 判断一个值是否为函数类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isArray()
     * @for kity.Utils
     * @grammar isArray(unknown) => {boolean}
     * @description 判断一个值是否为数组类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isNumber()
     * @for kity.Utils
     * @grammar isNumber(unknown) => {boolean}
     * @description 判断一个值是否为数字类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isRegExp()
     * @for kity.Utils
     * @grammar isRegExp(unknown) => {boolean}
     * @description 判断一个值是否为正则表达式类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isObject()
     * @for kity.Utils
     * @grammar isObject(unknown) => {boolean}
     * @description 判断一个值是否为对象类型
     * @param  {any} unknown 要判断的值
     */
        /**
     * @method isBoolean()
     * @for kity.Utils
     * @grammar isBoolean(unknown) => {boolean}
     * @description 判断一个值是否为布尔类型
     * @param  {any} unknown 要判断的值
     */
        utils.each([ "String", "Function", "Array", "Number", "RegExp", "Object", "Boolean" ], function(v) {
            utils["is" + v] = function typeCheck(obj) {
                return Object.prototype.toString.apply(obj) == "[object " + v + "]";
            };
        });
        return utils;
    }
};

//src/filter/effect/colormatrixeffect.js
/**
 * 颜色矩阵运算效果封装
 */
_p[13] = {
    value: function(require, exports, module) {
        var Effect = _p.r(16), Utils = _p.r(12);
        var ColorMatrixEffect = _p.r(11).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;
    }
};

//src/filter/effect/compositeeffect.js
/**
 * 高斯模糊效果封装
 */
_p[14] = {
    value: function(require, exports, module) {
        var Effect = _p.r(16), Utils = _p.r(12);
        var CompositeEffect = _p.r(11).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;
    }
};

//src/filter/effect/convolvematrixeffect.js
/**
 * 像素级别的矩阵卷积运算效果封装
 */
_p[15] = {
    value: function(require, exports, module) {
        var Effect = _p.r(16), Utils = _p.r(12);
        var ConvolveMatrixEffect = _p.r(11).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;
    }
};

//src/filter/effect/effect.js
/*
 * 效果类
 * 该类型的对象不存储任何内部属性, 所有操作都是针对该类对象所维护的节点进行的
 */
_p[16] = {
    value: function(require, exports, module) {
        var svg = _p.r(67), Effect = _p.r(11).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") || "";
            }
        });
        _p.r(12).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;
    }
};

//src/filter/effect/gaussianblureffect.js
/**
 * 高斯模糊效果封装
 */
_p[17] = {
    value: function(require, exports, module) {
        var Effect = _p.r(16), Utils = _p.r(12);
        return _p.r(11).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));
            }
        });
    }
};

//src/filter/effect/offseteffect.js
/**
 * 偏移效果封装
 */
_p[18] = {
    value: function(require, exports, module) {
        var Effect = _p.r(16), Utils = _p.r(12);
        return _p.r(11).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));
            }
        });
    }
};

//src/filter/effectcontainer.js
/*
 * Effect所用的container
 */
_p[19] = {
    value: function(require) {
        return _p.r(11).createClass("EffectContainer", {
            base: _p.r(29),
            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());
            }
        });
    }
};

//src/filter/filter.js
/**
 * Filter 基类
 */
_p[20] = {
    value: function(require, exports, module) {
        var svg = _p.r(67);
        var Class = _p.r(11);
        var Filter = Class.createClass("Filter", {
            mixins: [ _p.r(19) ],
            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 = _p.r(60);
        Class.extendClass(Shape, {
            applyFilter: function(filter) {
                var filterId = filter.get("id");
                if (filterId) {
                    this.node.setAttribute("filter", "url(#" + filterId + ")");
                }
                return this;
            }
        });
        return Filter;
    }
};

//src/filter/gaussianblurfilter.js
/*
 * 高斯模糊滤镜
 */
_p[21] = {
    value: function(require, exports, module) {
        var GaussianblurEffect = _p.r(17);
        return _p.r(11).createClass("GaussianblurFilter", {
            base: _p.r(20),
            constructor: function(stdDeviation) {
                this.callBase();
                this.addEffect(new GaussianblurEffect(stdDeviation));
            }
        });
    }
};

//src/filter/projectionfilter.js
/*
 * 投影滤镜
 */
_p[22] = {
    value: function(require, exports, module) {
        var GaussianblurEffect = _p.r(17), Effect = _p.r(16), ColorMatrixEffect = _p.r(13), Color = _p.r(28), Utils = _p.r(12), CompositeEffect = _p.r(14), OffsetEffect = _p.r(18);
        return _p.r(11).createClass("ProjectionFilter", {
            base: _p.r(20),
            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);
            }
        });
    }
};

//src/graphic/bezier.js
/**
 * @fileOverview
 *
 * 贝塞尔曲线
 */
_p[23] = {
    value: function(require, exports, module) {
        /**
     * @class kity.Bezier
     * @mixins kity.PointContainer
     * @base kity.Path
     * @description 绘制和使用贝塞尔曲线。贝塞尔曲线作为一个贝塞尔点的容器,任何贝塞尔点的改变都会更改贝塞尔曲线的外观
     */
        return _p.r(11).createClass("Bezier", {
            mixins: [ _p.r(51) ],
            base: _p.r(46),
            /**
         * @constructor
         * @for kity.Bezier
         *
         * @grammar new kity.Bezier(bezierPoints)
         *
         * @param  {kity.BezierPoints[]} bezierPoints 贝塞尔点集合,每个元素应该是 {kity.BezierPoint} 类型
         *
         * @example
         *
         * ```js
         * var bezier = new kity.Bezier([
         *     new kity.BezierPoint(0, 0).setForward(100, 0),
         *     new kity.BezierPoint(100, 100).setBackward(100, 0)
         * ]);
         * ```
         */
            constructor: function(bezierPoints) {
                this.callBase();
                bezierPoints = bezierPoints || [];
                this.changeable = true;
                this.setBezierPoints(bezierPoints);
            },
            /**
         * @method getBezierPoints()
         * @for kity.Bezier
         * @description 返回当前贝塞尔曲线的贝塞尔点集合
         *
         * @grammar getBezierPoints() => {kity.BezierPoints[]}
         *
         */
            getBezierPoints: function() {
                return this.getPoints();
            },
            /**
         * @method setBezierPoints()
         * @for kity.Bezier
         * @description 设置当前贝塞尔曲线的贝塞尔点集合
         *
         * @grammar setBeizerPoints(bezierPoints) => {this}
         *
         * @param {kity.BezierPoint[]} bezierPoints 贝塞尔点集合
         */
            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;
            }
        });
    }
};

//src/graphic/bezierpoint.js
/**
 * @fileOverview
 *
 * 表示一个贝塞尔点
 */
_p[24] = {
    value: function(require, exports, module) {
        var ShapePoint = _p.r(63);
        var Vector = _p.r(73);
        /**
     * @class kity.BezierPoint
     *
     * @description 表示一个贝塞尔点
     *              一个贝塞尔点由顶点坐标(曲线经过的点)、前方控制点、后方控制点表示
     */
        var BezierPoint = _p.r(11).createClass("BezierPoint", {
            /**
         * @constructor
         * @for kity.BezierPoint
         *
         * @description 创建一个具有默认顶点坐标的贝塞尔点,两个控制点的坐标和顶点一致
         *
         * @param  {Number}  x        顶点的 x 坐标
         * @param  {Number}  y        顶点的 y 坐标
         * @param  {Boolean} isSmooth 指示当前贝塞尔点是否光滑,光滑会约束顶点和两个控制点共线
         */
            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);
            },
            /**
         * @method clone()
         * @for kity.BezierPoint
         * @description 返回贝塞尔点的一份拷贝
         *
         * @grammar clone() => {kity.BezierPoint}
         */
            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.setSymReflaction(this.isSymReflaction);
                newPoint.setSmooth(this.isSmooth());
                return newPoint;
            },
            /**
         * @method setVertex()
         * @for kity.BezierPoint
         * @description 设置贝塞尔点的顶点坐标,注意,控制点的坐标不会跟着变化。希望控制点的坐标跟着变化,请用 moveTo() 方法
         *
         * @grammar setVertex(x, y) => {this}
         *
         * @param {Number} x 顶点的 x 坐标
         * @param {Number} y 顶点的 y 坐标
         */
            setVertex: function(x, y) {
                this.vertex.setPoint(x, y);
                this.update();
                return this;
            },
            /**
         * @method moveTo()
         * @for kity.BezierPoint
         * @description 同步移动整个贝塞尔点,使顶点的移动到指定的坐标中。控制点的位置相对顶点坐标固定。
         *
         * @grammar moveTo() => {this}
         *
         * @param  {Number} x 顶点的目标 x 坐标
         * @param  {Number} y 顶点的目标 y 坐标
         *
         */
            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();
            },
            /**
         * @method setForward()
         * @for kity.BezierPoint
         * @description 设置前方控制点的位置,如果贝塞尔点光滑,后方控制点会跟着联动
         *
         * @grammar setForward(x, y) => {this}
         *
         * @param {Number} x 前方控制点的 x 坐标
         * @param {Number} y 前方控制点的 y 坐标
         */
            setForward: function(x, y) {
                this.forward.setPoint(x, y);
                //更新后置点
                if (this.smooth) {
                    this.updateAnother(this.forward, this.backward);
                }
                this.update();
                this.lastControlPointSet = this.forward;
                return this;
            },
            /**
         * @method setBackward()
         * @for kity.BezierPoint
         * @description 设置后方控制点的位置,如果贝塞尔点光滑,前方控制点会跟着联动
         *
         * @grammar setBackward(x, y) => {this}
         *
         * @param {Number} x 后方控制点的 x 坐标
         * @param {Number} y 后方控制点的 y 坐标
         */
            setBackward: function(x, y) {
                this.backward.setPoint(x, y);
                //更新前置点
                if (this.smooth) {
                    this.updateAnother(this.backward, this.forward);
                }
                this.update();
                this.lastControlPointSet = this.backward;
                return this;
            },
            /**
         * @method setSymReflaction()
         * @for kity.BezierPoint
         * @description 设定是否镜像两个控制点的位置
         *
         * @grammar setSymReflaction(value) => {this}
         *
         * @param {boolean} value 如果设置为 true,且贝塞尔点光滑,两个控制点离顶点的距离相等
         */
            setSymReflaction: function(value) {
                this.symReflaction = value;
                if (this.smooth) this.setSmooth(true);
                return this;
            },
            /**
         * @method isSymReflaction()
         * @for kity.BezierPoint
         * @description 当前贝塞尔点的两个控制点是否被镜像约束
         *
         * @grammar isSymReflaction() => {boolean}
         */
            isSymReflaction: function() {
                return this.symReflaction;
            },
            /**
         * @private
         *
         * 根据前方控制点或后方控制点更新另一方
         */
            updateAnother: function(p, q) {
                var v = this.getVertex(), pv = Vector.fromPoints(p.getPoint(), v), vq = Vector.fromPoints(v, q.getPoint());
                vq = pv.normalize(this.isSymReflaction() ? pv.length() : vq.length());
                q.setPoint(v.x + vq.x, v.y + vq.y);
                return this;
            },
            /**
         * @method setSmooth()
         * @for kity.BezierPoint
         * @description 设置贝塞尔点是否光滑,光滑会约束顶点和两个控制点共线
         *
         * @param {Boolean} isSmooth 设置为 true 让贝塞尔点光滑
         */
            setSmooth: function(isSmooth) {
                var lc;
                this.smooth = !!isSmooth;
                if (this.smooth && (lc = this.lastControlPointSet)) {
                    this.updateAnother(lc, lc == this.forward ? this.backward : this.forward);
                }
                return this;
            },
            /**
         * @method isSmooth()
         * @for kity.BezierPoint
         * @description 判断贝塞尔点是否光滑
         *
         * @grammar isSmooth() => {boolean}
         */
            isSmooth: function() {
                return this.smooth;
            },
            /**
         * @method getVertex()
         * @for kity.BezierPoint
         * @description 获得当前贝塞尔点的顶点
         *
         * @grammar getVertex() => {kity.ShapePoint}
         */
            getVertex: function() {
                return this.vertex.getPoint();
            },
            /**
         * @method getForward()
         * @for kity.BezierPoint
         * @description 获得当前贝塞尔点的前方控制点
         *
         * @grammar getForward() => {kity.ShapePoint}
         */
            getForward: function() {
                return this.forward.getPoint();
            },
            /**
         * @method getBackward()
         * @for kity.BezierPoint
         * @description 获得当前贝塞尔点的后方控制点
         *
         * @grammar getBackward() => {kity.ShapePoint}
         */
            getBackward: function() {
                return this.backward.getPoint();
            },
            /**
         * @private
         *
         * 联动更新相关的贝塞尔曲线
         */
            update: function() {
                if (!this.container) {
                    return this;
                }
                //新增参数 this, 把当前引起变化的点传递过去, 以便有需要的地方可以获取到引起变化的源
                if (this.container.update) this.container.update(this);
            }
        });
        return BezierPoint;
    }
};

//src/graphic/box.js
/**
 * @fileOverview
 *
 * 表示一个矩形区域
 */
_p[25] = {
    value: function(require, exports, module) {
        /**
     * @class kity.Box
     * @description 表示一个矩形区域
     */
        var Box = _p.r(11).createClass("Box", {
            /**
         * @constructor
         * @for kity.Box
         *
         * @grammar new kity.Box(x, y, width, height)
         * @grammar new kity.Box(box)
         *
         * @param  {Number} x|box.x      矩形区域的 x 坐标
         * @param  {Number} y|box.y      矩形区域的 y 坐标
         * @param  {Number} width|box.width   矩形区域的宽度
         * @param  {Number} height|box.height 矩形区域的高度
         *
         * @example
         *
         * ```js
         * var box = new kity.Box(10, 20, 50, 50);
         * var box2 = new kity.Box({x: 10, y: 20, width: 50, height: 50});
         * ```
         */
            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;
                }
                /**
             * @property x
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的 x 坐标
             */
                this.x = x || 0;
                /**
             * @property y
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的 y 坐标
             */
                this.y = y || 0;
                /**
             * @property width
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的宽度
             */
                this.width = width || 0;
                /**
             * @property height
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的高度
             */
                this.height = height || 0;
                /**
             * @property left
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的最左侧坐标,等价于 x 的值
             */
                this.left = this.x;
                /**
             * @property right
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的最右侧坐标,等价于 x + width 的值
             */
                this.right = this.x + this.width;
                /**
             * @property top
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的最上侧坐标,等价于 y 的值
             */
                this.top = this.y;
                /**
             * @property bottom
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的最下侧坐标,等价于 y + height 的值
             */
                this.bottom = this.y + this.height;
                /**
             * @property cx
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的中心 x 坐标
             */
                this.cx = this.x + this.width / 2;
                /**
             * @property cy
             * @for kity.Box
             * @type {Number}
             * @readOnly
             * @description 矩形区域的中心 y 坐标
             */
                this.cy = this.y + this.height / 2;
            },
            /**
         * @method getRangeX()
         * @for kity.Box
         * @description 获得矩形区域的 x 值域
         *
         * @grammar getRangeX() => {Number[]}
         *
         * @example
         *
         * var box = new kity.Box(10, 10, 30, 50);
         * console.log(box.getRangeX()); // [10, 40]
         */
            getRangeX: function() {
                return [ this.left, this.right ];
            },
            /**
         * @method getRangeY()
         * @for kity.Box
         * @description 获得矩形区域的 y 值域
         *
         * @grammar getRangeY() => {Number[]}
         *
         * @example
         *
         * var box = new kity.Box(10, 10, 30, 50);
         * console.log(box.getRangeY()); // [10, 60]
         */
            getRangeY: function() {
                return [ this.top, this.bottom ];
            },
            /**
         * @method merge()
         * @for kity.Box
         * @description 把当前矩形区域和指定的矩形区域合并,返回一个新的矩形区域(即包含两个源矩形区域的最小矩形区域)
         *
         * @grammar merge(another) => {kity.Box}
         * @param  {kity.Box} another 要合并的矩形区域
         *
         * @example
         *
         * ```js
         * var box1 = new kity.Box(10, 10, 50, 50);
         * var box2 = new kity.Box(30, 30, 50, 50);
         * var box3 = box1.merge(box2);
         * console.log(box3.valueOf()); // [10, 10, 70, 70]
         * ```
         */
            merge: function(another) {
                if (this.isEmpty()) {
                    return new Box(another.x, another.y, another.width, another.height);
                }
                var left = Math.min(this.left, another.left), right = Math.max(this.right, another.right), top = Math.min(this.top, another.top), bottom = Math.max(this.bottom, another.bottom);
                return new Box(left, top, right - left, bottom - top);
            },
            /**
         * @method intersect()
         * @for kity.Box
         * @description 求当前矩形区域和指定的矩形区域重叠的矩形区域
         *
         * @grammar intersect(another) => {kity.Box}
         * @param  {kity.Box} another 要求重叠的矩形区域
         *
         * @example
         *
         * ```js
         * var box1 = new kity.Box(10, 10, 50, 50);
         * var box2 = new kity.Box(30, 30, 50, 50);
         * var box3 = box1.intersect(box2);
         * console.log(box3.valueOf()); // [30, 30, 20, 20]
         * ```
         */
            intersect: function(another) {
                if (!another instanceof Box) {
                    another = new Box(another);
                }
                var left = Math.max(this.left, another.left), right = Math.min(this.right, another.right), top = Math.max(this.top, another.top), bottom = Math.min(this.bottom, another.bottom);
                if (left > right || top > bottom) return new Box();
                return new Box(left, top, right - left, bottom - top);
            },
            /**
         * @method expand()
         * @for kity.Box
         * @description 扩展(或收缩)当前的盒子,返回新的盒子
         *
         * @param {Number} top
         *     矩形区域的上边界往上扩展的值;如果是负数,则上边界往下收缩
         *
         * @param {Number} right
         *     [Optional] 矩形区域的右边界往右拓展的值;
         *                如果是负数,则右边界往左收缩;
         *                如果不设置该值,使用和 top 同样的值。
         *
         * @param {Number} bottom
         *     [Optional] 矩形区域的下边界往下拓展的值;
         *                如果是负数,则下边界往上收缩;
         *                如果不设置该值,使用和 top 同样的值。
         *
         * @param {Number} left
         *     [Optional] 矩形区域的左边界往左拓展的值;
         *                如果是负数,则左边界往右收缩;
         *                如果不设置该值,使用和 right 同样的值。
         *
         * @example
         *
         * ```js
         * var box = new kity.Box(10, 10, 20, 20);
         * var box1 = box.expand(10); // [0, 0, 40, 40]
         * var box2 = box.expand(10, 20); // [0, -10, 40, 60]
         * var box3 = box.expand(1, 2, 3, 4); // [9, 8, 24, 26]
         * ```
         */
            expand: function(top, right, bottom, left) {
                if (arguments.length < 1) {
                    return new Box(this);
                }
                if (arguments.length < 2) {
                    right = top;
                }
                if (arguments.length < 3) {
                    bottom = top;
                }
                if (arguments.length < 4) {
                    left = right;
                }
                var x = this.left - left, y = this.top - top, width = this.width + right, height = this.height + top;
                return new Box(x, y, width, height);
            },
            /**
         * @method valueOf()
         * @for kity.Box
         * @description 返回当前盒子的数组表示
         *
         * @grammar valueOf() => {Number[]}
         *
         * @example
         *
         * ```js
         * var box = new kity.Box(0, 0, 200, 50);
         * console.log(box.valueOf()); // [0, 0, 200, 50]
         * ```
         */
            valueOf: function() {
                return [ this.x, this.y, this.width, this.height ];
            },
            /**
         * @method toString()
         * @for kity.Box
         * @description 返回当前盒子的字符串表示
         *
         * @grammar toString() => {String}
         *
         * @example
         *
         * ```js
         * var box = new kity.Box(0, 0, 200, 50);
         * console.log(box.toString()); // "0 0 200 50"
         */
            toString: function() {
                return this.valueOf().join(" ");
            },
            /**
         * @method isEmpty()
         * @for kity.Box
         * @description 判断当前盒子是否具有尺寸(面积大
         *
         * @grammar isEmpty() => {boolean}
         *
         * @example
         * ```js
         * var box = new kity.Box(0, 0, 0, 100000);
         * console.log(box.isEmpty()); // true
         * ```
         */
            isEmpty: function() {
                return !this.width || !this.height;
            }
        });
        /**
     * @method parse()
     * @static
     * @for kity.Box
     * @description 解析一个字符串或数组为 kity.Box 对象
     *
     * @grammar kity.Box.parse(any) => {kity.Box}
     *
     * @param  {Number[]|String} any 要解析的字符串或数组
     *
     * @example
     *
     * ```js
     * console.log(kity.Box.parse('0 0 100 200'));
     * console.log(kity.Box.parse([0, 0, 100, 200]));
     * ```
     */
        Box.parse = function(any) {
            if (typeof any == "string") {
                return Box.parse(any.split(/[\s,]+/).map(parseFloat));
            }
            if (any instanceof Array) {
                return new Box(any[0], any[1], any[2], any[3]);
            }
            if ("x" in any) return new Box(any);
            return null;
        };
        return Box;
    }
};

//src/graphic/circle.js
/**
 * @fileOverview
 *
 * 绘制和使用圆形
 */
_p[26] = {
    value: function(require, exports, module) {
        /**
     * @class kity.Circle
     * @base kity.Ellipse
     * @description 表示一个圆形
     */
        return _p.r(11).createClass("Circle", {
            base: _p.r(32),
            /**
         * @constructor
         * @for kity.Circle
         *
         * @grammar new kity.Circle(radius, cx, cy)
         *
         * @param  {Number} radius 半径
         * @param  {Number} cx     圆心 x 坐标
         * @param  {Number} cy     圆心 y 坐标
         */
            constructor: function(radius, cx, cy) {
                this.callBase(radius, radius, cx, cy);
            },
            /**
         * @method
         * @for kity.Circle
         * @description 获取圆形的半径
         *
         * @grammar getRadius() => {Number}
         */
            getRadius: function() {
                return this.getRadiusX();
            },
            /**
         * @method
         * @for kity.Circle
         * @description 设置圆形的半径
         *
         * @grammar setRadius() => {this}
         *
         * @param {Number} radius 半径大小
         */
            setRadius: function(radius) {
                return this.callBase(radius, radius);
            }
        });
    }
};

//src/graphic/clip.js
/**
 * @fileOverview
 *
 * 支持图形裁切
 */
_p[27] = {
    value: function(require, exports, module) {
        var Class = _p.r(11);
        var Shape = _p.r(60);
        /**
     * @class kity.Clip
     * @base kity.Resource
     * @mixins kity.ShapeContainer
     *
     * @description 创建图形裁切,用于裁切目标图形
     */
        var Clip = Class.createClass("Clip", {
            base: Shape,
            mixins: [ _p.r(61) ],
            /**
         * @constructor
         * @for kity.Clip
         *
         * @grammar new kity.Clip(paper)
         *
         * @param  {kity.Paper} paper 资源所属的文档
         *
         * @example
         *
         * ```js
         * var circle = paper.put(new kity.Circle(100).fill('yellow'));
         * var clip = new kity.Clip(paper);
         * clip.addShape(new kity.Circle(100, 50, 0));
         * clip.clip(circle);
         * ```
         */
            constructor: function(paper) {
                this.callBase("clipPath", paper);
            },
            /**
         * @method clip()
         * @for kity.Clip
         * @description 将裁切应用到指定的图形上,应用之后,目标图形将显示与裁切形状重合的部分
         *
         * @grammar clip(shape) => {this}
         *
         * @param  {kity.Shape} shape 要应用裁切的图形
         */
            clip: function(shape) {
                shape.getNode().setAttribute("clip-path", this);
                return this;
            }
        });
        Class.extendClass(Shape, {
            /**
         * @method clipWidth()
         * @for kity.Shape
         *
         * @grammar clipWidth(clip) => {this}
         *
         * @param {kity.Clip|kity.Shape} clip 要用于裁切当前图形的图形;
         *     如果 clip 本身是一个裁切对象(kity.Clip 类型),则直接裁切;
         *     否则将创建新的裁切包含给定的图形,然后对当前图形进行裁切
         *
         * @example
         *
         * ```js
         * var circle = paper.put(new kity.Circle(100));
         * var rect = paper.put(new kity.Rect(100, 100, -100, 0));
         *
         * circle.clipWidth(rect);
         * ```
         */
            clipWith: function(clip) {
                if (clip instanceof Shape) {
                    clip = new Clip(clip.getPaper()).addShape(clip);
                }
                clip.clip(this);
                return this;
            }
        });
        return Clip;
    }
};

//src/graphic/color.js
/**
 * @fileOverview
 *
 * 提供颜色支持
 */
_p[28] = {
    value: function(require, exports, module) {
        var Utils = _p.r(12), StandardColor = _p.r(64), ColorUtils = {}, /**
         * @class kity.Color
         * @description 表示一个颜色
         */
        Color = _p.r(11).createClass("Color", {
            /**
             * @constructor
             * @for kity.Color
             *
             * @grammar new kity.Color(r, g, b)
             * @grammar new kity.Color(r, g, b, a)
             * @grammar new kity.Color(colorString)
             *
             * @param {Number} r 红色分量,取值 0 - 255
             * @param {Number} g 绿色分量,取值 0 - 255
             * @param {Number} b 蓝色分量,取值 0 - 255
             * @param {Number} a 透明度(可选),取值 0 - 100
             * @param {String} colorString 一个代表颜色的字符串,可以是:
             *     熟知颜色表:如 'red', 'yellow'
             *     HEX 表示:如 '#368', '#123456'
             *     RGB 表示:如 'RGB(200, 200, 0)', 'RGBA(200, 200, 200, .5)'
             *     HSL 表示:如 'HSL(100, 60%, 80%)', 'HSLA(100, 60%, 80%, .5)'
             */
            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: arguments[3] === undefined ? 1 : parseFloat(arguments[3])
                    };
                    colorValue = ColorUtils.overflowFormat(colorValue);
                    //获取hsl分量
                    colorValue = Utils.extend(colorValue, ColorUtils.rgbValueToHslValue(colorValue));
                }
                this._color = colorValue;
            },
            /**
             * @method set()
             * @for kity.Color
             *
             * @description 设置当前颜色某个分量的值
             *
             * @grammar set(name, value) => {this}
             *
             * @param {string} name  要设置的颜色通道的名称
             *     r: 红色(Red),取值范围 [0, 255]
             *     g: 绿色(Green),取值范围 [0, 255]
             *     b: 蓝色(Blue),取值范围 [0, 255]
             *     a: 透明度(Alpha),取值范围 [0, 1]
             *     h: 色环角度(Hue),取值范围 [0, 359]
             *     s: 饱和度(Saturation),取值范围 [0, 100]
             *     l: 亮度(Lightness),取值范围 [0, 100]
             *     r、g、b 值和 h、s、l 值会联动修改
             * @param {number} value 要设置的值
             */
            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;
            },
            /**
             * @method inc()
             *
             * @description 返回新的颜色,表示当前颜色增加指定通道的值之后的颜色
             *
             * @grammar inc(name, value) => {this}
             *
             * @param  {string} name  要增加的通道的名称,具体含义请查看 set 方法
             * @param  {number} value 增量值
             */
            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);
            },
            /**
             * @method dec()
             * @for kity.Color
             *
             * @description 返回新的颜色,表示当前颜色减少指定通道的值之后的颜色
             *
             * @grammar dec(name, value) => {this}
             *
             * @param  {string} name  要减少值的通道的名称,具体含义请查看 set 方法
             * @param  {number} value 减量值
             */
            dec: function(name, value) {
                return this.inc(name, -value);
            },
            /**
             * @method clone()
             * @for kity.Color
             *
             * @description 返回当前颜色的一个拷贝
             *
             * @grammar clone() => {kity.Color}
             */
            clone: function() {
                return new Color(this.toRGBA());
            },
            /**
             * @method get()
             * @for kity.Color
             *
             * @description 返回当前颜色指定的分量
             *
             * @grammar get() => {number}
             */
            get: function(name) {
                if (!Color._MAX_VALUE[name]) {
                    return null;
                }
                return this._color[name];
            },
            getValues: function() {
                return Utils.clone(this._color);
            },
            /**
             * @method valueOf()
             * @for kity.Color
             *
             * @description 返回当前颜色的一个字面量表示
             *
             * @return {plain} 颜色字面量,其结构为:
             *     {
             *         r: 0,
             *         g: 0,
             *         b: 0,
             *         a: 0,
             *         h: 0,
             *         s: 0,
             *         l: 0
             *     }
             */
            valueOf: function() {
                return this.getValues();
            },
            /**
             * @method toRGB()
             * @for kity.Color
             *
             * @description 返回当前颜色的 RGB 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toRGBA())方法。
             *
             * @grammar toRGB() => {string}
             */
            toRGB: function() {
                return ColorUtils.toString(this._color, "rgb");
            },
            /**
             * @method toRGBA()
             * @for kity.Color
             *
             * @description 返回当前颜色的 RGBA 表示
             *
             * @grammar toRGBA() => {string}
             */
            toRGBA: function() {
                return ColorUtils.toString(this._color, "rgba");
            },
            /**
             * @method toHEX()
             * @for kity.Color
             *
             * @description 返回当前颜色的 HEX 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toRGBA())方法。
             *
             * @grammar toHEX() => {string}
             */
            toHEX: function() {
                return ColorUtils.toString(this._color, "hex");
            },
            /**
             * @method toHSL()
             * @for kity.Color
             *
             * @description 返回当前颜色的 HSL 表示,如果颜色有透明度,将抛弃透明度属性(想要保留请使用 toHSLA())方法。
             *
             * @grammar toHSL() => {string}
             */
            toHSL: function() {
                return ColorUtils.toString(this._color, "hsl");
            },
            /**
             * @method toHSLA()
             * @for kity.Color
             *
             * @description 返回当前颜色的 HSLA 表示
             *
             * @grammar toHSLA() => {string}
             */
            toHSLA: function() {
                return ColorUtils.toString(this._color, "hsla");
            },
            /**
             * @method toString()
             * @for kity.Color
             *
             * @description 返回当前颜色的 RGB 或 RGBA 表示,如果颜色有透明度,将使用 RGBA 形式,否则是 RGB 形式
             * @grammar toString() => {string}
             */
            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",
            /**
         * @method parse()
         * @static
         * @for kity.Color
         *
         * @description 解析一个颜色字符串为 kity.Color 对象
         *
         * @grammar kity.Color.parse(valStr)
         *
         * @param  {string} valStr 一个代表颜色的字符串,可以是:
         *     熟知颜色表:如 'red', 'yellow'
         *     HEX 表示:如 '#368', '#123456'
         *     RGB 表示:如 'RGB(200, 200, 0)', 'RGBA(200, 200, 200, .5)'
         *     HSL 表示:如 'HSL(100, 60%, 80%)', 'HSLA(100, 60%, 80%, .5)'
         */
            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);
            },
            /**
         * @method createHSL()
         * @for kity.Color
         * @static
         *
         * @description 创建一个 HSL 颜色
         *
         * @grammar kity.Color.createHSL(h, s, l) => {kity.Color}
         *
         * @param  {number} h 色环(Hue)分量值,取值范围 [0, 359]
         * @param  {number} s 饱和度(Saturation)分量值,取值范围 [0, 100]
         * @param  {number} l 亮度(Lighteness)分量值,取值范围 [0, 100]
         */
            createHSL: function(h, s, l) {
                return Color.createHSLA(h, s, l, 1);
            },
            /**
         * @method createHSLA()
         * @for kity.Color
         * @static
         *
         * @description 创建一个 HSLA 颜色
         *
         * @grammar kity.Color.createHSLA(h, s, l, a) => {kity.Color}
         *
         * @param  {number} h 色环(Hue)分量值,取值范围 [0, 359]
         * @param  {number} s 饱和度(Saturation)分量值,取值范围 [0, 100]
         * @param  {number} l 亮度(Lighteness)分量值,取值范围 [0, 100]
         * @param  {number} a 透明度(Alpha)分量值,取值范围 [0, 1]
         */
            createHSLA: function(h, s, l, a) {
                var colorValue = null;
                s += "%";
                l += "%";
                colorValue = [ "hsla(" + h, s, l, a + ")" ];
                return Color.parse(colorValue.join(", "));
            },
            /**
         * @method createRGB()
         * @for kity.Color
         * @static
         *
         * @description 创建一个 RGB 颜色
         *
         * @grammar kity.Color.createRGB(r, g, b) => {kity.Color}
         *
         * @param  {number} r 红色(Red)分量值,取值范围 [0, 255]
         * @param  {number} g 绿色(Green)分量值,取值范围 [0, 255]
         * @param  {number} b 蓝色(Blue)分量值,取值范围 [0, 255]
         */
            createRGB: function(r, g, b) {
                return Color.createRGBA(r, g, b, 1);
            },
            /**
         * @method createRGBA()
         * @for kity.Color
         * @static
         *
         * @description 创建一个 RGBA 颜色
         *
         * @grammar kity.Color.createRGBA(r, g, b, a) => {kity.Color}
         *
         * @param  {number} r 红色(Red)分量值,取值范围 [0, 255]
         * @param  {number} g 绿色(Green)分量值,取值范围 [0, 255]
         * @param  {number} b 蓝色(Blue)分量值,取值范围 [0, 255]
         * @param  {number} a 透明度(Alpha)分量值,取值范围 [0, 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;
    }
};

//src/graphic/container.js
_p[29] = {
    value: function(require, exports, module) {
        function itemRemove() {
            this.container.removeItem(this);
            return this;
        }
        return _p.r(11).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) {}
        });
    }
};

//src/graphic/curve.js
/*
 * 曲线
 * */
_p[30] = {
    value: function(require, exports, module) {
        var Utils = _p.r(12), 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 _p.r(11).createClass("Curve", {
            base: _p.r(46),
            mixins: [ _p.r(51) ],
            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;
            }
        });
    }
};

//src/graphic/data.js
_p[31] = {
    value: function(require, exports, module) {
        return _p.r(11).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;
            }
        });
    }
};

//src/graphic/ellipse.js
_p[32] = {
    value: function(require, exports, module) {
        var Utils = _p.r(12), Point = _p.r(50);
        return _p.r(11).createClass("Ellipse", {
            base: _p.r(46),
            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();
            }
        });
    }
};

//src/graphic/eventhandler.js
/*
 * kity event 实现
 */
_p[33] = {
    value: 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 = _p.r(12), ShapeEvent = _p.r(62);
        // 内部处理器缓存
        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;
            userHandlerList = USER_HANDLER_CACHE[eventId][type];
            //移除指定的监听器
            if (!isRemoveAll) {
                isRemoveAll = true;
                Utils.each(userHandlerList, function removeKityEvent(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 kityEventHandler(e) {
                    e = new ShapeEvent(e || window.event);
                    Utils.each(USER_HANDLER_CACHE[eid][type], function executeKityEvent(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 && "on" + type in 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;
            var handlers = INNER_HANDLER_CACHE[messageObj._EVNET_UID];
            if (!handlers) return;
            handler = handlers[type];
            if (!handler) {
                return;
            }
            event = Utils.extend({
                type: type,
                target: messageObj
            }, msg || {});
            handler.call(messageObj, event);
        }
        // 对外接口
        return _p.r(11).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) {
                sendMessage(this, type, params);
                return this;
            }
        });
    }
};

//src/graphic/geometry.js
_p[34] = {
    value: function(require) {
        var utils = _p.r(12);
        var Point = _p.r(50);
        var Vector = _p.r(73);
        var Matrix = _p.r(43);
        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, j, 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));
                    j = 0;
                    while (j in param) {
                        controlPoint1 = param.slice(j, j + 2);
                        controlPoint2 = param.slice(j + 2, j + 4);
                        endPoint = param.slice(j + 4, j + 6);
                        // 写入当前一段曲线
                        res.push([ "C" ].concat(controlPoint1).concat(controlPoint2).concat(endPoint));
                        j += 6;
                    }
                    break;
                }
                if (command != "A") {
                    // 写入当前一段曲线
                    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) {
            // 表示(c[0]*t^4 + c[1]*t^3 + c[2]*t^2 + c[3]*t^1 + c[4])^(1/2)的函数
            function f(x) {
                var m = c0 * Math.pow(x, 4) + c1 * Math.pow(x, 3) + c2 * Math.pow(x, 2) + c3 * x + c4;
                if (m < 0) {
                    m = 0;
                }
                return Math.pow(m, .5);
            }
            // 用Newton-Cotes型求积公式
            var arr = bezierArray;
            // 三次贝塞尔曲线函数求导后,求出对应的方程系数,用cx[],cy[]表示x`(t)和y`(t)的系数
            var cx0, cx1, cx2;
            var cy0, cy1, cy2;
            // 用c[]表示x`(t)^2 + y`(t)^2的结果的系数
            var c0, c1, c2, c3, c4;
            // 求x`(t) 和 y`(t)的系数
            cx0 = -3 * arr[0] + 9 * arr[2] - 9 * arr[4] + 3 * arr[6];
            cx1 = 6 * arr[0] - 12 * arr[2] + 6 * arr[4];
            cx2 = -3 * arr[0] + 3 * arr[2];
            cy0 = -3 * arr[1] + 9 * arr[3] - 9 * arr[5] + 3 * arr[7];
            cy1 = 6 * arr[1] - 12 * arr[3] + 6 * arr[5];
            cy2 = -3 * arr[1] + 3 * arr[3];
            // 求x`(t)^2 + y`(t)^2的结果的系数 c[]
            c0 = Math.pow(cx0, 2) + Math.pow(cy0, 2);
            c1 = 2 * (cx0 * cx1 + cy0 * cy1);
            c2 = 2 * (cx0 * cx2 + cy0 * cy2) + Math.pow(cx1, 2) + Math.pow(cy1, 2);
            c3 = 2 * (cx1 * cx2 + cy1 * cy2);
            c4 = Math.pow(cx2, 2) + Math.pow(cy2, 2);
            // 用cotes积分公式求值
            return (f(0) + f(1) + 4 * (f(.125) + f(.375) + f(.625) + f(.875)) + 2 * (f(.25) + f(.5) + f(.75))) / 24;
        });
        // 计算一个 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
        _p.r(11).extendClass(Matrix, {
            transformPath: function(path) {
                return g.transformPath(path, this);
            }
        });
        return g;
    }
};

//src/graphic/gradient.js
_p[35] = {
    value: function(require, exports, module) {
        var svg = _p.r(67);
        var Resource = _p.r(58);
        var Color = _p.r(28);
        return _p.r(11).createClass("GradientBrush", {
            base: Resource,
            constructor: function(gradientNodeType, paper) {
                this.callBase(gradientNodeType, paper);
                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;
            }
        });
    }
};

//src/graphic/group.js
_p[36] = {
    value: function(require, exports, module) {
        var ShapeContainer = _p.r(61);
        return _p.r(11).createClass("Group", {
            mixins: [ ShapeContainer ],
            base: _p.r(60),
            constructor: function Group() {
                this.callBase("g");
            }
        });
    }
};

//src/graphic/hyperlink.js
_p[37] = {
    value: function(require, exports, module) {
        var ShapeContainer = _p.r(61);
        return _p.r(11).createClass("HyperLink", {
            mixins: [ ShapeContainer ],
            base: _p.r(60),
            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");
            }
        });
    }
};

//src/graphic/image.js
_p[38] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("Image", {
            base: _p.r(60),
            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;
            }
        });
    }
};

//src/graphic/line.js
_p[39] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("Line", {
            base: _p.r(46),
            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;
            }
        });
    }
};

//src/graphic/lineargradient.js
_p[40] = {
    value: function(require, exports, module) {
        var svg = _p.r(67);
        var Gradient = _p.r(35);
        return _p.r(11).createClass("LinearGradientBrush", {
            base: Gradient,
            constructor: function(paper) {
                this.callBase("linearGradient", paper);
                this.setStartPosition(0, 0);
                this.setEndPosition(1, 0);
            },
            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")
                };
            }
        });
    }
};

//src/graphic/marker.js
_p[41] = {
    value: function(require, exports, module) {
        var Point = _p.r(50);
        var Marker = _p.r(11).createClass("Marker", {
            base: _p.r(58),
            mixins: [ _p.r(61), _p.r(75) ],
            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 = _p.r(46);
        _p.r(11).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;
    }
};

//src/graphic/mask.js
/**
 * 蒙板
 */
_p[42] = {
    value: function(require, exports, module) {
        var Class = _p.r(11);
        var Shape = _p.r(60);
        var Mask = Class.createClass("Mask", {
            base: Shape,
            mixins: [ _p.r(61) ],
            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;
    }
};

//src/graphic/matrix.js
_p[43] = {
    value: function(require, exports, module) {
        var utils = _p.r(12);
        var Box = _p.r(25);
        var mPattern = /matrix\s*\((.+)\)/i;
        var Point = _p.r(50);
        // 注意,合并的结果是先执行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 = _p.r(11).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);
            },
            clone: function() {
                return new Matrix(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
            });
            return box;
        };
        // 获得从 node 到 refer 的变换矩阵
        Matrix.getCTM = function(target, refer) {
            var ctm = {
                a: 1,
                b: 0,
                c: 0,
                d: 1,
                e: 0,
                f: 0
            };
            var node = target.shapeNode || target.node;
            refer = refer || "parent";
            /**
         * 由于新版chrome(dev 48.0)移除了getTransformToElement这个方法可能导致报错,这里做兼容处理
         * @Date 2015-11-12
         * @Editor Naixor
         */
            function getTransformToElement(target, source) {
                var matrix;
                try {
                    matrix = source.getScreenCTM().inverse();
                } catch (e) {
                    throw new Error("Can not inverse source element' ctm.");
                }
                return matrix.multiply(target.getScreenCTM());
            }
            // 根据参照坐标系选区的不一样,返回不同的结果
            switch (refer) {
              case "screen":
                // 以浏览器屏幕为参照坐标系
                ctm = node.getScreenCTM();
                break;

              case "doc":
              case "paper":
                // 以文档(Paper)为参照坐标系
                ctm = node.getCTM();
                break;

              case "view":
              case "top":
                // 以顶层绘图容器(视野)为参照坐标系
                if (target.getPaper()) {
                    ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(target.getPaper().shapeNode) : getTransformToElement(node, target.getPaper().shapeNode);
                }
                break;

              case "parent":
                // 以父容器为参照坐标系
                if (target.node.parentNode) {
                    ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(target.node.parentNode) : getTransformToElement(node, target.node.parentNode);
                }
                break;

              default:
                // 其他情况,指定参照物
                if (refer.node) {
                    ctm = node.getTransformToElement !== undefined ? node.getTransformToElement(refer.shapeNode || refer.node) : getTransformToElement(node, refer.shapeNode || refer.node);
                }
            }
            return ctm ? new Matrix(ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f) : new Matrix();
        };
        return Matrix;
    }
};

//src/graphic/palette.js
/**
 * 调色板
 */
_p[44] = {
    value: function(require, exports, module) {
        //标准color
        var StandardColor = _p.r(64), Color = _p.r(28), Utils = _p.r(12);
        var Palette = _p.r(11).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;
    }
};

//src/graphic/paper.js
_p[45] = {
    value: function(require, exports, module) {
        var Class = _p.r(11);
        var utils = _p.r(12);
        var svg = _p.r(67);
        var Container = _p.r(29);
        var ShapeContainer = _p.r(61);
        var ViewBox = _p.r(75);
        var EventHandler = _p.r(33);
        var Styled = _p.r(66);
        var Matrix = _p.r(43);
        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");
                node.setAttribute("version", "1.1");
                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;
            },
            getViewPortMatrix: function() {
                return Matrix.parse(this.shapeNode.getAttribute("transform"));
            },
            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 = _p.r(60);
        Class.extendClass(Shape, {
            getPaper: function() {
                var parent = this.container;
                while (parent && parent instanceof Paper === false) {
                    parent = parent.container;
                }
                return parent;
            },
            isAttached: function() {
                return !!this.getPaper();
            },
            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;
    }
};

//src/graphic/path.js
_p[46] = {
    value: function(require, exports, module) {
        var Utils = _p.r(12);
        var createClass = _p.r(11).createClass;
        var Shape = _p.r(60);
        var svg = _p.r(67);
        var g = _p.r(34);
        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");
            }
        });
    }
};

//src/graphic/pattern.js
_p[47] = {
    value: function(require, exports, module) {
        var Resource = _p.r(58);
        var ShapeContainer = _p.r(61);
        var svg = _p.r(67);
        return _p.r(11).createClass("PatternBrush", {
            base: Resource,
            mixins: [ ShapeContainer ],
            constructor: function(paper) {
                this.callBase("pattern", paper);
                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;
            }
        });
    }
};

//src/graphic/pen.js
_p[48] = {
    value: function(require, exports, module) {
        var Color = _p.r(28);
        return _p.r(11).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());
                }
            }
        });
    }
};

//src/graphic/pie.js
_p[49] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass({
            base: _p.r(68),
            constructor: function(radius, angle, angleOffset) {
                this.callBase([ 0, radius ], angle, angleOffset);
            },
            getRadius: function() {
                return this.getSectionArray()[1];
            },
            setRadius: function(radius) {
                this.setSectionArray([ 0, radius ]);
            }
        });
    }
};

//src/graphic/point.js
/*
 * 点对象抽象
 */
_p[50] = {
    value: function(require, exports, module) {
        /**
     * @class kity.Point
     * @description 表示一个点
     */
        var Point = _p.r(11).createClass("Point", {
            /**
         * @constructor
         * @for kity.Point
         * @description 指定默认的 x 和 y 创建一个点
         * 
         * @param  {Number} x 点的 x 坐标
         * @param  {Number} y 点的 y 坐标
         */
            constructor: function(x, y) {
                /**
             * @property
             * @for kity.Point
             * @description 表示点的 x 坐标
             * @type {Number}
             */
                this.x = x || 0;
                /**
             * @property
             * @for kity.Point
             * @description 表示点的 y 坐标
             * @type {Number}
             */
                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);
            },
            round: function() {
                return new Point(this.x | 0, this.y | 0);
            },
            isOrigin: function() {
                return this.x === 0 && this.y === 0;
            }
        });
        /**
     * @static
     * @method fromPolar()
     * @for kity.Point
     * @grammar kity.Point.fromPolar(radius, angle, unit) => kity.Point
     * @param  {Number} radius 极坐标中的半径
     * @param  {Number} angle  极坐标中的角度
     * @param  {String} unit   角度使用的单位,默认为 'deg' (角度),可以取值为 'rad',表示传入的是弧度值
     */
        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) return new Point();
            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;
    }
};

//src/graphic/pointcontainer.js
/**
 * 点集合容器
 */
_p[51] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("PointContainer", {
            base: _p.r(29),
            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);
            }
        });
    }
};

//src/graphic/poly.js
/*
 * 通过点来决定图形的公共父类
 */
_p[52] = {
    value: function(require, exports, module) {
        var Utils = _p.r(12);
        return _p.r(11).createClass("Poly", {
            base: _p.r(46),
            mixins: [ _p.r(51) ],
            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;
            }
        });
    }
};

//src/graphic/polygon.js
_p[53] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("Polygon", {
            base: _p.r(52),
            constructor: function(points) {
                this.callBase(points, true);
            }
        });
    }
};

//src/graphic/polyline.js
_p[54] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("Polyline", {
            base: _p.r(52),
            constructor: function(points) {
                this.callBase(points);
            }
        });
    }
};

//src/graphic/radialgradient.js
_p[55] = {
    value: function(require, exports, module) {
        var Gradient = _p.r(35);
        return _p.r(11).createClass("RadialGradientBrush", {
            base: Gradient,
            constructor: function(paper) {
                this.callBase("radialGradient", paper);
                this.setCenter(.5, .5);
                this.setFocal(.5, .5);
                this.setRadius(.5);
            },
            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");
            }
        });
    }
};

//src/graphic/rect.js
_p[56] = {
    value: function(require, exports, module) {
        var RectUtils = {}, Utils = _p.r(12), Point = _p.r(50), Box = _p.r(25);
        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);
            }
        });
        /**
     * @class kity.Rect
     * @description 表示一个矩形
     * @base kity.Path
     */
        var Rect = _p.r(11).createClass("Rect", {
            base: _p.r(46),
            /**
         * @constructor
         * @for kity.Rect
         * @grammar new kity.Rect(width, height, x, y, radius)
         * @param  {Number} width  矩形的初始化宽度
         * @param  {Number} height 矩形的初始化高度
         * @param  {Number} x      矩形的初始化 x 坐标
         * @param  {Number} y      矩形的初始化 y 坐标
         * @param  {Number} radius 矩形的初始化圆角大小
         */
            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;
            },
            /**
         * @method setWidth
         * @for kity.Rect
         * @grammar setWidth(width) => kity.Rect
         * @description 设置矩形的宽度,设置后返回矩形实例本身
         * @param {Number} width 宽度值
         *
         * @example
         * ```js
         * rect.setWidth(300);
         * ```
         */
            setWidth: function(width) {
                this.width = width;
                return this.update();
            },
            /**
         * @method setHeight
         * @for  kity.Rect
         * @grammar setHeight(height) => kity.Rect
         * @description 设置矩形的高度,设置后返回矩形实例本身
         * @param {Number} height 高度值
         *
         * @example
         * ```js
         * rect.setHeight(200);
         * ```
         */
            setHeight: function(height) {
                this.height = height;
                return this.update();
            },
            /**
         * @method setSize
         * @for  kity.Rect
         * @grammar setSize(width, height) => kity.Rect
         * @description 设置矩形的尺寸,设置后返回矩形本身
         * @param {Number} width  矩形的宽度值
         * @param {Number} height 矩形的高度值
         *
         * @example
         * ```js
         * rect.setSize(300, 200);
         * ```
         */
            setSize: function(width, height) {
                this.width = width;
                this.height = height;
                return this.update();
            },
            /**
         * @method setBox
         * @for kity.Rect
         * @grammar setBox(box) => kity.Rect
         * @description 使用一个 kity 的盒子数据,
         * @param {kity.Box} box 盒子数据
         */
            setBox: function(box) {
                this.x = box.x;
                this.y = box.y;
                this.width = box.width;
                this.height = box.height;
                return this.update();
            },
            getBox: function() {
                return new Box(this.x, this.y, this.width, this.height);
            },
            getRadius: function() {
                return this.radius;
            },
            setRadius: function(radius) {
                this.radius = RectUtils.formatRadius(this.width, this.height, radius || 0);
                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();
            }
        });
        return Rect;
    }
};

//src/graphic/regularpolygon.js
_p[57] = {
    value: function(require, exports, module) {
        var Point = _p.r(50);
        return _p.r(11).createClass("RegularPolygon", {
            base: _p.r(46),
            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;
            }
        });
    }
};

//src/graphic/resource.js
/**
 * @fileOverview
 *
 * 资源节点基类
 *
 * @author: techird
 * @copyright: Baidu FEX, 2014
 */
_p[58] = {
    value: function(require, exports, module) {
        var svg = _p.r(67);
        return _p.r(11).createClass("Resource", {
            constructor: function(nodeType, paper) {
                this.callBase();
                this.node = svg.createNode(nodeType);
                if (paper) {
                    paper.addResource(this);
                }
            },
            toString: function() {
                return "url(#" + this.node.id + ")";
            }
        });
    }
};

//src/graphic/ring.js
_p[59] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass({
            base: _p.r(68),
            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 ]);
            }
        });
    }
};

//src/graphic/shape.js
_p[60] = {
    value: function(require, exports, module) {
        var svg = _p.r(67);
        var utils = _p.r(12);
        var EventHandler = _p.r(33);
        var Styled = _p.r(66);
        var Data = _p.r(31);
        var Matrix = _p.r(43);
        var Pen = _p.r(48);
        var slice = Array.prototype.slice;
        var Box = _p.r(25);
        var Shape = _p.r(11).createClass("Shape", {
            mixins: [ EventHandler, Styled, Data ],
            constructor: function Shape(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 if (pen) {
                    // 字符串或重写了 toString 的对象
                    this.node.setAttribute("stroke", pen.toString());
                    if (width) {
                        this.node.setAttribute("stroke-width", width);
                    }
                } else if (pen === null) {
                    this.node.removeAttribute("stroe");
                }
                return this;
            },
            fill: function(brush) {
                // 字符串或重写了 toString 的对象
                if (brush) {
                    this.node.setAttribute("fill", brush.toString());
                }
                if (brush === null) {
                    this.node.removeAttribute("fill");
                }
                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);
                }
                return this;
            },
            getAttr: function(a) {
                return this.node.getAttribute(a);
            }
        });
        return Shape;
    }
};

//src/graphic/shapecontainer.js
_p[61] = {
    value: function(require, exports, module) {
        var Container = _p.r(29);
        var utils = _p.r(12);
        var ShapeContainer = _p.r(11).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);
            },
            put: function(shape) {
                this.addShape(shape);
                return shape;
            },
            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 = _p.r(60);
        _p.r(11).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;
    }
};

//src/graphic/shapeevent.js
/*
 * 图形事件包装类
 * */
_p[62] = {
    value: function(require, exprots, module) {
        var Matrix = _p.r(43), Utils = _p.r(12), Point = _p.r(50);
        return _p.r(11).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 target = this.targetShape;
                var targetNode = target.shapeNode || target.node;
                var pScreen = new Point(eventClient && eventClient.clientX || 0, eventClient && eventClient.clientY || 0);
                var pTarget = Matrix.transformPoint(pScreen, targetNode.getScreenCTM().inverse());
                var pRefer = Matrix.getCTM(target, refer || "view").transformPoint(pTarget);
                return pRefer;
            },
            stopPropagation: function() {
                var evt = this.originEvent;
                if (!evt) {
                    return true;
                }
                if (evt.stopPropagation) {
                    evt.stopPropagation();
                } else {
                    evt.cancelBubble = false;
                }
            }
        });
    }
};

//src/graphic/shapepoint.js
/*
 * 图形上的点抽象
 */
_p[63] = {
    value: function(require, exports, module) {
        return _p.r(11).createClass("ShapePoint", {
            base: _p.r(50),
            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;
            }
        });
    }
};

//src/graphic/standardcolor.js
/**
 * 标准颜色映射
 */
_p[64] = {
    value: {
        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: {}
    }
};

//src/graphic/star.js
_p[65] = {
    value: 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 = _p.r(50);
        return _p.r(11).createClass("Star", {
            base: _p.r(46),
            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();
            }
        });
    }
};

//src/graphic/styled.js
_p[66] = {
    value: function(require, exports, module) {
        // polyfill for ie
        var ClassList = _p.r(11).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 _p.r(11).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;
            }
        });
    }
};

//src/graphic/svg.js
_p[67] = {
    value: 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;
    }
};

//src/graphic/sweep.js
_p[68] = {
    value: function(require, exports, module) {
        var Point = _p.r(50);
        return _p.r(11).createClass("Sweep", {
            base: _p.r(46),
            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, sweepFlag = angleLength < 0 ? 0 : 1, 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, sweepFlag, Point.fromPolar(to, angleHalf));
                    drawer.carcTo(to, 0, sweepFlag, Point.fromPolar(to, angleEnd));
                }
                drawer.lineTo(Point.fromPolar(from, angleEnd));
                if (from) {
                    drawer.carcTo(from, 0, sweepFlag, Point.fromPolar(from, angleHalf));
                    drawer.carcTo(from, 0, sweepFlag, Point.fromPolar(from, angleStart));
                }
                drawer.close();
                drawer.done();
            }
        });
    }
};

//src/graphic/text.js
_p[69] = {
    value: function(require, exports, module) {
        var TextContent = _p.r(70);
        var ShapeContainer = _p.r(61);
        var svg = _p.r(67);
        var utils = _p.r(12);
        var offsetHash = {};
        function getTextBoundOffset(text) {
            var font = text._cachedFontHash;
            if (offsetHash[font]) {
                return offsetHash[font];
            }
            var textContent = text.getContent();
            text.setContent("百度Fex");
            var bbox = text.getBoundaryBox(), y = text.getY();
            if (!bbox.height) return {
                top: 0,
                bottom: 0,
                middle: 0
            };
            var topOffset = y - bbox.y + +text.node.getAttribute("dy"), bottomOffset = topOffset - bbox.height;
            text.setContent(textContent);
            return offsetHash[font] = {
                top: topOffset,
                bottom: bottomOffset,
                middle: (topOffset + bottomOffset) / 2
            };
        }
        return _p.r(11).createClass("Text", {
            base: TextContent,
            mixins: [ ShapeContainer ],
            constructor: function(content) {
                this.callBase("text");
                if (content !== undefined) {
                    this.setContent(content);
                }
                this._buildFontHash();
            },
            fixPosition: function() {
                if (!this.__fixedPosition) {
                    this.setVerticalAlign(this.getVerticalAlign());
                }
            },
            _buildFontHash: function() {
                var style = window.getComputedStyle(this.node);
                this._cachedFontHash = [ style.fontFamily, style.fontSize, style.fontStretch, style.fontStyle, style.fontVariant, style.fontWeight ].join("-");
            },
            _fontChanged: function(font) {
                var last = this._lastFont;
                var current = utils.extend({}, last, font);
                if (!last) {
                    this._lastFont = font;
                    return true;
                }
                var changed = last.family != current.family || last.size != current.size || last.style != current.style || last.weight != current.weight;
                this._lastFont = current;
                return changed;
            },
            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);
                if (this._fontChanged(font)) {
                    this._buildFontHash();
                    this.setVerticalAlign(this.getVerticalAlign());
                }
                return this;
            },
            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;
                    }
                    if (dy) this.__fixedPosition = true;
                    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;
            }
        });
    }
};

//src/graphic/textcontent.js
_p[70] = {
    value: function(require, exports, module) {
        var Shape = _p.r(60);
        return _p.r(11).createClass("TextContent", {
            base: Shape,
            constructor: function(nodeType) {
                // call shape constructor
                this.callBase(nodeType);
                this.shapeNode = this.shapeNode || this.node;
                this.shapeNode.setAttribute("text-rendering", "geometricPrecision");
            },
            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));
            }
        });
    }
};

//src/graphic/textspan.js
_p[71] = {
    value: function(require, exports, module) {
        var TextContent = _p.r(70);
        var Styled = _p.r(66);
        return _p.r(11).createClass("TextSpan", {
            base: TextContent,
            mixins: [ Styled ],
            constructor: function(content) {
                this.callBase("tspan");
                this.setContent(content);
            }
        });
    }
};

//src/graphic/use.js
/*
 * USE 功能
 */
_p[72] = {
    value: function(require, exports, module) {
        var Svg = _p.r(67);
        var Class = _p.r(11);
        var Use = Class.createClass("Use", {
            base: _p.r(60),
            constructor: function(shape) {
                this.callBase("use");
                this.ref(shape);
            },
            ref: function(shape) {
                if (!shape) {
                    this.node.removeAttributeNS(Svg.xlink, "xlink:href");
                    return this;
                }
                var 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");
                }
                return this;
            }
        });
        var Shape = _p.r(60);
        Class.extendClass(Shape, {
            // fast-use
            use: function() {
                return new Use(this);
            }
        });
        return Use;
    }
};

//src/graphic/vector.js
_p[73] = {
    value: function(require, exports, module) {
        var Point = _p.r(50);
        var Matrix = _p.r(43);
        var Vector = _p.r(11).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);
        };
        Vector.fromPolar = function() {
            var p = Point.fromPolar.apply(Point, arguments);
            return new Vector(p.x, p.y);
        };
        _p.r(11).extendClass(Point, {
            asVector: function() {
                return new Vector(this.x, this.y);
            }
        });
        return Vector;
    }
};

//src/graphic/view.js
_p[74] = {
    value: function(require, exports, module) {
        var ShapeContainer = _p.r(61);
        var ViewBox = _p.r(75);
        return _p.r(11).createClass("View", {
            mixins: [ ShapeContainer, ViewBox ],
            base: _p.r(74),
            constructor: function() {
                this.callBase("view");
            }
        });
    }
};

//src/graphic/viewbox.js
_p[75] = {
    value: function(require, exports, module) {
        return _p.r(11).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;
            }
        });
    }
};

//src/kity.js
/**
 * @fileOverview kity 暴露的方法或对象
 */
_p[76] = {
    value: function(require, exports, module) {
        var kity = {}, utils = _p.r(12);
        kity.version = "2.0.0";
        utils.extend(kity, {
            // core
            createClass: _p.r(11).createClass,
            extendClass: _p.r(11).extendClass,
            Utils: utils,
            Browser: _p.r(10),
            // shape
            Box: _p.r(25),
            Bezier: _p.r(23),
            BezierPoint: _p.r(24),
            Circle: _p.r(26),
            Clip: _p.r(27),
            Color: _p.r(28),
            Container: _p.r(29),
            Curve: _p.r(30),
            Ellipse: _p.r(32),
            Group: _p.r(36),
            Gradient: _p.r(35),
            HyperLink: _p.r(37),
            Image: _p.r(38),
            Line: _p.r(39),
            LinearGradient: _p.r(40),
            Mask: _p.r(42),
            Matrix: _p.r(43),
            Marker: _p.r(41),
            Palette: _p.r(44),
            Paper: _p.r(45),
            Path: _p.r(46),
            Pattern: _p.r(47),
            Pen: _p.r(48),
            Point: _p.r(50),
            PointContainer: _p.r(51),
            Polygon: _p.r(53),
            Polyline: _p.r(54),
            Pie: _p.r(49),
            RadialGradient: _p.r(55),
            Resource: _p.r(58),
            Rect: _p.r(56),
            RegularPolygon: _p.r(57),
            Ring: _p.r(59),
            Shape: _p.r(60),
            ShapePoint: _p.r(63),
            ShapeContainer: _p.r(61),
            Sweep: _p.r(68),
            Star: _p.r(65),
            Text: _p.r(69),
            TextSpan: _p.r(71),
            Use: _p.r(72),
            Vector: _p.r(73),
            g: _p.r(34),
            // animate
            Animator: _p.r(0),
            Easing: _p.r(1),
            OpacityAnimator: _p.r(4),
            RotateAnimator: _p.r(6),
            ScaleAnimator: _p.r(7),
            Timeline: _p.r(8),
            TranslateAnimator: _p.r(9),
            PathAnimator: _p.r(5),
            MotionAnimator: _p.r(3),
            requestFrame: _p.r(2).requestFrame,
            releaseFrame: _p.r(2).releaseFrame,
            // filter
            Filter: _p.r(20),
            GaussianblurFilter: _p.r(21),
            ProjectionFilter: _p.r(22),
            // effect
            ColorMatrixEffect: _p.r(13),
            CompositeEffect: _p.r(14),
            ConvolveMatrixEffect: _p.r(15),
            Effect: _p.r(16),
            GaussianblurEffect: _p.r(17),
            OffsetEffect: _p.r(18)
        });
        return window.kity = kity;
    }
};

var moduleMapping = {
    kity: 76
};

function use(name) {
    _p.r([ moduleMapping[name] ]);
}
/* global use, inc: true */

/**
 * 模块暴露
 */
use('kity');
})();