| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240 | 
							- <!DOCTYPE html>
 
- <html>
 
- <head>
 
-   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
-   <title>The source code</title>
 
-   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
 
-   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
 
-   <style type="text/css">
 
-     .highlight { display: block; background-color: #ddd; }
 
-   </style>
 
-   <script type="text/javascript">
 
-     function highlight() {
 
-       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
 
-     }
 
-   </script>
 
- </head>
 
- <body onload="prettyPrint(); highlight();">
 
-   <pre class="prettyprint lang-js"><span id='Ext-draw-Draw'>/**
 
- </span> * @class Ext.draw.Draw
 
-  * Base Drawing class.  Provides base drawing functions.
 
-  * @private
 
-  */
 
- Ext.define('Ext.draw.Draw', {
 
-     /* Begin Definitions */
 
-     singleton: true,
 
-     requires: ['Ext.draw.Color'],
 
-     /* End Definitions */
 
-     pathToStringRE: /,?([achlmqrstvxz]),?/gi,
 
-     pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
 
-     pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
 
-     stopsRE: /^(\d+%?)$/,
 
-     radian: Math.PI / 180,
 
-     availableAnimAttrs: {
 
-         along: "along",
 
-         blur: null,
 
-         "clip-rect": "csv",
 
-         cx: null,
 
-         cy: null,
 
-         fill: "color",
 
-         "fill-opacity": null,
 
-         "font-size": null,
 
-         height: null,
 
-         opacity: null,
 
-         path: "path",
 
-         r: null,
 
-         rotation: "csv",
 
-         rx: null,
 
-         ry: null,
 
-         scale: "csv",
 
-         stroke: "color",
 
-         "stroke-opacity": null,
 
-         "stroke-width": null,
 
-         translation: "csv",
 
-         width: null,
 
-         x: null,
 
-         y: null
 
-     },
 
-     is: function(o, type) {
 
-         type = String(type).toLowerCase();
 
-         return (type == "object" && o === Object(o)) ||
 
-             (type == "undefined" && typeof o == type) ||
 
-             (type == "null" && o === null) ||
 
-             (type == "array" && Array.isArray && Array.isArray(o)) ||
 
-             (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type;
 
-     },
 
-     ellipsePath: function(sprite) {
 
-         var attr = sprite.attr;
 
-         return Ext.String.format("M{0},{1}A{2},{3},0,1,1,{0},{4}A{2},{3},0,1,1,{0},{1}z", attr.x, attr.y - attr.ry, attr.rx, attr.ry, attr.y + attr.ry);
 
-     },
 
-     rectPath: function(sprite) {
 
-         var attr = sprite.attr;
 
-         if (attr.radius) {
 
-             return Ext.String.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", attr.x + attr.radius, attr.y, attr.width - attr.radius * 2, attr.radius, -attr.radius, attr.height - attr.radius * 2, attr.radius * 2 - attr.width, attr.radius * 2 - attr.height);
 
-         }
 
-         else {
 
-             return Ext.String.format("M{0},{1}L{2},{1},{2},{3},{0},{3}z", attr.x, attr.y, attr.width + attr.x, attr.height + attr.y);
 
-         }
 
-     },
 
-     // To be deprecated, converts itself (an arrayPath) to a proper SVG path string
 
-     path2string: function () {
 
-         return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
 
-     },
 
-     // Convert the passed arrayPath to a proper SVG path string (d attribute)
 
-     pathToString: function(arrayPath) {
 
-         return arrayPath.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
 
-     },
 
-     parsePathString: function (pathString) {
 
-         if (!pathString) {
 
-             return null;
 
-         }
 
-         var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
 
-             data = [],
 
-             me = this;
 
-         if (me.is(pathString, "array") && me.is(pathString[0], "array")) { // rough assumption
 
-             data = me.pathClone(pathString);
 
-         }
 
-         if (!data.length) {
 
-             String(pathString).replace(me.pathCommandRE, function (a, b, c) {
 
-                 var params = [],
 
-                     name = b.toLowerCase();
 
-                 c.replace(me.pathValuesRE, function (a, b) {
 
-                     b && params.push(+b);
 
-                 });
 
-                 if (name == "m" && params.length > 2) {
 
-                     data.push([b].concat(Ext.Array.splice(params, 0, 2)));
 
-                     name = "l";
 
-                     b = (b == "m") ? "l" : "L";
 
-                 }
 
-                 while (params.length >= paramCounts[name]) {
 
-                     data.push([b].concat(Ext.Array.splice(params, 0, paramCounts[name])));
 
-                     if (!paramCounts[name]) {
 
-                         break;
 
-                     }
 
-                 }
 
-             });
 
-         }
 
-         data.toString = me.path2string;
 
-         return data;
 
-     },
 
-     mapPath: function (path, matrix) {
 
-         if (!matrix) {
 
-             return path;
 
-         }
 
-         var x, y, i, ii, j, jj, pathi;
 
-         path = this.path2curve(path);
 
-         for (i = 0, ii = path.length; i < ii; i++) {
 
-             pathi = path[i];
 
-             for (j = 1, jj = pathi.length; j < jj-1; j += 2) {
 
-                 x = matrix.x(pathi[j], pathi[j + 1]);
 
-                 y = matrix.y(pathi[j], pathi[j + 1]);
 
-                 pathi[j] = x;
 
-                 pathi[j + 1] = y;
 
-             }
 
-         }
 
-         return path;
 
-     },
 
-     pathClone: function(pathArray) {
 
-         var res = [],
 
-             j, jj, i, ii;
 
-         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { // rough assumption
 
-             pathArray = this.parsePathString(pathArray);
 
-         }
 
-         for (i = 0, ii = pathArray.length; i < ii; i++) {
 
-             res[i] = [];
 
-             for (j = 0, jj = pathArray[i].length; j < jj; j++) {
 
-                 res[i][j] = pathArray[i][j];
 
-             }
 
-         }
 
-         res.toString = this.path2string;
 
-         return res;
 
-     },
 
-     pathToAbsolute: function (pathArray) {
 
-         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { // rough assumption
 
-             pathArray = this.parsePathString(pathArray);
 
-         }
 
-         var res = [],
 
-             x = 0,
 
-             y = 0,
 
-             mx = 0,
 
-             my = 0,
 
-             i = 0,
 
-             ln = pathArray.length,
 
-             r, pathSegment, j, ln2;
 
-         // MoveTo initial x/y position
 
-         if (ln && pathArray[0][0] == "M") {
 
-             x = +pathArray[0][1];
 
-             y = +pathArray[0][2];
 
-             mx = x;
 
-             my = y;
 
-             i++;
 
-             res[0] = ["M", x, y];
 
-         }
 
-         for (; i < ln; i++) {
 
-             r = res[i] = [];
 
-             pathSegment = pathArray[i];
 
-             if (pathSegment[0] != pathSegment[0].toUpperCase()) {
 
-                 r[0] = pathSegment[0].toUpperCase();
 
-                 switch (r[0]) {
 
-                     // Elliptical Arc
 
-                     case "A":
 
-                         r[1] = pathSegment[1];
 
-                         r[2] = pathSegment[2];
 
-                         r[3] = pathSegment[3];
 
-                         r[4] = pathSegment[4];
 
-                         r[5] = pathSegment[5];
 
-                         r[6] = +(pathSegment[6] + x);
 
-                         r[7] = +(pathSegment[7] + y);
 
-                         break;
 
-                     // Vertical LineTo
 
-                     case "V":
 
-                         r[1] = +pathSegment[1] + y;
 
-                         break;
 
-                     // Horizontal LineTo
 
-                     case "H":
 
-                         r[1] = +pathSegment[1] + x;
 
-                         break;
 
-                     case "M":
 
-                     // MoveTo
 
-                         mx = +pathSegment[1] + x;
 
-                         my = +pathSegment[2] + y;
 
-                     default:
 
-                         j = 1;
 
-                         ln2 = pathSegment.length;
 
-                         for (; j < ln2; j++) {
 
-                             r[j] = +pathSegment[j] + ((j % 2) ? x : y);
 
-                         }
 
-                 }
 
-             }
 
-             else {
 
-                 j = 0;
 
-                 ln2 = pathSegment.length;
 
-                 for (; j < ln2; j++) {
 
-                     res[i][j] = pathSegment[j];
 
-                 }
 
-             }
 
-             switch (r[0]) {
 
-                 // ClosePath
 
-                 case "Z":
 
-                     x = mx;
 
-                     y = my;
 
-                     break;
 
-                 // Horizontal LineTo
 
-                 case "H":
 
-                     x = r[1];
 
-                     break;
 
-                 // Vertical LineTo
 
-                 case "V":
 
-                     y = r[1];
 
-                     break;
 
-                 // MoveTo
 
-                 case "M":
 
-                     pathSegment = res[i];
 
-                     ln2 = pathSegment.length;
 
-                     mx = pathSegment[ln2 - 2];
 
-                     my = pathSegment[ln2 - 1];
 
-                 default:
 
-                     pathSegment = res[i];
 
-                     ln2 = pathSegment.length;
 
-                     x = pathSegment[ln2 - 2];
 
-                     y = pathSegment[ln2 - 1];
 
-             }
 
-         }
 
-         res.toString = this.path2string;
 
-         return res;
 
-     },
 
-     // TO BE DEPRECATED
 
-     pathToRelative: function (pathArray) {
 
-         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) {
 
-             pathArray = this.parsePathString(pathArray);
 
-         }
 
-         var res = [],
 
-             x = 0,
 
-             y = 0,
 
-             mx = 0,
 
-             my = 0,
 
-             start = 0,
 
-             r,
 
-             pa,
 
-             i,
 
-             j,
 
-             k,
 
-             len,
 
-             ii,
 
-             jj,
 
-             kk;
 
-         
 
-         if (pathArray[0][0] == "M") {
 
-             x = pathArray[0][1];
 
-             y = pathArray[0][2];
 
-             mx = x;
 
-             my = y;
 
-             start++;
 
-             res.push(["M", x, y]);
 
-         }
 
-         for (i = start, ii = pathArray.length; i < ii; i++) {
 
-             r = res[i] = [];
 
-             pa = pathArray[i];
 
-             if (pa[0] != pa[0].toLowerCase()) {
 
-                 r[0] = pa[0].toLowerCase();
 
-                 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).toFixed(3);
 
-                         r[7] = +(pa[7] - y).toFixed(3);
 
-                         break;
 
-                     case "v":
 
-                         r[1] = +(pa[1] - y).toFixed(3);
 
-                         break;
 
-                     case "m":
 
-                         mx = pa[1];
 
-                         my = pa[2];
 
-                     default:
 
-                         for (j = 1, jj = pa.length; j < jj; j++) {
 
-                             r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
 
-                         }
 
-                 }
 
-             } else {
 
-                 r = res[i] = [];
 
-                 if (pa[0] == "m") {
 
-                     mx = pa[1] + x;
 
-                     my = pa[2] + y;
 
-                 }
 
-                 for (k = 0, kk = pa.length; k < kk; k++) {
 
-                     res[i][k] = pa[k];
 
-                 }
 
-             }
 
-             len = res[i].length;
 
-             switch (res[i][0]) {
 
-                 case "z":
 
-                     x = mx;
 
-                     y = my;
 
-                     break;
 
-                 case "h":
 
-                     x += +res[i][len - 1];
 
-                     break;
 
-                 case "v":
 
-                     y += +res[i][len - 1];
 
-                     break;
 
-                 default:
 
-                     x += +res[i][len - 2];
 
-                     y += +res[i][len - 1];
 
-             }
 
-         }
 
-         res.toString = this.path2string;
 
-         return res;
 
-     },
 
-     // Returns a path converted to a set of curveto commands
 
-     path2curve: function (path) {
 
-         var me = this,
 
-             points = me.pathToAbsolute(path),
 
-             ln = points.length,
 
-             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
 
-             i, seg, segLn, point;
 
-             
 
-         for (i = 0; i < ln; i++) {
 
-             points[i] = me.command2curve(points[i], attrs);
 
-             if (points[i].length > 7) {
 
-                     points[i].shift();
 
-                     point = points[i];
 
-                     while (point.length) {
 
-                         Ext.Array.splice(points, i++, 0, ["C"].concat(Ext.Array.splice(point, 0, 6)));
 
-                     }
 
-                     Ext.Array.erase(points, i, 1);
 
-                     ln = points.length;
 
-                     i--;
 
-                 }
 
-             seg = points[i];
 
-             segLn = seg.length;
 
-             attrs.x = seg[segLn - 2];
 
-             attrs.y = seg[segLn - 1];
 
-             attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x;
 
-             attrs.by = parseFloat(seg[segLn - 3]) || attrs.y;
 
-         }
 
-         return points;
 
-     },
 
-     
 
-     interpolatePaths: function (path, path2) {
 
-         var me = this,
 
-             p = me.pathToAbsolute(path),
 
-             p2 = me.pathToAbsolute(path2),
 
-             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
 
-             attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
 
-             fixArc = function (pp, i) {
 
-                 if (pp[i].length > 7) {
 
-                     pp[i].shift();
 
-                     var pi = pp[i];
 
-                     while (pi.length) {
 
-                         Ext.Array.splice(pp, i++, 0, ["C"].concat(Ext.Array.splice(pi, 0, 6)));
 
-                     }
 
-                     Ext.Array.erase(pp, i, 1);
 
-                     ii = Math.max(p.length, p2.length || 0);
 
-                 }
 
-             },
 
-             fixM = function (path1, path2, a1, a2, i) {
 
-                 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
 
-                     Ext.Array.splice(path2, i, 0, ["M", a2.x, a2.y]);
 
-                     a1.bx = 0;
 
-                     a1.by = 0;
 
-                     a1.x = path1[i][1];
 
-                     a1.y = path1[i][2];
 
-                     ii = Math.max(p.length, p2.length || 0);
 
-                 }
 
-             },
 
-             i, ii,
 
-             seg, seg2, seglen, seg2len;
 
-         for (i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) {
 
-             p[i] = me.command2curve(p[i], attrs);
 
-             fixArc(p, i);
 
-             (p2[i] = me.command2curve(p2[i], attrs2));
 
-             fixArc(p2, i);
 
-             fixM(p, p2, attrs, attrs2, i);
 
-             fixM(p2, p, attrs2, attrs, i);
 
-             seg = p[i];
 
-             seg2 = p2[i];
 
-             seglen = seg.length;
 
-             seg2len = seg2.length;
 
-             attrs.x = seg[seglen - 2];
 
-             attrs.y = seg[seglen - 1];
 
-             attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
 
-             attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
 
-             attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x);
 
-             attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y);
 
-             attrs2.x = seg2[seg2len - 2];
 
-             attrs2.y = seg2[seg2len - 1];
 
-         }
 
-         return [p, p2];
 
-     },
 
-     
 
-     //Returns any path command as a curveto command based on the attrs passed
 
-     command2curve: function (pathCommand, d) {
 
-         var me = this;
 
-         if (!pathCommand) {
 
-             return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
 
-         }
 
-         if (pathCommand[0] != "T" && pathCommand[0] != "Q") {
 
-             d.qx = d.qy = null;
 
-         }
 
-         switch (pathCommand[0]) {
 
-             case "M":
 
-                 d.X = pathCommand[1];
 
-                 d.Y = pathCommand[2];
 
-                 break;
 
-             case "A":
 
-                 pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1))));
 
-                 break;
 
-             case "S":
 
-                 pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1));
 
-                 break;
 
-             case "T":
 
-                 d.qx = d.x + (d.x - (d.qx || d.x));
 
-                 d.qy = d.y + (d.y - (d.qy || d.y));
 
-                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2]));
 
-                 break;
 
-             case "Q":
 
-                 d.qx = pathCommand[1];
 
-                 d.qy = pathCommand[2];
 
-                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4]));
 
-                 break;
 
-             case "L":
 
-                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]);
 
-                 break;
 
-             case "H":
 
-                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y);
 
-                 break;
 
-             case "V":
 
-                 pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]);
 
-                 break;
 
-             case "Z":
 
-                 pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y);
 
-                 break;
 
-         }
 
-         return pathCommand;
 
-     },
 
-     quadratic2curve: function (x1, y1, ax, ay, x2, y2) {
 
-         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
 
-             ];
 
-     },
 
-     
 
-     rotate: function (x, y, rad) {
 
-         var cos = Math.cos(rad),
 
-             sin = Math.sin(rad),
 
-             X = x * cos - y * sin,
 
-             Y = x * sin + y * cos;
 
-         return {x: X, y: Y};
 
-     },
 
-     arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
 
-         // for more information of where this Math came from visit:
 
-         // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
 
-         var me = this,
 
-             PI = Math.PI,
 
-             radian = me.radian,
 
-             _120 = PI * 120 / 180,
 
-             rad = radian * (+angle || 0),
 
-             res = [],
 
-             math = Math,
 
-             mcos = math.cos,
 
-             msin = math.sin,
 
-             msqrt = math.sqrt,
 
-             mabs = math.abs,
 
-             masin = math.asin,
 
-             xy, cos, sin, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2,
 
-             t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old;
 
-         if (!recursive) {
 
-             xy = me.rotate(x1, y1, -rad);
 
-             x1 = xy.x;
 
-             y1 = xy.y;
 
-             xy = me.rotate(x2, y2, -rad);
 
-             x2 = xy.x;
 
-             y2 = xy.y;
 
-             cos = mcos(radian * angle);
 
-             sin = msin(radian * angle);
 
-             x = (x1 - x2) / 2;
 
-             y = (y1 - y2) / 2;
 
-             h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
 
-             if (h > 1) {
 
-                 h = msqrt(h);
 
-                 rx = h * rx;
 
-                 ry = h * ry;
 
-             }
 
-             rx2 = rx * rx;
 
-             ry2 = ry * ry;
 
-             k = (large_arc_flag == sweep_flag ? -1 : 1) *
 
-                     msqrt(mabs((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 = masin(((y1 - cy) / ry).toFixed(7));
 
-             f2 = masin(((y2 - cy) / ry).toFixed(7));
 
-             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 (sweep_flag && f1 > f2) {
 
-                 f1 = f1 - PI * 2;
 
-             }
 
-             if (!sweep_flag && f2 > f1) {
 
-                 f2 = f2 - PI * 2;
 
-             }
 
-         }
 
-         else {
 
-             f1 = recursive[0];
 
-             f2 = recursive[1];
 
-             cx = recursive[2];
 
-             cy = recursive[3];
 
-         }
 
-         df = f2 - f1;
 
-         if (mabs(df) > _120) {
 
-             f2old = f2;
 
-             x2old = x2;
 
-             y2old = y2;
 
-             f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
 
-             x2 = cx + rx * mcos(f2);
 
-             y2 = cy + ry * msin(f2);
 
-             res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
 
-         }
 
-         df = f2 - f1;
 
-         c1 = mcos(f1);
 
-         s1 = msin(f1);
 
-         c2 = mcos(f2);
 
-         s2 = msin(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 = [];
 
-             ln = res.length;
 
-             for (i = 0;  i < ln; i++) {
 
-                 newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x;
 
-             }
 
-             return newres;
 
-         }
 
-     },
 
-     // TO BE DEPRECATED
 
-     rotateAndTranslatePath: function (sprite) {
 
-         var alpha = sprite.rotation.degrees,
 
-             cx = sprite.rotation.x,
 
-             cy = sprite.rotation.y,
 
-             dx = sprite.translation.x,
 
-             dy = sprite.translation.y,
 
-             path,
 
-             i,
 
-             p,
 
-             xy,
 
-             j,
 
-             res = [];
 
-         if (!alpha && !dx && !dy) {
 
-             return this.pathToAbsolute(sprite.attr.path);
 
-         }
 
-         dx = dx || 0;
 
-         dy = dy || 0;
 
-         path = this.pathToAbsolute(sprite.attr.path);
 
-         for (i = path.length; i--;) {
 
-             p = res[i] = path[i].slice();
 
-             if (p[0] == "A") {
 
-                 xy = this.rotatePoint(p[6], p[7], alpha, cx, cy);
 
-                 p[6] = xy.x + dx;
 
-                 p[7] = xy.y + dy;
 
-             } else {
 
-                 j = 1;
 
-                 while (p[j + 1] != null) {
 
-                     xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy);
 
-                     p[j] = xy.x + dx;
 
-                     p[j + 1] = xy.y + dy;
 
-                     j += 2;
 
-                 }
 
-             }
 
-         }
 
-         return res;
 
-     },
 
-     // TO BE DEPRECATED
 
-     rotatePoint: function (x, y, alpha, cx, cy) {
 
-         if (!alpha) {
 
-             return {
 
-                 x: x,
 
-                 y: y
 
-             };
 
-         }
 
-         cx = cx || 0;
 
-         cy = cy || 0;
 
-         x = x - cx;
 
-         y = y - cy;
 
-         alpha = alpha * this.radian;
 
-         var cos = Math.cos(alpha),
 
-             sin = Math.sin(alpha);
 
-         return {
 
-             x: x * cos - y * sin + cx,
 
-             y: x * sin + y * cos + cy
 
-         };
 
-     },
 
-     pathDimensions: function (path) {
 
-         if (!path || !(path + "")) {
 
-             return {x: 0, y: 0, width: 0, height: 0};
 
-         }
 
-         path = this.path2curve(path);
 
-         var x = 0, 
 
-             y = 0,
 
-             X = [],
 
-             Y = [],
 
-             i = 0,
 
-             ln = path.length,
 
-             p, xmin, ymin, dim;
 
-         for (; i < ln; i++) {
 
-             p = path[i];
 
-             if (p[0] == "M") {
 
-                 x = p[1];
 
-                 y = p[2];
 
-                 X.push(x);
 
-                 Y.push(y);
 
-             }
 
-             else {
 
-                 dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
 
-                 X = X.concat(dim.min.x, dim.max.x);
 
-                 Y = Y.concat(dim.min.y, dim.max.y);
 
-                 x = p[5];
 
-                 y = p[6];
 
-             }
 
-         }
 
-         xmin = Math.min.apply(0, X);
 
-         ymin = Math.min.apply(0, Y);
 
-         return {
 
-             x: xmin,
 
-             y: ymin,
 
-             path: path,
 
-             width: Math.max.apply(0, X) - xmin,
 
-             height: Math.max.apply(0, Y) - ymin
 
-         };
 
-     },
 
-     intersectInside: function(path, cp1, cp2) {
 
-         return (cp2[0] - cp1[0]) * (path[1] - cp1[1]) > (cp2[1] - cp1[1]) * (path[0] - cp1[0]);
 
-     },
 
-     intersectIntersection: function(s, e, cp1, cp2) {
 
-         var p = [],
 
-             dcx = cp1[0] - cp2[0],
 
-             dcy = cp1[1] - cp2[1],
 
-             dpx = s[0] - e[0],
 
-             dpy = s[1] - e[1],
 
-             n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0],
 
-             n2 = s[0] * e[1] - s[1] * e[0],
 
-             n3 = 1 / (dcx * dpy - dcy * dpx);
 
-         p[0] = (n1 * dpx - n2 * dcx) * n3;
 
-         p[1] = (n1 * dpy - n2 * dcy) * n3;
 
-         return p;
 
-     },
 
-     intersect: function(subjectPolygon, clipPolygon) {
 
-         var me = this,
 
-             i = 0,
 
-             ln = clipPolygon.length,
 
-             cp1 = clipPolygon[ln - 1],
 
-             outputList = subjectPolygon,
 
-             cp2, s, e, point, ln2, inputList, j;
 
-         for (; i < ln; ++i) {
 
-             cp2 = clipPolygon[i];
 
-             inputList = outputList;
 
-             outputList = [];
 
-             s = inputList[inputList.length - 1];
 
-             j = 0;
 
-             ln2 = inputList.length;
 
-             for (; j < ln2; j++) {
 
-                 e = inputList[j];
 
-                 if (me.intersectInside(e, cp1, cp2)) {
 
-                     if (!me.intersectInside(s, cp1, cp2)) {
 
-                         outputList.push(me.intersectIntersection(s, e, cp1, cp2));
 
-                     }
 
-                     outputList.push(e);
 
-                 }
 
-                 else if (me.intersectInside(s, cp1, cp2)) {
 
-                     outputList.push(me.intersectIntersection(s, e, cp1, cp2));
 
-                 }
 
-                 s = e;
 
-             }
 
-             cp1 = cp2;
 
-         }
 
-         return outputList;
 
-     },
 
-     
 
-     bezier : function (a, b, c, d, x) {
 
-         if (x === 0) {
 
-             return a;
 
-         } 
 
-         else if (x === 1) {
 
-             return d;
 
-         }
 
-         var du = 1 - x,
 
-             d3 = du * du * du,
 
-             r = x / du;
 
-         return d3 * (a + r * (3 * b + r * (3 * c + d * r)));
 
-     },
 
-     
 
-     bezierDim : function (a, b, c, d) {
 
-         var points = [], r,
 
-             A, top, C, delta, bottom, s,
 
-             min, max, i;
 
-         // The min and max happens on boundary or b' == 0
 
-         if (a + 3 * c == d + 3 * b) {   
 
-             r = a - b;
 
-             r /= 2 * (a - b - b + c);
 
-             if ( r < 1 && r > 0) {
 
-                 points.push(r);
 
-             }
 
-         } else {
 
-             // b'(x) / -3 = (a-3b+3c-d)x^2+ (-2a+4b-2c)x + (a-b)
 
-             // delta = -4 (-b^2+a c+b c-c^2-a d+b d)
 
-             A = a - 3 * b + 3 * c - d;
 
-             top = 2 * (a - b - b + c);
 
-             C = a - b;
 
-             delta = top * top - 4 * A * C;
 
-             bottom = A + A;
 
-             if (delta === 0) {
 
-                 r = top / bottom;
 
-                 if (r < 1 && r > 0) {
 
-                     points.push(r);
 
-                 }
 
-             } else if (delta > 0) {
 
-                 s = Math.sqrt(delta);
 
-                 r = (s + top) / bottom;
 
-                 
 
-                 if (r < 1 && r > 0) {
 
-                     points.push(r);
 
-                 }
 
-                 
 
-                 r = (top - s) / bottom;
 
-                 
 
-                 if (r < 1 && r > 0) {
 
-                     points.push(r);
 
-                 }
 
-             }
 
-         }
 
-         min = Math.min(a, d);
 
-         max = Math.max(a, d);
 
-         for (i = 0; i < points.length; i++) {
 
-             min = Math.min(min, this.bezier(a, b, c, d, points[i]));
 
-             max = Math.max(max, this.bezier(a, b, c, d, points[i]));
 
-         }
 
-         return [min, max];
 
-     },
 
-     
 
-     curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
 
-         var x = this.bezierDim(p1x, c1x, c2x, p2x),
 
-             y = this.bezierDim(p1y, c1y, c2y, p2y);
 
-         return {
 
-             min: {
 
-                 x: x[0],
 
-                 y: y[0]
 
-             },
 
-             max: {
 
-                 x: x[1],
 
-                 y: y[1]
 
-             }
 
-         };
 
-     },
 
- <span id='Ext-draw-Draw-method-getAnchors'>    /**
 
- </span>     * @private
 
-      *
 
-      * Calculates bezier curve control anchor points for a particular point in a path, with a
 
-      * smoothing curve applied. The smoothness of the curve is controlled by the 'value' parameter.
 
-      * Note that this algorithm assumes that the line being smoothed is normalized going from left
 
-      * to right; it makes special adjustments assuming this orientation.
 
-      *
 
-      * @param {Number} prevX X coordinate of the previous point in the path
 
-      * @param {Number} prevY Y coordinate of the previous point in the path
 
-      * @param {Number} curX X coordinate of the current point in the path
 
-      * @param {Number} curY Y coordinate of the current point in the path
 
-      * @param {Number} nextX X coordinate of the next point in the path
 
-      * @param {Number} nextY Y coordinate of the next point in the path
 
-      * @param {Number} value A value to control the smoothness of the curve; this is used to
 
-      *                 divide the distance between points, so a value of 2 corresponds to
 
-      *                 half the distance between points (a very smooth line) while higher values
 
-      *                 result in less smooth curves. Defaults to 4.
 
-      * @return {Object} Object containing x1, y1, x2, y2 bezier control anchor points; x1 and y1
 
-      *                  are the control point for the curve toward the previous path point, and
 
-      *                  x2 and y2 are the control point for the curve toward the next path point.
 
-      */
 
-     getAnchors: function (prevX, prevY, curX, curY, nextX, nextY, value) {
 
-         value = value || 4;
 
-         var M = Math,
 
-             PI = M.PI,
 
-             halfPI = PI / 2,
 
-             abs = M.abs,
 
-             sin = M.sin,
 
-             cos = M.cos,
 
-             atan = M.atan,
 
-             control1Length, control2Length, control1Angle, control2Angle,
 
-             control1X, control1Y, control2X, control2Y, alpha;
 
-         // Find the length of each control anchor line, by dividing the horizontal distance
 
-         // between points by the value parameter.
 
-         control1Length = (curX - prevX) / value;
 
-         control2Length = (nextX - curX) / value;
 
-         // Determine the angle of each control anchor line. If the middle point is a vertical
 
-         // turnaround then we force it to a flat horizontal angle to prevent the curve from
 
-         // dipping above or below the middle point. Otherwise we use an angle that points
 
-         // toward the previous/next target point.
 
-         if ((curY >= prevY && curY >= nextY) || (curY <= prevY && curY <= nextY)) {
 
-             control1Angle = control2Angle = halfPI;
 
-         } else {
 
-             control1Angle = atan((curX - prevX) / abs(curY - prevY));
 
-             if (prevY < curY) {
 
-                 control1Angle = PI - control1Angle;
 
-             }
 
-             control2Angle = atan((nextX - curX) / abs(curY - nextY));
 
-             if (nextY < curY) {
 
-                 control2Angle = PI - control2Angle;
 
-             }
 
-         }
 
-         // Adjust the calculated angles so they point away from each other on the same line
 
-         alpha = halfPI - ((control1Angle + control2Angle) % (PI * 2)) / 2;
 
-         if (alpha > halfPI) {
 
-             alpha -= PI;
 
-         }
 
-         control1Angle += alpha;
 
-         control2Angle += alpha;
 
-         // Find the control anchor points from the angles and length
 
-         control1X = curX - control1Length * sin(control1Angle);
 
-         control1Y = curY + control1Length * cos(control1Angle);
 
-         control2X = curX + control2Length * sin(control2Angle);
 
-         control2Y = curY + control2Length * cos(control2Angle);
 
-         // One last adjustment, make sure that no control anchor point extends vertically past
 
-         // its target prev/next point, as that results in curves dipping above or below and
 
-         // bending back strangely. If we find this happening we keep the control angle but
 
-         // reduce the length of the control line so it stays within bounds.
 
-         if ((curY > prevY && control1Y < prevY) || (curY < prevY && control1Y > prevY)) {
 
-             control1X += abs(prevY - control1Y) * (control1X - curX) / (control1Y - curY);
 
-             control1Y = prevY;
 
-         }
 
-         if ((curY > nextY && control2Y < nextY) || (curY < nextY && control2Y > nextY)) {
 
-             control2X -= abs(nextY - control2Y) * (control2X - curX) / (control2Y - curY);
 
-             control2Y = nextY;
 
-         }
 
-         
 
-         return {
 
-             x1: control1X,
 
-             y1: control1Y,
 
-             x2: control2X,
 
-             y2: control2Y
 
-         };
 
-     },
 
-     /* Smoothing function for a path.  Converts a path into cubic beziers.  Value defines the divider of the distance between points.
 
-      * Defaults to a value of 4.
 
-      */
 
-     smooth: function (originalPath, value) {
 
-         var path = this.path2curve(originalPath),
 
-             newp = [path[0]],
 
-             x = path[0][1],
 
-             y = path[0][2],
 
-             j,
 
-             points,
 
-             i = 1,
 
-             ii = path.length,
 
-             beg = 1,
 
-             mx = x,
 
-             my = y,
 
-             cx = 0,
 
-             cy = 0,
 
-             pathi,
 
-             pathil,
 
-             pathim,
 
-             pathiml,
 
-             pathip,
 
-             pathipl,
 
-             begl;
 
-         
 
-         for (; i < ii; i++) {
 
-             pathi = path[i];
 
-             pathil = pathi.length;
 
-             pathim = path[i - 1];
 
-             pathiml = pathim.length;
 
-             pathip = path[i + 1];
 
-             pathipl = pathip && pathip.length;
 
-             if (pathi[0] == "M") {
 
-                 mx = pathi[1];
 
-                 my = pathi[2];
 
-                 j = i + 1;
 
-                 while (path[j][0] != "C") {
 
-                     j++;
 
-                 }
 
-                 cx = path[j][5];
 
-                 cy = path[j][6];
 
-                 newp.push(["M", mx, my]);
 
-                 beg = newp.length;
 
-                 x = mx;
 
-                 y = my;
 
-                 continue;
 
-             }
 
-             if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) {
 
-                 begl = newp[beg].length;
 
-                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value);
 
-                 newp[beg][1] = points.x2;
 
-                 newp[beg][2] = points.y2;
 
-             }
 
-             else if (!pathip || pathip[0] == "M") {
 
-                 points = {
 
-                     x1: pathi[pathil - 2],
 
-                     y1: pathi[pathil - 1]
 
-                 };
 
-             } else {
 
-                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value);
 
-             }
 
-             newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]);
 
-             x = points.x2;
 
-             y = points.y2;
 
-         }
 
-         return newp;
 
-     },
 
-     findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
 
-         var t1 = 1 - t;
 
-         return {
 
-             x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x,
 
-             y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y
 
-         };
 
-     },
 
- <span id='Ext-draw-Draw-method-snapEnds'>    /**
 
- </span>     * @private
 
-      */
 
-     snapEnds: function (from, to, stepsMax, prettyNumbers) {
 
-         if (Ext.isDate(from)) {
 
-             return this.snapEndsByDate(from, to, stepsMax);
 
-         }
 
-         var step = (to - from) / stepsMax,
 
-             level = Math.floor(Math.log(step) / Math.LN10) + 1,
 
-             m = Math.pow(10, level),
 
-             cur,
 
-             modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
 
-             interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
 
-             stepCount = 0,
 
-             value,
 
-             weight,
 
-             i,
 
-             topValue,
 
-             topWeight = 1e9,
 
-             ln = interval.length;
 
-         cur = from = Math.floor(from / m) * m;
 
-         
 
-         if(prettyNumbers){
 
-             for (i = 0; i < ln; i++) {
 
-                 value = interval[i][0];
 
-                 weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1];
 
-                 if (weight < topWeight) {
 
-                     topValue = value;
 
-                     topWeight = weight;
 
-                 }
 
-             }
 
-             step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2);
 
-             while (cur < to) {
 
-                 cur += step;
 
-                 stepCount++;
 
-             }
 
-             to = +cur.toFixed(10);
 
-         }else{
 
-             stepCount = stepsMax;
 
-         }
 
-         
 
-         return {
 
-             from: from,
 
-             to: to,
 
-             power: level,
 
-             step: step,
 
-             steps: stepCount
 
-         };
 
-     },
 
- <span id='Ext-draw-Draw-method-snapEndsByDate'>    /**
 
- </span>     * snapEndsByDate is a utility method to deduce an appropriate tick configuration for the data set of given
 
-      * feature. Refer to {@link #snapEnds}.
 
-      *
 
-      * @param {Date} from The minimum value in the data
 
-      * @param {Date} to The maximum value in the data
 
-      * @param {Number} stepsMax The maximum number of ticks
 
-      * @param {Boolean} lockEnds If true, the 'from' and 'to' parameters will be used as fixed end values
 
-      *        and will not be adjusted
 
-      * @return {Object} The calculated step and ends info; properties are:
 
-      *     - from: The result start value, which may be lower than the original start value
 
-      *     - to: The result end value, which may be higher than the original end value
 
-      *     - step: The value size of each step
 
-      *     - steps: The number of steps. NOTE: the steps may not divide the from/to range perfectly evenly;
 
-      *              there may be a smaller distance between the last step and the end value than between prior
 
-      *              steps, particularly when the `endsLocked` param is true. Therefore it is best to not use
 
-      *              the `steps` result when finding the axis tick points, instead use the `step`, `to`, and
 
-      *              `from` to find the correct point for each tick.
 
-      */
 
-     snapEndsByDate: function (from, to, stepsMax, lockEnds) {
 
-         var selectedStep = false,
 
-             scales       = [
 
-                 [Ext.Date.MILLI, [1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 500]],
 
-                 [Ext.Date.SECOND, [1, 2, 3, 5, 10, 15, 30]],
 
-                 [Ext.Date.MINUTE, [1, 2, 3, 5, 10, 20, 30]],
 
-                 [Ext.Date.HOUR, [1, 2, 3, 4, 6, 12]],
 
-                 [Ext.Date.DAY, [1, 2, 3, 7, 14]],
 
-                 [Ext.Date.MONTH, [1, 2, 3, 4, 6]]
 
-             ],
 
-             sLen         = scales.length,
 
-             stop         = false,
 
-             scale, j, yearDiff, s;
 
-         // Find the most desirable scale
 
-         for (s = 0; s < sLen; s++) {
 
-             scale = scales[s];
 
-             if (!stop) {
 
-                 for (j = 0; j < scale[1].length; j++) {
 
-                     if (to < Ext.Date.add(from, scale[0], scale[1][j] * stepsMax)) {
 
-                         selectedStep = [scale[0], scale[1][j]];
 
-                         stop         = true;
 
-                         break;
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         if (!selectedStep) {
 
-             yearDiff = this.snapEnds(from.getFullYear(), to.getFullYear() + 1, stepsMax, lockEnds);
 
-             selectedStep = [Date.YEAR, Math.round(yearDiff.step)];
 
-         }
 
-         return this.snapEndsByDateAndStep(from, to, selectedStep, lockEnds);
 
-     },
 
- <span id='Ext-draw-Draw-method-snapEndsByDateAndStep'>    /**
 
- </span>     * snapEndsByDateAndStep is a utility method to deduce an appropriate tick configuration for the data set of given
 
-      * feature and specific step size.
 
-      * @param {Date} from The minimum value in the data
 
-      * @param {Date} to The maximum value in the data
 
-      * @param {Array} step An array with two components: The first is the unit of the step (day, month, year, etc). The second one is the number of units for the step (1, 2, etc.).
 
-      * @param {Boolean} lockEnds If true, the 'from' and 'to' parameters will be used as fixed end values
 
-      *        and will not be adjusted
 
-      */
 
-     snapEndsByDateAndStep: function(from, to, step, lockEnds) {
 
-         var fromStat = [from.getFullYear(), from.getMonth(), from.getDate(),
 
-                 from.getHours(), from.getMinutes(), from.getSeconds(), from.getMilliseconds()],
 
-             steps = 0, testFrom, testTo;
 
-         if (lockEnds) {
 
-             testFrom = from;
 
-         } else {
 
-             switch (step[0]) {
 
-                 case Ext.Date.MILLI:
 
-                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
 
-                             fromStat[4], fromStat[5], Math.floor(fromStat[6] / step[1]) * step[1]);
 
-                     break;
 
-                 case Ext.Date.SECOND:
 
-                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
 
-                             fromStat[4], Math.floor(fromStat[5] / step[1]) * step[1], 0);
 
-                     break;
 
-                 case Ext.Date.MINUTE:
 
-                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
 
-                             Math.floor(fromStat[4] / step[1]) * step[1], 0, 0);
 
-                     break;
 
-                 case Ext.Date.HOUR:
 
-                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2],
 
-                             Math.floor(fromStat[3] / step[1]) * step[1], 0, 0, 0);
 
-                     break;
 
-                 case Ext.Date.DAY:
 
-                     testFrom = new Date(fromStat[0], fromStat[1],
 
-                             Math.floor(fromStat[2] - 1 / step[1]) * step[1] + 1, 0, 0, 0, 0);
 
-                     break;
 
-                 case Ext.Date.MONTH:
 
-                     testFrom = new Date(fromStat[0], Math.floor(fromStat[1] / step[1]) * step[1], 1, 0, 0, 0, 0);
 
-                     break;
 
-                 default: // Ext.Date.YEAR
 
-                     testFrom = new Date(Math.floor(fromStat[0] / step[1]) * step[1], 0, 1, 0, 0, 0, 0);
 
-                     break;
 
-             }
 
-         }
 
-         testTo = testFrom;
 
-         // TODO(zhangbei) : We can do it better somehow...
 
-         while (testTo < to) {
 
-             testTo = Ext.Date.add(testTo, step[0], step[1]);
 
-             steps++;
 
-         }
 
-         if (lockEnds) {
 
-             testTo = to;
 
-         }
 
-         return {
 
-             from : +testFrom,
 
-             to : +testTo,
 
-             step : (testTo - testFrom) / steps,
 
-             steps : steps
 
-         };
 
-     },
 
-     sorter: function (a, b) {
 
-         return a.offset - b.offset;
 
-     },
 
-     rad: function(degrees) {
 
-         return degrees % 360 * Math.PI / 180;
 
-     },
 
-     degrees: function(radian) {
 
-         return radian * 180 / Math.PI % 360;
 
-     },
 
-     withinBox: function(x, y, bbox) {
 
-         bbox = bbox || {};
 
-         return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height));
 
-     },
 
-     parseGradient: function(gradient) {
 
-         var me = this,
 
-             type = gradient.type || 'linear',
 
-             angle = gradient.angle || 0,
 
-             radian = me.radian,
 
-             stops = gradient.stops,
 
-             stopsArr = [],
 
-             stop,
 
-             vector,
 
-             max,
 
-             stopObj;
 
-         if (type == 'linear') {
 
-             vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)];
 
-             max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
 
-             vector[2] *= max;
 
-             vector[3] *= max;
 
-             if (vector[2] < 0) {
 
-                 vector[0] = -vector[2];
 
-                 vector[2] = 0;
 
-             }
 
-             if (vector[3] < 0) {
 
-                 vector[1] = -vector[3];
 
-                 vector[3] = 0;
 
-             }
 
-         }
 
-         for (stop in stops) {
 
-             if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) {
 
-                 stopObj = {
 
-                     offset: parseInt(stop, 10),
 
-                     color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff',
 
-                     opacity: stops[stop].opacity || 1
 
-                 };
 
-                 stopsArr.push(stopObj);
 
-             }
 
-         }
 
-         // Sort by pct property
 
-         Ext.Array.sort(stopsArr, me.sorter);
 
-         if (type == 'linear') {
 
-             return {
 
-                 id: gradient.id,
 
-                 type: type,
 
-                 vector: vector,
 
-                 stops: stopsArr
 
-             };
 
-         }
 
-         else {
 
-             return {
 
-                 id: gradient.id,
 
-                 type: type,
 
-                 centerX: gradient.centerX,
 
-                 centerY: gradient.centerY,
 
-                 focalX: gradient.focalX,
 
-                 focalY: gradient.focalY,
 
-                 radius: gradient.radius,
 
-                 vector: vector,
 
-                 stops: stopsArr
 
-             };
 
-         }
 
-     }
 
- });
 
- </pre>
 
- </body>
 
- </html>
 
 
  |