src/cm/media/js/lib/yui/yui_3.10.3/build/graphics-vml/graphics-vml-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('graphics-vml', function (Y, NAME) {
       
     9 
       
    10 var IMPLEMENTATION = "vml",
       
    11     SHAPE = "shape",
       
    12 	SPLITPATHPATTERN = /[a-z][^a-z]*/ig,
       
    13     SPLITARGSPATTERN = /[\-]?[0-9]*[0-9|\.][0-9]*/g,
       
    14     Y_LANG = Y.Lang,
       
    15     IS_NUM = Y_LANG.isNumber,
       
    16     IS_ARRAY = Y_LANG.isArray,
       
    17     Y_DOM = Y.DOM,
       
    18     Y_SELECTOR = Y.Selector,
       
    19     DOCUMENT = Y.config.doc,
       
    20     AttributeLite = Y.AttributeLite,
       
    21 	VMLShape,
       
    22 	VMLCircle,
       
    23 	VMLPath,
       
    24 	VMLRect,
       
    25 	VMLEllipse,
       
    26 	VMLGraphic,
       
    27     VMLPieSlice,
       
    28     _getClassName = Y.ClassNameManager.getClassName;
       
    29 
       
    30 function VMLDrawing() {}
       
    31 
       
    32 /**
       
    33  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Drawing.html">`Drawing`</a> class.
       
    34  * `VMLDrawing` is not intended to be used directly. Instead, use the <a href="Drawing.html">`Drawing`</a> class.
       
    35  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
    36  * capabilities, the <a href="Drawing.html">`Drawing`</a> class will point to the `VMLDrawing` class.
       
    37  *
       
    38  * @module graphics
       
    39  * @class VMLDrawing
       
    40  * @constructor
       
    41  */
       
    42 VMLDrawing.prototype = {
       
    43     /**
       
    44      * Maps path to methods
       
    45      *
       
    46      * @property _pathSymbolToMethod
       
    47      * @type Object
       
    48      * @private
       
    49      */
       
    50     _pathSymbolToMethod: {
       
    51         M: "moveTo",
       
    52         m: "relativeMoveTo",
       
    53         L: "lineTo",
       
    54         l: "relativeLineTo",
       
    55         C: "curveTo",
       
    56         c: "relativeCurveTo",
       
    57         Q: "quadraticCurveTo",
       
    58         q: "relativeQuadraticCurveTo",
       
    59         z: "closePath",
       
    60         Z: "closePath"
       
    61     },
       
    62 
       
    63     /**
       
    64      * Value for rounding up to coordsize
       
    65      *
       
    66      * @property _coordSpaceMultiplier
       
    67      * @type Number
       
    68      * @private
       
    69      */
       
    70     _coordSpaceMultiplier: 100,
       
    71 
       
    72     /**
       
    73      * Rounds dimensions and position values based on the coordinate space.
       
    74      *
       
    75      * @method _round
       
    76      * @param {Number} The value for rounding
       
    77      * @return Number
       
    78      * @private
       
    79      */
       
    80     _round:function(val)
       
    81     {
       
    82         return Math.round(val * this._coordSpaceMultiplier);
       
    83     },
       
    84 
       
    85     /**
       
    86      * Concatanates the path.
       
    87      *
       
    88      * @method _addToPath
       
    89      * @param {String} val The value to add to the path string.
       
    90      * @private
       
    91      */
       
    92     _addToPath: function(val)
       
    93     {
       
    94         this._path = this._path || "";
       
    95         if(this._movePath)
       
    96         {
       
    97             this._path += this._movePath;
       
    98             this._movePath = null;
       
    99         }
       
   100         this._path += val;
       
   101     },
       
   102 
       
   103     /**
       
   104      * Current x position of the drawing.
       
   105      *
       
   106      * @property _currentX
       
   107      * @type Number
       
   108      * @private
       
   109      */
       
   110     _currentX: 0,
       
   111 
       
   112     /**
       
   113      * Current y position of the drqwing.
       
   114      *
       
   115      * @property _currentY
       
   116      * @type Number
       
   117      * @private
       
   118      */
       
   119     _currentY: 0,
       
   120 
       
   121     /**
       
   122      * Draws a bezier curve.
       
   123      *
       
   124      * @method curveTo
       
   125      * @param {Number} cp1x x-coordinate for the first control point.
       
   126      * @param {Number} cp1y y-coordinate for the first control point.
       
   127      * @param {Number} cp2x x-coordinate for the second control point.
       
   128      * @param {Number} cp2y y-coordinate for the second control point.
       
   129      * @param {Number} x x-coordinate for the end point.
       
   130      * @param {Number} y y-coordinate for the end point.
       
   131      * @chainable
       
   132      */
       
   133     curveTo: function() {
       
   134         this._curveTo.apply(this, [Y.Array(arguments), false]);
       
   135         return this;
       
   136     },
       
   137 
       
   138     /**
       
   139      * Draws a bezier curve.
       
   140      *
       
   141      * @method relativeCurveTo
       
   142      * @param {Number} cp1x x-coordinate for the first control point.
       
   143      * @param {Number} cp1y y-coordinate for the first control point.
       
   144      * @param {Number} cp2x x-coordinate for the second control point.
       
   145      * @param {Number} cp2y y-coordinate for the second control point.
       
   146      * @param {Number} x x-coordinate for the end point.
       
   147      * @param {Number} y y-coordinate for the end point.
       
   148      * @chainable
       
   149      */
       
   150     relativeCurveTo: function() {
       
   151         this._curveTo.apply(this, [Y.Array(arguments), true]);
       
   152         return this;
       
   153     },
       
   154 
       
   155     /**
       
   156      * Implements curveTo methods.
       
   157      *
       
   158      * @method _curveTo
       
   159      * @param {Array} args The arguments to be used.
       
   160      * @param {Boolean} relative Indicates whether or not to use relative coordinates.
       
   161      * @private
       
   162      */
       
   163     _curveTo: function(args, relative) {
       
   164         var w,
       
   165             h,
       
   166             x,
       
   167             y,
       
   168             cp1x,
       
   169             cp1y,
       
   170             cp2x,
       
   171             cp2y,
       
   172             pts,
       
   173             right,
       
   174             left,
       
   175             bottom,
       
   176             top,
       
   177             i,
       
   178             len,
       
   179             path,
       
   180             command = relative ? " v " : " c ",
       
   181             relativeX = relative ? parseFloat(this._currentX) : 0,
       
   182             relativeY = relative ? parseFloat(this._currentY) : 0;
       
   183         len = args.length - 5;
       
   184         path = command;
       
   185         for(i = 0; i < len; i = i + 6)
       
   186         {
       
   187             cp1x = parseFloat(args[i]);
       
   188             cp1y = parseFloat(args[i + 1]);
       
   189             cp2x = parseFloat(args[i + 2]);
       
   190             cp2y = parseFloat(args[i + 3]);
       
   191             x = parseFloat(args[i + 4]);
       
   192             y = parseFloat(args[i + 5]);
       
   193             if(i > 0)
       
   194             {
       
   195                 path = path + ", ";
       
   196             }
       
   197             path = path +
       
   198                     this._round(cp1x) +
       
   199                     ", " +
       
   200                     this._round(cp1y) +
       
   201                     ", " +
       
   202                     this._round(cp2x) +
       
   203                     ", " +
       
   204                     this._round(cp2y) +
       
   205                     ", " +
       
   206                     this._round(x) +
       
   207                     ", " +
       
   208                     this._round(y);
       
   209             cp1x = cp1x + relativeX;
       
   210             cp1y = cp1y + relativeY;
       
   211             cp2x = cp2x + relativeX;
       
   212             cp2y = cp2y + relativeY;
       
   213             x = x + relativeX;
       
   214             y = y + relativeY;
       
   215             right = Math.max(x, Math.max(cp1x, cp2x));
       
   216             bottom = Math.max(y, Math.max(cp1y, cp2y));
       
   217             left = Math.min(x, Math.min(cp1x, cp2x));
       
   218             top = Math.min(y, Math.min(cp1y, cp2y));
       
   219             w = Math.abs(right - left);
       
   220             h = Math.abs(bottom - top);
       
   221             pts = [[this._currentX, this._currentY] , [cp1x, cp1y], [cp2x, cp2y], [x, y]];
       
   222             this._setCurveBoundingBox(pts, w, h);
       
   223             this._currentX = x;
       
   224             this._currentY = y;
       
   225         }
       
   226         this._addToPath(path);
       
   227     },
       
   228 
       
   229     /**
       
   230      * Draws a quadratic bezier curve.
       
   231      *
       
   232      * @method quadraticCurveTo
       
   233      * @param {Number} cpx x-coordinate for the control point.
       
   234      * @param {Number} cpy y-coordinate for the control point.
       
   235      * @param {Number} x x-coordinate for the end point.
       
   236      * @param {Number} y y-coordinate for the end point.
       
   237      * @chainable
       
   238      */
       
   239     quadraticCurveTo: function() {
       
   240         this._quadraticCurveTo.apply(this, [Y.Array(arguments), false]);
       
   241         return this;
       
   242     },
       
   243 
       
   244     /**
       
   245      * Draws a quadratic bezier curve relative to the current position.
       
   246      *
       
   247      * @method relativeQuadraticCurveTo
       
   248      * @param {Number} cpx x-coordinate for the control point.
       
   249      * @param {Number} cpy y-coordinate for the control point.
       
   250      * @param {Number} x x-coordinate for the end point.
       
   251      * @param {Number} y y-coordinate for the end point.
       
   252      * @chainable
       
   253      */
       
   254     relativeQuadraticCurveTo: function() {
       
   255         this._quadraticCurveTo.apply(this, [Y.Array(arguments), true]);
       
   256         return this;
       
   257     },
       
   258 
       
   259     /**
       
   260      * Implements quadraticCurveTo methods.
       
   261      *
       
   262      * @method _quadraticCurveTo
       
   263      * @param {Array} args The arguments to be used.
       
   264      * @param {Boolean} relative Indicates whether or not to use relative coordinates.
       
   265      * @private
       
   266      */
       
   267     _quadraticCurveTo: function(args, relative) {
       
   268         var cpx,
       
   269             cpy,
       
   270             cp1x,
       
   271             cp1y,
       
   272             cp2x,
       
   273             cp2y,
       
   274             x,
       
   275             y,
       
   276             currentX = this._currentX,
       
   277             currentY = this._currentY,
       
   278             i,
       
   279             len = args.length - 3,
       
   280             bezierArgs = [],
       
   281             relativeX = relative ? parseFloat(this._currentX) : 0,
       
   282             relativeY = relative ? parseFloat(this._currentY) : 0;
       
   283         for(i = 0; i < len; i = i + 4)
       
   284         {
       
   285             cpx = parseFloat(args[i]) + relativeX;
       
   286             cpy = parseFloat(args[i + 1]) + relativeY;
       
   287             x = parseFloat(args[i + 2]) + relativeX;
       
   288             y = parseFloat(args[i + 3]) + relativeY;
       
   289             cp1x = currentX + 0.67*(cpx - currentX);
       
   290             cp1y = currentY + 0.67*(cpy - currentY);
       
   291             cp2x = cp1x + (x - currentX) * 0.34;
       
   292             cp2y = cp1y + (y - currentY) * 0.34;
       
   293             bezierArgs.push(cp1x);
       
   294             bezierArgs.push(cp1y);
       
   295             bezierArgs.push(cp2x);
       
   296             bezierArgs.push(cp2y);
       
   297             bezierArgs.push(x);
       
   298             bezierArgs.push(y);
       
   299         }
       
   300         this._curveTo.apply(this, [bezierArgs, false]);
       
   301     },
       
   302 
       
   303     /**
       
   304      * Draws a rectangle.
       
   305      *
       
   306      * @method drawRect
       
   307      * @param {Number} x x-coordinate
       
   308      * @param {Number} y y-coordinate
       
   309      * @param {Number} w width
       
   310      * @param {Number} h height
       
   311      * @chainable
       
   312      */
       
   313     drawRect: function(x, y, w, h) {
       
   314         this.moveTo(x, y);
       
   315         this.lineTo(x + w, y);
       
   316         this.lineTo(x + w, y + h);
       
   317         this.lineTo(x, y + h);
       
   318         this.lineTo(x, y);
       
   319         this._currentX = x;
       
   320         this._currentY = y;
       
   321         return this;
       
   322     },
       
   323 
       
   324     /**
       
   325      * Draws a rectangle with rounded corners.
       
   326      *
       
   327      * @method drawRect
       
   328      * @param {Number} x x-coordinate
       
   329      * @param {Number} y y-coordinate
       
   330      * @param {Number} w width
       
   331      * @param {Number} h height
       
   332      * @param {Number} ew width of the ellipse used to draw the rounded corners
       
   333      * @param {Number} eh height of the ellipse used to draw the rounded corners
       
   334      * @chainable
       
   335      */
       
   336     drawRoundRect: function(x, y, w, h, ew, eh) {
       
   337         this.moveTo(x, y + eh);
       
   338         this.lineTo(x, y + h - eh);
       
   339         this.quadraticCurveTo(x, y + h, x + ew, y + h);
       
   340         this.lineTo(x + w - ew, y + h);
       
   341         this.quadraticCurveTo(x + w, y + h, x + w, y + h - eh);
       
   342         this.lineTo(x + w, y + eh);
       
   343         this.quadraticCurveTo(x + w, y, x + w - ew, y);
       
   344         this.lineTo(x + ew, y);
       
   345         this.quadraticCurveTo(x, y, x, y + eh);
       
   346         return this;
       
   347     },
       
   348 
       
   349     /**
       
   350      * Draws a circle. Used internally by `CanvasCircle` class.
       
   351      *
       
   352      * @method drawCircle
       
   353      * @param {Number} x y-coordinate
       
   354      * @param {Number} y x-coordinate
       
   355      * @param {Number} r radius
       
   356      * @chainable
       
   357      * @protected
       
   358      */
       
   359 	drawCircle: function(x, y, radius) {
       
   360         var startAngle = 0,
       
   361             endAngle = 360,
       
   362             circum = radius * 2;
       
   363 
       
   364         endAngle *= 65535;
       
   365         this._drawingComplete = false;
       
   366         this._trackSize(x + circum, y + circum);
       
   367         this.moveTo((x + circum), (y + radius));
       
   368         this._addToPath(
       
   369             " ae " +
       
   370             this._round(x + radius) +
       
   371             ", " +
       
   372             this._round(y + radius) +
       
   373             ", " +
       
   374             this._round(radius) +
       
   375             ", " +
       
   376             this._round(radius) +
       
   377             ", " +
       
   378             startAngle +
       
   379             ", " +
       
   380             endAngle
       
   381         );
       
   382         return this;
       
   383     },
       
   384 
       
   385     /**
       
   386      * Draws an ellipse.
       
   387      *
       
   388      * @method drawEllipse
       
   389      * @param {Number} x x-coordinate
       
   390      * @param {Number} y y-coordinate
       
   391      * @param {Number} w width
       
   392      * @param {Number} h height
       
   393      * @chainable
       
   394      * @protected
       
   395      */
       
   396 	drawEllipse: function(x, y, w, h) {
       
   397         var startAngle = 0,
       
   398             endAngle = 360,
       
   399             radius = w * 0.5,
       
   400             yRadius = h * 0.5;
       
   401         endAngle *= 65535;
       
   402         this._drawingComplete = false;
       
   403         this._trackSize(x + w, y + h);
       
   404         this.moveTo((x + w), (y + yRadius));
       
   405         this._addToPath(
       
   406             " ae " +
       
   407             this._round(x + radius) +
       
   408             ", " +
       
   409             this._round(x + radius) +
       
   410             ", " +
       
   411             this._round(y + yRadius) +
       
   412             ", " +
       
   413             this._round(radius) +
       
   414             ", " +
       
   415             this._round(yRadius) +
       
   416             ", " +
       
   417             startAngle +
       
   418             ", " +
       
   419             endAngle
       
   420         );
       
   421         return this;
       
   422     },
       
   423 
       
   424     /**
       
   425      * Draws a diamond.
       
   426      *
       
   427      * @method drawDiamond
       
   428      * @param {Number} x y-coordinate
       
   429      * @param {Number} y x-coordinate
       
   430      * @param {Number} width width
       
   431      * @param {Number} height height
       
   432      * @chainable
       
   433      * @protected
       
   434      */
       
   435     drawDiamond: function(x, y, width, height)
       
   436     {
       
   437         var midWidth = width * 0.5,
       
   438             midHeight = height * 0.5;
       
   439         this.moveTo(x + midWidth, y);
       
   440         this.lineTo(x + width, y + midHeight);
       
   441         this.lineTo(x + midWidth, y + height);
       
   442         this.lineTo(x, y + midHeight);
       
   443         this.lineTo(x + midWidth, y);
       
   444         return this;
       
   445     },
       
   446 
       
   447     /**
       
   448      * Draws a wedge.
       
   449      *
       
   450      * @method drawWedge
       
   451      * @param {Number} x x-coordinate of the wedge's center point
       
   452      * @param {Number} y y-coordinate of the wedge's center point
       
   453      * @param {Number} startAngle starting angle in degrees
       
   454      * @param {Number} arc sweep of the wedge. Negative values draw clockwise.
       
   455      * @param {Number} radius radius of wedge. If [optional] yRadius is defined, then radius is the x radius.
       
   456      * @param {Number} yRadius [optional] y radius for wedge.
       
   457      * @chainable
       
   458      * @private
       
   459      */
       
   460     drawWedge: function(x, y, startAngle, arc, radius)
       
   461     {
       
   462         var diameter = radius * 2;
       
   463         if(Math.abs(arc) > 360)
       
   464         {
       
   465             arc = 360;
       
   466         }
       
   467         this._currentX = x;
       
   468         this._currentY = y;
       
   469         startAngle *= -65535;
       
   470         arc *= 65536;
       
   471         startAngle = Math.round(startAngle);
       
   472         arc = Math.round(arc);
       
   473         this.moveTo(x, y);
       
   474         this._addToPath(
       
   475             " ae " +
       
   476             this._round(x) +
       
   477             ", " +
       
   478             this._round(y) +
       
   479             ", " +
       
   480             this._round(radius) +
       
   481             " " +
       
   482             this._round(radius) +
       
   483             ", " +
       
   484             startAngle +
       
   485             ", " +
       
   486             arc
       
   487         );
       
   488         this._trackSize(diameter, diameter);
       
   489         return this;
       
   490     },
       
   491 
       
   492     /**
       
   493      * Draws a line segment from the current drawing position to the specified x and y coordinates.
       
   494      *
       
   495      * @method lineTo
       
   496      * @param {Number} point1 x-coordinate for the end point.
       
   497      * @param {Number} point2 y-coordinate for the end point.
       
   498      * @chainable
       
   499      */
       
   500     lineTo: function()
       
   501     {
       
   502         this._lineTo.apply(this, [Y.Array(arguments), false]);
       
   503         return this;
       
   504     },
       
   505 
       
   506     /**
       
   507      * Draws a line segment using the current line style from the current drawing position to the relative x and y coordinates.
       
   508      *
       
   509      * @method relativeLineTo
       
   510      * @param {Number} point1 x-coordinate for the end point.
       
   511      * @param {Number} point2 y-coordinate for the end point.
       
   512      * @chainable
       
   513      */
       
   514     relativeLineTo: function()
       
   515     {
       
   516         this._lineTo.apply(this, [Y.Array(arguments), true]);
       
   517         return this;
       
   518     },
       
   519 
       
   520     /**
       
   521      * Implements lineTo methods.
       
   522      *
       
   523      * @method _lineTo
       
   524      * @param {Array} args The arguments to be used.
       
   525      * @param {Boolean} relative Indicates whether or not to use relative coordinates.
       
   526      * @private
       
   527      */
       
   528     _lineTo: function(args, relative) {
       
   529         var point1 = args[0],
       
   530             i,
       
   531             len,
       
   532             x,
       
   533             y,
       
   534             path = relative ? " r " : " l ",
       
   535             relativeX = relative ? parseFloat(this._currentX) : 0,
       
   536             relativeY = relative ? parseFloat(this._currentY) : 0;
       
   537         if (typeof point1 === "string" || typeof point1 === "number") {
       
   538             len = args.length - 1;
       
   539             for (i = 0; i < len; i = i + 2) {
       
   540                 x = parseFloat(args[i]);
       
   541                 y = parseFloat(args[i + 1]);
       
   542                 path += ' ' + this._round(x) + ', ' + this._round(y);
       
   543                 x = x + relativeX;
       
   544                 y = y + relativeY;
       
   545                 this._currentX = x;
       
   546                 this._currentY = y;
       
   547                 this._trackSize.apply(this, [x, y]);
       
   548             }
       
   549         }
       
   550         else
       
   551         {
       
   552             len = args.length;
       
   553             for (i = 0; i < len; i = i + 1) {
       
   554                 x = parseFloat(args[i][0]);
       
   555                 y = parseFloat(args[i][1]);
       
   556                 path += ' ' + this._round(x) + ', ' + this._round(y);
       
   557                 x = x + relativeX;
       
   558                 y = y + relativeY;
       
   559                 this._currentX = x;
       
   560                 this._currentY = y;
       
   561                 this._trackSize.apply(this, [x, y]);
       
   562             }
       
   563         }
       
   564         this._addToPath(path);
       
   565         return this;
       
   566     },
       
   567 
       
   568     /**
       
   569      * Moves the current drawing position to specified x and y coordinates.
       
   570      *
       
   571      * @method moveTo
       
   572      * @param {Number} x x-coordinate for the end point.
       
   573      * @param {Number} y y-coordinate for the end point.
       
   574      * @chainable
       
   575      */
       
   576     moveTo: function()
       
   577     {
       
   578         this._moveTo.apply(this, [Y.Array(arguments), false]);
       
   579         return this;
       
   580     },
       
   581 
       
   582     /**
       
   583      * Moves the current drawing position relative to specified x and y coordinates.
       
   584      *
       
   585      * @method relativeMoveTo
       
   586      * @param {Number} x x-coordinate for the end point.
       
   587      * @param {Number} y y-coordinate for the end point.
       
   588      * @chainable
       
   589      */
       
   590     relativeMoveTo: function()
       
   591     {
       
   592         this._moveTo.apply(this, [Y.Array(arguments), true]);
       
   593         return this;
       
   594     },
       
   595 
       
   596     /**
       
   597      * Implements moveTo methods.
       
   598      *
       
   599      * @method _moveTo
       
   600      * @param {Array} args The arguments to be used.
       
   601      * @param {Boolean} relative Indicates whether or not to use relative coordinates.
       
   602      * @private
       
   603      */
       
   604     _moveTo: function(args, relative) {
       
   605         var x = parseFloat(args[0]),
       
   606             y = parseFloat(args[1]),
       
   607             command = relative ? " t " : " m ",
       
   608             relativeX = relative ? parseFloat(this._currentX) : 0,
       
   609             relativeY = relative ? parseFloat(this._currentY) : 0;
       
   610         this._movePath = command + this._round(x) + ", " + this._round(y);
       
   611         x = x + relativeX;
       
   612         y = y + relativeY;
       
   613         this._trackSize(x, y);
       
   614         this._currentX = x;
       
   615         this._currentY = y;
       
   616     },
       
   617 
       
   618     /**
       
   619      * Draws the graphic.
       
   620      *
       
   621      * @method _draw
       
   622      * @private
       
   623      */
       
   624     _closePath: function()
       
   625     {
       
   626         var fill = this.get("fill"),
       
   627             stroke = this.get("stroke"),
       
   628             node = this.node,
       
   629             w = this.get("width"),
       
   630             h = this.get("height"),
       
   631             path = this._path,
       
   632             pathEnd = "",
       
   633             multiplier = this._coordSpaceMultiplier;
       
   634         this._fillChangeHandler();
       
   635         this._strokeChangeHandler();
       
   636         if(path)
       
   637         {
       
   638             if(fill && fill.color)
       
   639             {
       
   640                 pathEnd += ' x';
       
   641             }
       
   642             if(stroke)
       
   643             {
       
   644                 pathEnd += ' e';
       
   645             }
       
   646         }
       
   647         if(path)
       
   648         {
       
   649             node.path = path + pathEnd;
       
   650         }
       
   651         if(!isNaN(w) && !isNaN(h))
       
   652         {
       
   653             node.coordOrigin = this._left + ", " + this._top;
       
   654             node.coordSize = (w * multiplier) + ", " + (h * multiplier);
       
   655             node.style.position = "absolute";
       
   656             node.style.width =  w + "px";
       
   657             node.style.height =  h + "px";
       
   658         }
       
   659         this._path = path;
       
   660         this._movePath = null;
       
   661         this._updateTransform();
       
   662     },
       
   663 
       
   664     /**
       
   665      * Completes a drawing operation.
       
   666      *
       
   667      * @method end
       
   668      * @chainable
       
   669      */
       
   670     end: function()
       
   671     {
       
   672         this._closePath();
       
   673         return this;
       
   674     },
       
   675 
       
   676     /**
       
   677      * Ends a fill and stroke
       
   678      *
       
   679      * @method closePath
       
   680      * @chainable
       
   681      */
       
   682     closePath: function()
       
   683     {
       
   684         this._addToPath(" x e");
       
   685         return this;
       
   686     },
       
   687 
       
   688     /**
       
   689      * Clears the path.
       
   690      *
       
   691      * @method clear
       
   692      * @chainable
       
   693      */
       
   694     clear: function()
       
   695     {
       
   696 		this._right = 0;
       
   697         this._bottom = 0;
       
   698         this._width = 0;
       
   699         this._height = 0;
       
   700         this._left = 0;
       
   701         this._top = 0;
       
   702         this._path = "";
       
   703         this._movePath = null;
       
   704         return this;
       
   705     },
       
   706 
       
   707     /**
       
   708      * Returns the points on a curve
       
   709      *
       
   710      * @method getBezierData
       
   711      * @param Array points Array containing the begin, end and control points of a curve.
       
   712      * @param Number t The value for incrementing the next set of points.
       
   713      * @return Array
       
   714      * @private
       
   715      */
       
   716     getBezierData: function(points, t) {
       
   717         var n = points.length,
       
   718             tmp = [],
       
   719             i,
       
   720             j;
       
   721 
       
   722         for (i = 0; i < n; ++i){
       
   723             tmp[i] = [points[i][0], points[i][1]]; // save input
       
   724         }
       
   725 
       
   726         for (j = 1; j < n; ++j) {
       
   727             for (i = 0; i < n - j; ++i) {
       
   728                 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
       
   729                 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
       
   730             }
       
   731         }
       
   732         return [ tmp[0][0], tmp[0][1] ];
       
   733     },
       
   734 
       
   735     /**
       
   736      * Calculates the bounding box for a curve
       
   737      *
       
   738      * @method _setCurveBoundingBox
       
   739      * @param Array pts Array containing points for start, end and control points of a curve.
       
   740      * @param Number w Width used to calculate the number of points to describe the curve.
       
   741      * @param Number h Height used to calculate the number of points to describe the curve.
       
   742      * @private
       
   743      */
       
   744     _setCurveBoundingBox: function(pts, w, h)
       
   745     {
       
   746         var i,
       
   747             left = this._currentX,
       
   748             right = left,
       
   749             top = this._currentY,
       
   750             bottom = top,
       
   751             len = Math.round(Math.sqrt((w * w) + (h * h))),
       
   752             t = 1/len,
       
   753             xy;
       
   754         for(i = 0; i < len; ++i)
       
   755         {
       
   756             xy = this.getBezierData(pts, t * i);
       
   757             left = isNaN(left) ? xy[0] : Math.min(xy[0], left);
       
   758             right = isNaN(right) ? xy[0] : Math.max(xy[0], right);
       
   759             top = isNaN(top) ? xy[1] : Math.min(xy[1], top);
       
   760             bottom = isNaN(bottom) ? xy[1] : Math.max(xy[1], bottom);
       
   761         }
       
   762         left = Math.round(left * 10)/10;
       
   763         right = Math.round(right * 10)/10;
       
   764         top = Math.round(top * 10)/10;
       
   765         bottom = Math.round(bottom * 10)/10;
       
   766         this._trackSize(right, bottom);
       
   767         this._trackSize(left, top);
       
   768     },
       
   769 
       
   770     /**
       
   771      * Updates the size of the graphics object
       
   772      *
       
   773      * @method _trackSize
       
   774      * @param {Number} w width
       
   775      * @param {Number} h height
       
   776      * @private
       
   777      */
       
   778     _trackSize: function(w, h) {
       
   779         if (w > this._right) {
       
   780             this._right = w;
       
   781         }
       
   782         if(w < this._left)
       
   783         {
       
   784             this._left = w;
       
   785         }
       
   786         if (h < this._top)
       
   787         {
       
   788             this._top = h;
       
   789         }
       
   790         if (h > this._bottom)
       
   791         {
       
   792             this._bottom = h;
       
   793         }
       
   794         this._width = this._right - this._left;
       
   795         this._height = this._bottom - this._top;
       
   796     },
       
   797 
       
   798     _left: 0,
       
   799 
       
   800     _right: 0,
       
   801 
       
   802     _top: 0,
       
   803 
       
   804     _bottom: 0,
       
   805 
       
   806     _width: 0,
       
   807 
       
   808     _height: 0
       
   809 };
       
   810 Y.VMLDrawing = VMLDrawing;
       
   811 /**
       
   812  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Shape.html">`Shape`</a> class.
       
   813  * `VMLShape` is not intended to be used directly. Instead, use the <a href="Shape.html">`Shape`</a> class.
       
   814  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
   815  * capabilities, the <a href="Shape.html">`Shape`</a> class will point to the `VMLShape` class.
       
   816  *
       
   817  * @module graphics
       
   818  * @class VMLShape
       
   819  * @constructor
       
   820  * @param {Object} cfg (optional) Attribute configs
       
   821  */
       
   822 VMLShape = function()
       
   823 {
       
   824     this._transforms = [];
       
   825     this.matrix = new Y.Matrix();
       
   826     this._normalizedMatrix = new Y.Matrix();
       
   827     VMLShape.superclass.constructor.apply(this, arguments);
       
   828 };
       
   829 
       
   830 VMLShape.NAME = "shape";
       
   831 
       
   832 Y.extend(VMLShape, Y.GraphicBase, Y.mix({
       
   833 	/**
       
   834 	 * Indicates the type of shape
       
   835 	 *
       
   836 	 * @property _type
       
   837 	 * @type String
       
   838      * @private
       
   839 	 */
       
   840 	_type: "shape",
       
   841 
       
   842     /**
       
   843      * Init method, invoked during construction.
       
   844      * Calls `initializer` method.
       
   845      *
       
   846      * @method init
       
   847      * @protected
       
   848      */
       
   849 	init: function()
       
   850 	{
       
   851 		this.initializer.apply(this, arguments);
       
   852 	},
       
   853 
       
   854 	/**
       
   855 	 * Initializes the shape
       
   856 	 *
       
   857 	 * @private
       
   858 	 * @method _initialize
       
   859 	 */
       
   860 	initializer: function(cfg)
       
   861 	{
       
   862 		var host = this,
       
   863             graphic = cfg.graphic,
       
   864             data = this.get("data");
       
   865 		host.createNode();
       
   866         if(graphic)
       
   867         {
       
   868             this._setGraphic(graphic);
       
   869         }
       
   870         if(data)
       
   871         {
       
   872             host._parsePathData(data);
       
   873         }
       
   874         this._updateHandler();
       
   875 	},
       
   876 
       
   877     /**
       
   878      * Set the Graphic instance for the shape.
       
   879      *
       
   880      * @method _setGraphic
       
   881      * @param {Graphic | Node | HTMLElement | String} render This param is used to determine the graphic instance. If it is a
       
   882      * `Graphic` instance, it will be assigned to the `graphic` attribute. Otherwise, a new Graphic instance will be created
       
   883      * and rendered into the dom element that the render represents.
       
   884      * @private
       
   885      */
       
   886     _setGraphic: function(render)
       
   887     {
       
   888         var graphic;
       
   889         if(render instanceof Y.VMLGraphic)
       
   890         {
       
   891             this._graphic = render;
       
   892         }
       
   893         else
       
   894         {
       
   895             render = Y.one(render);
       
   896             graphic = new Y.VMLGraphic({
       
   897                 render: render
       
   898             });
       
   899             graphic._appendShape(this);
       
   900             this._graphic = graphic;
       
   901             this._appendStrokeAndFill();
       
   902         }
       
   903     },
       
   904 
       
   905     /**
       
   906      * Appends fill and stroke nodes to the shape.
       
   907      *
       
   908      * @method _appendStrokeAndFill
       
   909      * @private
       
   910      */
       
   911     _appendStrokeAndFill: function()
       
   912     {
       
   913         if(this._strokeNode)
       
   914         {
       
   915             this.node.appendChild(this._strokeNode);
       
   916         }
       
   917         if(this._fillNode)
       
   918         {
       
   919             this.node.appendChild(this._fillNode);
       
   920         }
       
   921     },
       
   922 
       
   923 	/**
       
   924 	 * Creates the dom node for the shape.
       
   925 	 *
       
   926      * @method createNode
       
   927 	 * @return HTMLElement
       
   928 	 * @private
       
   929 	 */
       
   930 	createNode: function()
       
   931 	{
       
   932         var node,
       
   933             concat = this._camelCaseConcat,
       
   934 			x = this.get("x"),
       
   935 			y = this.get("y"),
       
   936             w = this.get("width"),
       
   937             h = this.get("height"),
       
   938 			id,
       
   939 			type,
       
   940 			name = this.name,
       
   941             nodestring,
       
   942             visibility = this.get("visible") ? "visible" : "hidden",
       
   943 			strokestring,
       
   944 			classString,
       
   945 			stroke,
       
   946 			endcap,
       
   947 			opacity,
       
   948 			joinstyle,
       
   949 			miterlimit,
       
   950 			dashstyle,
       
   951 			fill,
       
   952 			fillstring;
       
   953 			id = this.get("id");
       
   954 		type = this._type === "path" ? "shape" : this._type;
       
   955         classString = _getClassName(SHAPE) +
       
   956                     " " +
       
   957                     _getClassName(concat(IMPLEMENTATION, SHAPE)) +
       
   958                     " " +
       
   959                     _getClassName(name) +
       
   960                     " " +
       
   961                     _getClassName(concat(IMPLEMENTATION, name)) +
       
   962                     " " +
       
   963                     IMPLEMENTATION +
       
   964                     type;
       
   965         stroke = this._getStrokeProps();
       
   966         fill = this._getFillProps();
       
   967 
       
   968 		nodestring  = '<' +
       
   969                         type +
       
   970                         '  xmlns="urn:schemas-microsft.com:vml" id="' +
       
   971                         id +
       
   972                         '" class="' +
       
   973                         classString +
       
   974                         '" style="behavior:url(#default#VML);display:inline-block;position:absolute;left:' +
       
   975                         x +
       
   976                         'px;top:' +
       
   977                         y +
       
   978                         'px;width:' +
       
   979                         w +
       
   980                         'px;height:' +
       
   981                         h +
       
   982                         'px;visibility:' +
       
   983                         visibility +
       
   984                         '"';
       
   985 
       
   986         if(stroke && stroke.weight && stroke.weight > 0)
       
   987         {
       
   988             endcap = stroke.endcap;
       
   989             opacity = parseFloat(stroke.opacity);
       
   990             joinstyle = stroke.joinstyle;
       
   991             miterlimit = stroke.miterlimit;
       
   992             dashstyle = stroke.dashstyle;
       
   993             nodestring += ' stroked="t" strokecolor="' + stroke.color + '" strokeWeight="' + stroke.weight + 'px"';
       
   994 
       
   995             strokestring = '<stroke class="vmlstroke"' +
       
   996                             ' xmlns="urn:schemas-microsft.com:vml"' +
       
   997                             ' on="t"' +
       
   998                             ' style="behavior:url(#default#VML);display:inline-block;"' +
       
   999                             ' opacity="' + opacity + '"';
       
  1000             if(endcap)
       
  1001             {
       
  1002                 strokestring += ' endcap="' + endcap + '"';
       
  1003             }
       
  1004             if(joinstyle)
       
  1005             {
       
  1006                 strokestring += ' joinstyle="' + joinstyle + '"';
       
  1007             }
       
  1008             if(miterlimit)
       
  1009             {
       
  1010                 strokestring += ' miterlimit="' + miterlimit + '"';
       
  1011             }
       
  1012             if(dashstyle)
       
  1013             {
       
  1014                 strokestring += ' dashstyle="' + dashstyle + '"';
       
  1015             }
       
  1016             strokestring += '></stroke>';
       
  1017             this._strokeNode = DOCUMENT.createElement(strokestring);
       
  1018             nodestring += ' stroked="t"';
       
  1019         }
       
  1020         else
       
  1021         {
       
  1022             nodestring += ' stroked="f"';
       
  1023         }
       
  1024         if(fill)
       
  1025         {
       
  1026             if(fill.node)
       
  1027             {
       
  1028                 fillstring = fill.node;
       
  1029                 this._fillNode = DOCUMENT.createElement(fillstring);
       
  1030             }
       
  1031             if(fill.color)
       
  1032             {
       
  1033                 nodestring += ' fillcolor="' + fill.color + '"';
       
  1034             }
       
  1035             nodestring += ' filled="' + fill.filled + '"';
       
  1036         }
       
  1037 
       
  1038 
       
  1039         nodestring += '>';
       
  1040         nodestring += '</' + type + '>';
       
  1041 
       
  1042         node = DOCUMENT.createElement(nodestring);
       
  1043 
       
  1044         this.node = node;
       
  1045         this._strokeFlag = false;
       
  1046         this._fillFlag = false;
       
  1047 	},
       
  1048 
       
  1049 	/**
       
  1050 	 * Add a class name to each node.
       
  1051 	 *
       
  1052 	 * @method addClass
       
  1053 	 * @param {String} className the class name to add to the node's class attribute
       
  1054 	 */
       
  1055 	addClass: function(className)
       
  1056 	{
       
  1057         var node = this.node;
       
  1058 		Y_DOM.addClass(node, className);
       
  1059 	},
       
  1060 
       
  1061 	/**
       
  1062 	 * Removes a class name from each node.
       
  1063 	 *
       
  1064 	 * @method removeClass
       
  1065 	 * @param {String} className the class name to remove from the node's class attribute
       
  1066 	 */
       
  1067 	removeClass: function(className)
       
  1068 	{
       
  1069         var node = this.node;
       
  1070 		Y_DOM.removeClass(node, className);
       
  1071 	},
       
  1072 
       
  1073 	/**
       
  1074 	 * Gets the current position of the node in page coordinates.
       
  1075 	 *
       
  1076 	 * @method getXY
       
  1077 	 * @return Array The XY position of the shape.
       
  1078 	 */
       
  1079 	getXY: function()
       
  1080 	{
       
  1081 		var graphic = this._graphic,
       
  1082 			parentXY = graphic.getXY(),
       
  1083 			x = this.get("x"),
       
  1084 			y = this.get("y");
       
  1085 		return [parentXY[0] + x, parentXY[1] + y];
       
  1086 	},
       
  1087 
       
  1088 	/**
       
  1089 	 * Set the position of the shape in page coordinates, regardless of how the node is positioned.
       
  1090 	 *
       
  1091 	 * @method setXY
       
  1092 	 * @param {Array} Contains x & y values for new position (coordinates are page-based)
       
  1093      *
       
  1094 	 */
       
  1095 	setXY: function(xy)
       
  1096 	{
       
  1097 		var graphic = this._graphic,
       
  1098 			parentXY = graphic.getXY();
       
  1099 		this.set("x", xy[0] - parentXY[0]);
       
  1100 		this.set("y", xy[1] - parentXY[1]);
       
  1101 	},
       
  1102 
       
  1103 	/**
       
  1104 	 * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
       
  1105 	 *
       
  1106 	 * @method contains
       
  1107 	 * @param {VMLShape | HTMLElement} needle The possible node or descendent
       
  1108 	 * @return Boolean Whether or not this shape is the needle or its ancestor.
       
  1109 	 */
       
  1110 	contains: function(needle)
       
  1111 	{
       
  1112 		return needle === Y.one(this.node);
       
  1113 	},
       
  1114 
       
  1115 	/**
       
  1116 	 * Compares nodes to determine if they match.
       
  1117 	 * Node instances can be compared to each other and/or HTMLElements.
       
  1118 	 * @method compareTo
       
  1119 	 * @param {HTMLElement | Node} refNode The reference node to compare to the node.
       
  1120 	 * @return {Boolean} True if the nodes match, false if they do not.
       
  1121 	 */
       
  1122 	compareTo: function(refNode) {
       
  1123         var node = this.node;
       
  1124 		return node === refNode;
       
  1125 	},
       
  1126 
       
  1127 	/**
       
  1128 	 * Test if the supplied node matches the supplied selector.
       
  1129 	 *
       
  1130 	 * @method test
       
  1131 	 * @param {String} selector The CSS selector to test against.
       
  1132 	 * @return Boolean Wheter or not the shape matches the selector.
       
  1133 	 */
       
  1134 	test: function(selector)
       
  1135 	{
       
  1136 		return Y_SELECTOR.test(this.node, selector);
       
  1137 	},
       
  1138 
       
  1139 	/**
       
  1140      * Calculates and returns properties for setting an initial stroke.
       
  1141      *
       
  1142      * @method _getStrokeProps
       
  1143      * @return Object
       
  1144      *
       
  1145 	 * @private
       
  1146 	 */
       
  1147     _getStrokeProps: function()
       
  1148     {
       
  1149 		var props,
       
  1150 			stroke = this.get("stroke"),
       
  1151 			strokeOpacity,
       
  1152 			dashstyle,
       
  1153 			dash = "",
       
  1154 			val,
       
  1155 			i = 0,
       
  1156 			len,
       
  1157 			linecap,
       
  1158 			linejoin;
       
  1159         if(stroke && stroke.weight && stroke.weight > 0)
       
  1160 		{
       
  1161 			props = {};
       
  1162 			linecap = stroke.linecap || "flat";
       
  1163 			linejoin = stroke.linejoin || "round";
       
  1164             if(linecap !== "round" && linecap !== "square")
       
  1165             {
       
  1166                 linecap = "flat";
       
  1167             }
       
  1168 			strokeOpacity = parseFloat(stroke.opacity);
       
  1169 			dashstyle = stroke.dashstyle || "none";
       
  1170 			stroke.color = stroke.color || "#000000";
       
  1171 			stroke.weight = stroke.weight || 1;
       
  1172 			stroke.opacity = IS_NUM(strokeOpacity) ? strokeOpacity : 1;
       
  1173 			props.stroked = true;
       
  1174 			props.color = stroke.color;
       
  1175 			props.weight = stroke.weight;
       
  1176 			props.endcap = linecap;
       
  1177 			props.opacity = stroke.opacity;
       
  1178 			if(IS_ARRAY(dashstyle))
       
  1179 			{
       
  1180 				dash = [];
       
  1181 				len = dashstyle.length;
       
  1182 				for(i = 0; i < len; ++i)
       
  1183 				{
       
  1184 					val = dashstyle[i];
       
  1185 					dash[i] = val / stroke.weight;
       
  1186 				}
       
  1187 			}
       
  1188 			if(linejoin === "round" || linejoin === "bevel")
       
  1189 			{
       
  1190 				props.joinstyle = linejoin;
       
  1191 			}
       
  1192 			else
       
  1193 			{
       
  1194 				linejoin = parseInt(linejoin, 10);
       
  1195 				if(IS_NUM(linejoin))
       
  1196 				{
       
  1197 					props.miterlimit = Math.max(linejoin, 1);
       
  1198 					props.joinstyle = "miter";
       
  1199 				}
       
  1200 			}
       
  1201 			props.dashstyle = dash;
       
  1202         }
       
  1203         return props;
       
  1204     },
       
  1205 
       
  1206 	/**
       
  1207 	 * Adds a stroke to the shape node.
       
  1208 	 *
       
  1209 	 * @method _strokeChangeHandler
       
  1210 	 * @private
       
  1211 	 */
       
  1212 	_strokeChangeHandler: function()
       
  1213 	{
       
  1214         if(!this._strokeFlag)
       
  1215         {
       
  1216             return;
       
  1217         }
       
  1218         var node = this.node,
       
  1219 			stroke = this.get("stroke"),
       
  1220 			strokeOpacity,
       
  1221 			dashstyle,
       
  1222 			dash = "",
       
  1223 			val,
       
  1224 			i = 0,
       
  1225 			len,
       
  1226 			linecap,
       
  1227 			linejoin;
       
  1228 		if(stroke && stroke.weight && stroke.weight > 0)
       
  1229 		{
       
  1230 			linecap = stroke.linecap || "flat";
       
  1231 			linejoin = stroke.linejoin || "round";
       
  1232 			if(linecap !== "round" && linecap !== "square")
       
  1233 			{
       
  1234 				linecap = "flat";
       
  1235 			}
       
  1236 			strokeOpacity = parseFloat(stroke.opacity);
       
  1237 			dashstyle = stroke.dashstyle || "none";
       
  1238 			stroke.color = stroke.color || "#000000";
       
  1239 			stroke.weight = stroke.weight || 1;
       
  1240 			stroke.opacity = IS_NUM(strokeOpacity) ? strokeOpacity : 1;
       
  1241 			node.stroked = true;
       
  1242 			node.strokeColor = stroke.color;
       
  1243 			node.strokeWeight = stroke.weight + "px";
       
  1244 			if(!this._strokeNode)
       
  1245 			{
       
  1246 				this._strokeNode = this._createGraphicNode("stroke");
       
  1247 				node.appendChild(this._strokeNode);
       
  1248 			}
       
  1249 			this._strokeNode.endcap = linecap;
       
  1250 			this._strokeNode.opacity = stroke.opacity;
       
  1251 			if(IS_ARRAY(dashstyle))
       
  1252 			{
       
  1253 				dash = [];
       
  1254 				len = dashstyle.length;
       
  1255 				for(i = 0; i < len; ++i)
       
  1256 				{
       
  1257 					val = dashstyle[i];
       
  1258 					dash[i] = val / stroke.weight;
       
  1259 				}
       
  1260 			}
       
  1261 			if(linejoin === "round" || linejoin === "bevel")
       
  1262 			{
       
  1263 				this._strokeNode.joinstyle = linejoin;
       
  1264 			}
       
  1265 			else
       
  1266 			{
       
  1267 				linejoin = parseInt(linejoin, 10);
       
  1268 				if(IS_NUM(linejoin))
       
  1269 				{
       
  1270 					this._strokeNode.miterlimit = Math.max(linejoin, 1);
       
  1271 					this._strokeNode.joinstyle = "miter";
       
  1272 				}
       
  1273 			}
       
  1274 			this._strokeNode.dashstyle = dash;
       
  1275             this._strokeNode.on = true;
       
  1276 		}
       
  1277 		else
       
  1278 		{
       
  1279             if(this._strokeNode)
       
  1280             {
       
  1281                 this._strokeNode.on = false;
       
  1282             }
       
  1283 			node.stroked = false;
       
  1284 		}
       
  1285         this._strokeFlag = false;
       
  1286 	},
       
  1287 
       
  1288 	/**
       
  1289      * Calculates and returns properties for setting an initial fill.
       
  1290      *
       
  1291      * @method _getFillProps
       
  1292      * @return Object
       
  1293      *
       
  1294 	 * @private
       
  1295 	 */
       
  1296 	_getFillProps: function()
       
  1297 	{
       
  1298 		var fill = this.get("fill"),
       
  1299 			fillOpacity,
       
  1300 			props,
       
  1301 			gradient,
       
  1302 			i,
       
  1303 			fillstring,
       
  1304 			filled = false;
       
  1305 		if(fill)
       
  1306 		{
       
  1307 			props = {};
       
  1308 
       
  1309 			if(fill.type === "radial" || fill.type === "linear")
       
  1310 			{
       
  1311 				fillOpacity = parseFloat(fill.opacity);
       
  1312 				fillOpacity = IS_NUM(fillOpacity) ? fillOpacity : 1;
       
  1313 				filled = true;
       
  1314 				gradient = this._getGradientFill(fill);
       
  1315 				fillstring = '<fill xmlns="urn:schemas-microsft.com:vml"' +
       
  1316                             ' class="vmlfill" style="behavior:url(#default#VML);display:inline-block;"' +
       
  1317                             ' opacity="' + fillOpacity + '"';
       
  1318 				for(i in gradient)
       
  1319 				{
       
  1320 					if(gradient.hasOwnProperty(i))
       
  1321 					{
       
  1322 						fillstring += ' ' + i + '="' + gradient[i] + '"';
       
  1323 					}
       
  1324 				}
       
  1325 				fillstring += ' />';
       
  1326 				props.node = fillstring;
       
  1327 			}
       
  1328 			else if(fill.color)
       
  1329 			{
       
  1330 				fillOpacity = parseFloat(fill.opacity);
       
  1331 				filled = true;
       
  1332                 props.color = fill.color;
       
  1333 				if(IS_NUM(fillOpacity))
       
  1334 				{
       
  1335 					fillOpacity = Math.max(Math.min(fillOpacity, 1), 0);
       
  1336                     props.opacity = fillOpacity;
       
  1337                     if(fillOpacity < 1)
       
  1338                     {
       
  1339                         props.node = '<fill xmlns="urn:schemas-microsft.com:vml"' +
       
  1340                         ' class="vmlfill" style="behavior:url(#default#VML);display:inline-block;"' +
       
  1341                         ' type="solid" opacity="' + fillOpacity + '"/>';
       
  1342                     }
       
  1343                 }
       
  1344 			}
       
  1345 			props.filled = filled;
       
  1346 		}
       
  1347 		return props;
       
  1348 	},
       
  1349 
       
  1350 	/**
       
  1351 	 * Adds a fill to the shape node.
       
  1352 	 *
       
  1353 	 * @method _fillChangeHandler
       
  1354 	 * @private
       
  1355 	 */
       
  1356 	_fillChangeHandler: function()
       
  1357 	{
       
  1358         if(!this._fillFlag)
       
  1359         {
       
  1360             return;
       
  1361         }
       
  1362 		var node = this.node,
       
  1363 			fill = this.get("fill"),
       
  1364 			fillOpacity,
       
  1365 			fillstring,
       
  1366 			filled = false,
       
  1367             i,
       
  1368             gradient;
       
  1369 		if(fill)
       
  1370 		{
       
  1371 			if(fill.type === "radial" || fill.type === "linear")
       
  1372 			{
       
  1373 				filled = true;
       
  1374 				gradient = this._getGradientFill(fill);
       
  1375                 if(this._fillNode)
       
  1376                 {
       
  1377                     for(i in gradient)
       
  1378                     {
       
  1379                         if(gradient.hasOwnProperty(i))
       
  1380                         {
       
  1381                             if(i === "colors")
       
  1382                             {
       
  1383                                 this._fillNode.colors.value = gradient[i];
       
  1384                             }
       
  1385                             else
       
  1386                             {
       
  1387                                 this._fillNode[i] = gradient[i];
       
  1388                             }
       
  1389                         }
       
  1390                     }
       
  1391                 }
       
  1392                 else
       
  1393                 {
       
  1394                     fillstring = '<fill xmlns="urn:schemas-microsft.com:vml"' +
       
  1395                                 ' class="vmlfill"' +
       
  1396                                 ' style="behavior:url(#default#VML);display:inline-block;"';
       
  1397                     for(i in gradient)
       
  1398                     {
       
  1399                         if(gradient.hasOwnProperty(i))
       
  1400                         {
       
  1401                             fillstring += ' ' + i + '="' + gradient[i] + '"';
       
  1402                         }
       
  1403                     }
       
  1404                     fillstring += ' />';
       
  1405                     this._fillNode = DOCUMENT.createElement(fillstring);
       
  1406                     node.appendChild(this._fillNode);
       
  1407                 }
       
  1408 			}
       
  1409 			else if(fill.color)
       
  1410 			{
       
  1411                 node.fillcolor = fill.color;
       
  1412 				fillOpacity = parseFloat(fill.opacity);
       
  1413 				filled = true;
       
  1414 				if(IS_NUM(fillOpacity) && fillOpacity < 1)
       
  1415 				{
       
  1416 					fill.opacity = fillOpacity;
       
  1417                     if(this._fillNode)
       
  1418 					{
       
  1419                         if(this._fillNode.getAttribute("type") !== "solid")
       
  1420                         {
       
  1421                             this._fillNode.type = "solid";
       
  1422                         }
       
  1423 						this._fillNode.opacity = fillOpacity;
       
  1424 					}
       
  1425 					else
       
  1426 					{
       
  1427                         fillstring = '<fill xmlns="urn:schemas-microsft.com:vml"' +
       
  1428                         ' class="vmlfill"' +
       
  1429                         ' style="behavior:url(#default#VML);display:inline-block;"' +
       
  1430                         ' type="solid"' +
       
  1431                         ' opacity="' + fillOpacity + '"' +
       
  1432                         '/>';
       
  1433                         this._fillNode = DOCUMENT.createElement(fillstring);
       
  1434                         node.appendChild(this._fillNode);
       
  1435 					}
       
  1436 				}
       
  1437 				else if(this._fillNode)
       
  1438                 {
       
  1439                     this._fillNode.opacity = 1;
       
  1440                     this._fillNode.type = "solid";
       
  1441 				}
       
  1442 			}
       
  1443 		}
       
  1444 		node.filled = filled;
       
  1445         this._fillFlag = false;
       
  1446 	},
       
  1447 
       
  1448 	//not used. remove next release.
       
  1449     _updateFillNode: function(node)
       
  1450 	{
       
  1451 		if(!this._fillNode)
       
  1452 		{
       
  1453 			this._fillNode = this._createGraphicNode("fill");
       
  1454 			node.appendChild(this._fillNode);
       
  1455 		}
       
  1456 	},
       
  1457 
       
  1458     /**
       
  1459      * Calculates and returns an object containing gradient properties for a fill node.
       
  1460      *
       
  1461      * @method _getGradientFill
       
  1462      * @param {Object} fill Object containing fill properties.
       
  1463      * @return Object
       
  1464      * @private
       
  1465      */
       
  1466 	_getGradientFill: function(fill)
       
  1467 	{
       
  1468 		var gradientProps = {},
       
  1469 			gradientBoxWidth,
       
  1470 			gradientBoxHeight,
       
  1471 			type = fill.type,
       
  1472 			w = this.get("width"),
       
  1473 			h = this.get("height"),
       
  1474 			isNumber = IS_NUM,
       
  1475 			stop,
       
  1476 			stops = fill.stops,
       
  1477 			len = stops.length,
       
  1478 			opacity,
       
  1479 			color,
       
  1480 			i,
       
  1481 			oi,
       
  1482 			colorstring = "",
       
  1483 			cx = fill.cx,
       
  1484 			cy = fill.cy,
       
  1485 			fx = fill.fx,
       
  1486 			fy = fill.fy,
       
  1487 			r = fill.r,
       
  1488             pct,
       
  1489 			rotation = fill.rotation || 0;
       
  1490 		if(type === "linear")
       
  1491 		{
       
  1492             if(rotation <= 270)
       
  1493             {
       
  1494                 rotation = Math.abs(rotation - 270);
       
  1495             }
       
  1496 			else if(rotation < 360)
       
  1497             {
       
  1498                 rotation = 270 + (360 - rotation);
       
  1499             }
       
  1500             else
       
  1501             {
       
  1502                 rotation = 270;
       
  1503             }
       
  1504             gradientProps.type = "gradient";//"gradientunscaled";
       
  1505 			gradientProps.angle = rotation;
       
  1506 		}
       
  1507 		else if(type === "radial")
       
  1508 		{
       
  1509 			gradientBoxWidth = w * (r * 2);
       
  1510 			gradientBoxHeight = h * (r * 2);
       
  1511 			fx = r * 2 * (fx - 0.5);
       
  1512 			fy = r * 2 * (fy - 0.5);
       
  1513 			fx += cx;
       
  1514 			fy += cy;
       
  1515 			gradientProps.focussize = (gradientBoxWidth/w)/10 + "% " + (gradientBoxHeight/h)/10 + "%";
       
  1516 			gradientProps.alignshape = false;
       
  1517 			gradientProps.type = "gradientradial";
       
  1518 			gradientProps.focus = "100%";
       
  1519 			gradientProps.focusposition = Math.round(fx * 100) + "% " + Math.round(fy * 100) + "%";
       
  1520 		}
       
  1521 		for(i = 0;i < len; ++i) {
       
  1522 			stop = stops[i];
       
  1523 			color = stop.color;
       
  1524 			opacity = stop.opacity;
       
  1525 			opacity = isNumber(opacity) ? opacity : 1;
       
  1526 			pct = stop.offset || i/(len-1);
       
  1527 			pct *= (r * 2);
       
  1528             pct = Math.round(100 * pct) + "%";
       
  1529             oi = i > 0 ? i + 1 : "";
       
  1530             gradientProps["opacity" + oi] = opacity + "";
       
  1531             colorstring += ", " + pct + " " + color;
       
  1532 		}
       
  1533 		if(parseFloat(pct) < 100)
       
  1534 		{
       
  1535 			colorstring += ", 100% " + color;
       
  1536 		}
       
  1537 		gradientProps.colors = colorstring.substr(2);
       
  1538 		return gradientProps;
       
  1539 	},
       
  1540 
       
  1541     /**
       
  1542      * Adds a transform to the shape.
       
  1543      *
       
  1544      * @method _addTransform
       
  1545      * @param {String} type The transform being applied.
       
  1546      * @param {Array} args The arguments for the transform.
       
  1547 	 * @private
       
  1548 	 */
       
  1549 	_addTransform: function(type, args)
       
  1550 	{
       
  1551         args = Y.Array(args);
       
  1552         this._transform = Y_LANG.trim(this._transform + " " + type + "(" + args.join(", ") + ")");
       
  1553         args.unshift(type);
       
  1554         this._transforms.push(args);
       
  1555         if(this.initialized)
       
  1556         {
       
  1557             this._updateTransform();
       
  1558         }
       
  1559 	},
       
  1560 
       
  1561 	/**
       
  1562      * Applies all transforms.
       
  1563      *
       
  1564      * @method _updateTransform
       
  1565 	 * @private
       
  1566 	 */
       
  1567 	_updateTransform: function()
       
  1568 	{
       
  1569 		var node = this.node,
       
  1570             key,
       
  1571 			transform,
       
  1572 			transformOrigin,
       
  1573             x = this.get("x"),
       
  1574             y = this.get("y"),
       
  1575             tx,
       
  1576             ty,
       
  1577             matrix = this.matrix,
       
  1578             normalizedMatrix = this._normalizedMatrix,
       
  1579             isPathShape = this instanceof Y.VMLPath,
       
  1580             i,
       
  1581             len = this._transforms.length;
       
  1582         if(this._transforms && this._transforms.length > 0)
       
  1583 		{
       
  1584             transformOrigin = this.get("transformOrigin");
       
  1585 
       
  1586             if(isPathShape)
       
  1587             {
       
  1588                 normalizedMatrix.translate(this._left, this._top);
       
  1589             }
       
  1590             //vml skew matrix transformOrigin ranges from -0.5 to 0.5.
       
  1591             //subtract 0.5 from values
       
  1592             tx = transformOrigin[0] - 0.5;
       
  1593             ty = transformOrigin[1] - 0.5;
       
  1594 
       
  1595             //ensure the values are within the appropriate range to avoid errors
       
  1596             tx = Math.max(-0.5, Math.min(0.5, tx));
       
  1597             ty = Math.max(-0.5, Math.min(0.5, ty));
       
  1598             for(i = 0; i < len; ++i)
       
  1599             {
       
  1600                 key = this._transforms[i].shift();
       
  1601                 if(key)
       
  1602                 {
       
  1603                     normalizedMatrix[key].apply(normalizedMatrix, this._transforms[i]);
       
  1604                     matrix[key].apply(matrix, this._transforms[i]);
       
  1605                 }
       
  1606 			}
       
  1607             if(isPathShape)
       
  1608             {
       
  1609                 normalizedMatrix.translate(-this._left, -this._top);
       
  1610             }
       
  1611             transform = normalizedMatrix.a + "," +
       
  1612                         normalizedMatrix.c + "," +
       
  1613                         normalizedMatrix.b + "," +
       
  1614                         normalizedMatrix.d + "," +
       
  1615                         0 + "," +
       
  1616                         0;
       
  1617 		}
       
  1618         this._graphic.addToRedrawQueue(this);
       
  1619         if(transform)
       
  1620         {
       
  1621             if(!this._skew)
       
  1622             {
       
  1623                 this._skew = DOCUMENT.createElement(
       
  1624                     '<skew class="vmlskew"' +
       
  1625                     ' xmlns="urn:schemas-microsft.com:vml"' +
       
  1626                     ' on="false"' +
       
  1627                     ' style="behavior:url(#default#VML);display:inline-block;"' +
       
  1628                     '/>'
       
  1629                 );
       
  1630                 this.node.appendChild(this._skew);
       
  1631             }
       
  1632             this._skew.matrix = transform;
       
  1633             this._skew.on = true;
       
  1634             //this._skew.offset = this._getSkewOffsetValue(normalizedMatrix.dx) + "px, " + this._getSkewOffsetValue(normalizedMatrix.dy) + "px";
       
  1635             this._skew.origin = tx + ", " + ty;
       
  1636         }
       
  1637         if(this._type !== "path")
       
  1638         {
       
  1639             this._transforms = [];
       
  1640         }
       
  1641         //add the translate to the x and y coordinates
       
  1642         node.style.left = (x + this._getSkewOffsetValue(normalizedMatrix.dx)) + "px";
       
  1643         node.style.top =  (y + this._getSkewOffsetValue(normalizedMatrix.dy)) + "px";
       
  1644     },
       
  1645 
       
  1646     /**
       
  1647      * Normalizes the skew offset values between -32767 and 32767.
       
  1648      *
       
  1649      * @method _getSkewOffsetValue
       
  1650      * @param {Number} val The value to normalize
       
  1651      * @return Number
       
  1652      * @private
       
  1653      */
       
  1654     _getSkewOffsetValue: function(val)
       
  1655     {
       
  1656         var sign = Y.MatrixUtil.sign(val),
       
  1657             absVal = Math.abs(val);
       
  1658         val = Math.min(absVal, 32767) * sign;
       
  1659         return val;
       
  1660     },
       
  1661 
       
  1662 	/**
       
  1663 	 * Storage for translateX
       
  1664 	 *
       
  1665      * @property _translateX
       
  1666      * @type Number
       
  1667 	 * @private
       
  1668 	 */
       
  1669 	_translateX: 0,
       
  1670 
       
  1671 	/**
       
  1672 	 * Storage for translateY
       
  1673 	 *
       
  1674      * @property _translateY
       
  1675      * @type Number
       
  1676 	 * @private
       
  1677 	 */
       
  1678 	_translateY: 0,
       
  1679 
       
  1680     /**
       
  1681      * Storage for the transform attribute.
       
  1682      *
       
  1683      * @property _transform
       
  1684      * @type String
       
  1685      * @private
       
  1686      */
       
  1687     _transform: "",
       
  1688 
       
  1689     /**
       
  1690 	 * Specifies a 2d translation.
       
  1691 	 *
       
  1692 	 * @method translate
       
  1693 	 * @param {Number} x The value to translate on the x-axis.
       
  1694 	 * @param {Number} y The value to translate on the y-axis.
       
  1695 	 */
       
  1696 	translate: function(x, y)
       
  1697 	{
       
  1698 		this._translateX += x;
       
  1699 		this._translateY += y;
       
  1700 		this._addTransform("translate", arguments);
       
  1701 	},
       
  1702 
       
  1703 	/**
       
  1704 	 * Translates the shape along the x-axis. When translating x and y coordinates,
       
  1705 	 * use the `translate` method.
       
  1706 	 *
       
  1707 	 * @method translateX
       
  1708 	 * @param {Number} x The value to translate.
       
  1709 	 */
       
  1710 	translateX: function(x)
       
  1711     {
       
  1712         this._translateX += x;
       
  1713         this._addTransform("translateX", arguments);
       
  1714     },
       
  1715 
       
  1716 	/**
       
  1717 	 * Performs a translate on the y-coordinate. When translating x and y coordinates,
       
  1718 	 * use the `translate` method.
       
  1719 	 *
       
  1720 	 * @method translateY
       
  1721 	 * @param {Number} y The value to translate.
       
  1722 	 */
       
  1723 	translateY: function(y)
       
  1724     {
       
  1725         this._translateY += y;
       
  1726         this._addTransform("translateY", arguments);
       
  1727     },
       
  1728 
       
  1729     /**
       
  1730      * Skews the shape around the x-axis and y-axis.
       
  1731      *
       
  1732      * @method skew
       
  1733      * @param {Number} x The value to skew on the x-axis.
       
  1734      * @param {Number} y The value to skew on the y-axis.
       
  1735      */
       
  1736     skew: function()
       
  1737     {
       
  1738         this._addTransform("skew", arguments);
       
  1739     },
       
  1740 
       
  1741 	/**
       
  1742 	 * Skews the shape around the x-axis.
       
  1743 	 *
       
  1744 	 * @method skewX
       
  1745 	 * @param {Number} x x-coordinate
       
  1746 	 */
       
  1747      skewX: function()
       
  1748      {
       
  1749         this._addTransform("skewX", arguments);
       
  1750      },
       
  1751 
       
  1752 	/**
       
  1753 	 * Skews the shape around the y-axis.
       
  1754 	 *
       
  1755 	 * @method skewY
       
  1756 	 * @param {Number} y y-coordinate
       
  1757 	 */
       
  1758      skewY: function()
       
  1759      {
       
  1760         this._addTransform("skewY", arguments);
       
  1761      },
       
  1762 
       
  1763 	/**
       
  1764 	 * Rotates the shape clockwise around it transformOrigin.
       
  1765 	 *
       
  1766 	 * @method rotate
       
  1767 	 * @param {Number} deg The degree of the rotation.
       
  1768 	 */
       
  1769      rotate: function()
       
  1770      {
       
  1771         this._addTransform("rotate", arguments);
       
  1772      },
       
  1773 
       
  1774 	/**
       
  1775 	 * Specifies a 2d scaling operation.
       
  1776 	 *
       
  1777 	 * @method scale
       
  1778 	 * @param {Number} val
       
  1779 	 */
       
  1780     scale: function()
       
  1781     {
       
  1782         this._addTransform("scale", arguments);
       
  1783     },
       
  1784 
       
  1785 	/**
       
  1786      * Overrides default `on` method. Checks to see if its a dom interaction event. If so,
       
  1787      * return an event attached to the `node` element. If not, return the normal functionality.
       
  1788      *
       
  1789      * @method on
       
  1790      * @param {String} type event type
       
  1791      * @param {Object} callback function
       
  1792 	 * @private
       
  1793 	 */
       
  1794 	on: function(type, fn)
       
  1795 	{
       
  1796 		if(Y.Node.DOM_EVENTS[type])
       
  1797 		{
       
  1798 			return Y.one("#" +  this.get("id")).on(type, fn);
       
  1799 		}
       
  1800 		return Y.on.apply(this, arguments);
       
  1801 	},
       
  1802 
       
  1803 	/**
       
  1804 	 * Draws the shape.
       
  1805 	 *
       
  1806 	 * @method _draw
       
  1807 	 * @private
       
  1808 	 */
       
  1809 	_draw: function()
       
  1810 	{
       
  1811 	},
       
  1812 
       
  1813 	/**
       
  1814      * Updates `Shape` based on attribute changes.
       
  1815      *
       
  1816      * @method _updateHandler
       
  1817 	 * @private
       
  1818 	 */
       
  1819 	_updateHandler: function()
       
  1820 	{
       
  1821 		var host = this,
       
  1822             node = host.node;
       
  1823         host._fillChangeHandler();
       
  1824         host._strokeChangeHandler();
       
  1825         node.style.width = this.get("width") + "px";
       
  1826         node.style.height = this.get("height") + "px";
       
  1827         this._draw();
       
  1828 		host._updateTransform();
       
  1829 	},
       
  1830 
       
  1831 	/**
       
  1832 	 * Creates a graphic node
       
  1833 	 *
       
  1834 	 * @method _createGraphicNode
       
  1835 	 * @param {String} type node type to create
       
  1836 	 * @return HTMLElement
       
  1837 	 * @private
       
  1838 	 */
       
  1839 	_createGraphicNode: function(type)
       
  1840 	{
       
  1841 		type = type || this._type;
       
  1842 		return DOCUMENT.createElement(
       
  1843                 '<' + type +
       
  1844                 ' xmlns="urn:schemas-microsft.com:vml"' +
       
  1845                 ' style="behavior:url(#default#VML);display:inline-block;"' +
       
  1846                 ' class="vml' + type + '"' +
       
  1847                 '/>'
       
  1848             );
       
  1849 	},
       
  1850 
       
  1851 	/**
       
  1852 	 * Value function for fill attribute
       
  1853 	 *
       
  1854 	 * @private
       
  1855 	 * @method _getDefaultFill
       
  1856 	 * @return Object
       
  1857 	 */
       
  1858 	_getDefaultFill: function() {
       
  1859 		return {
       
  1860 			type: "solid",
       
  1861 			opacity: 1,
       
  1862 			cx: 0.5,
       
  1863 			cy: 0.5,
       
  1864 			fx: 0.5,
       
  1865 			fy: 0.5,
       
  1866 			r: 0.5
       
  1867 		};
       
  1868 	},
       
  1869 
       
  1870 	/**
       
  1871 	 * Value function for stroke attribute
       
  1872 	 *
       
  1873 	 * @private
       
  1874 	 * @method _getDefaultStroke
       
  1875 	 * @return Object
       
  1876 	 */
       
  1877 	_getDefaultStroke: function()
       
  1878 	{
       
  1879 		return {
       
  1880 			weight: 1,
       
  1881 			dashstyle: "none",
       
  1882 			color: "#000",
       
  1883 			opacity: 1.0
       
  1884 		};
       
  1885 	},
       
  1886 
       
  1887     /**
       
  1888      * Sets the value of an attribute.
       
  1889      *
       
  1890      * @method set
       
  1891      * @param {String|Object} name The name of the attribute. Alternatively, an object of key value pairs can
       
  1892      * be passed in to set multiple attributes at once.
       
  1893      * @param {Any} value The value to set the attribute to. This value is ignored if an object is received as
       
  1894      * the name param.
       
  1895      */
       
  1896 	set: function()
       
  1897 	{
       
  1898 		var host = this;
       
  1899 		AttributeLite.prototype.set.apply(host, arguments);
       
  1900 		if(host.initialized)
       
  1901 		{
       
  1902 			host._updateHandler();
       
  1903 		}
       
  1904 	},
       
  1905 
       
  1906 	/**
       
  1907 	 * Returns the bounds for a shape.
       
  1908 	 *
       
  1909      * Calculates the a new bounding box from the original corner coordinates (base on size and position) and the transform matrix.
       
  1910      * The calculated bounding box is used by the graphic instance to calculate its viewBox.
       
  1911      *
       
  1912 	 * @method getBounds
       
  1913 	 * @return Object
       
  1914 	 */
       
  1915 	getBounds: function()
       
  1916 	{
       
  1917 		var isPathShape = this instanceof Y.VMLPath,
       
  1918 			w = this.get("width"),
       
  1919 			h = this.get("height"),
       
  1920             x = this.get("x"),
       
  1921             y = this.get("y");
       
  1922         if(isPathShape)
       
  1923         {
       
  1924             x = x + this._left;
       
  1925             y = y + this._top;
       
  1926             w = this._right - this._left;
       
  1927             h = this._bottom - this._top;
       
  1928         }
       
  1929         return this._getContentRect(w, h, x, y);
       
  1930 	},
       
  1931 
       
  1932     /**
       
  1933      * Calculates the bounding box for the shape.
       
  1934      *
       
  1935      * @method _getContentRect
       
  1936      * @param {Number} w width of the shape
       
  1937      * @param {Number} h height of the shape
       
  1938      * @param {Number} x x-coordinate of the shape
       
  1939      * @param {Number} y y-coordinate of the shape
       
  1940      * @private
       
  1941      */
       
  1942     _getContentRect: function(w, h, x, y)
       
  1943     {
       
  1944         var transformOrigin = this.get("transformOrigin"),
       
  1945             transformX = transformOrigin[0] * w,
       
  1946             transformY = transformOrigin[1] * h,
       
  1947             transforms = this.matrix.getTransformArray(this.get("transform")),
       
  1948             matrix = new Y.Matrix(),
       
  1949             i,
       
  1950             len = transforms.length,
       
  1951             transform,
       
  1952             key,
       
  1953             contentRect,
       
  1954             isPathShape = this instanceof Y.VMLPath;
       
  1955         if(isPathShape)
       
  1956         {
       
  1957             matrix.translate(this._left, this._top);
       
  1958         }
       
  1959         transformX = !isNaN(transformX) ? transformX : 0;
       
  1960         transformY = !isNaN(transformY) ? transformY : 0;
       
  1961         matrix.translate(transformX, transformY);
       
  1962         for(i = 0; i < len; i = i + 1)
       
  1963         {
       
  1964             transform = transforms[i];
       
  1965             key = transform.shift();
       
  1966             if(key)
       
  1967             {
       
  1968                 matrix[key].apply(matrix, transform);
       
  1969             }
       
  1970         }
       
  1971         matrix.translate(-transformX, -transformY);
       
  1972         if(isPathShape)
       
  1973         {
       
  1974             matrix.translate(-this._left, -this._top);
       
  1975         }
       
  1976         contentRect = matrix.getContentRect(w, h, x, y);
       
  1977         return contentRect;
       
  1978     },
       
  1979 
       
  1980     /**
       
  1981      * Places the shape above all other shapes.
       
  1982      *
       
  1983      * @method toFront
       
  1984      */
       
  1985     toFront: function()
       
  1986     {
       
  1987         var graphic = this.get("graphic");
       
  1988         if(graphic)
       
  1989         {
       
  1990             graphic._toFront(this);
       
  1991         }
       
  1992     },
       
  1993 
       
  1994     /**
       
  1995      * Places the shape underneath all other shapes.
       
  1996      *
       
  1997      * @method toFront
       
  1998      */
       
  1999     toBack: function()
       
  2000     {
       
  2001         var graphic = this.get("graphic");
       
  2002         if(graphic)
       
  2003         {
       
  2004             graphic._toBack(this);
       
  2005         }
       
  2006     },
       
  2007 
       
  2008     /**
       
  2009      * Parses path data string and call mapped methods.
       
  2010      *
       
  2011      * @method _parsePathData
       
  2012      * @param {String} val The path data
       
  2013      * @private
       
  2014      */
       
  2015     _parsePathData: function(val)
       
  2016     {
       
  2017         var method,
       
  2018             methodSymbol,
       
  2019             args,
       
  2020             commandArray = Y.Lang.trim(val.match(SPLITPATHPATTERN)),
       
  2021             i,
       
  2022             len,
       
  2023             str,
       
  2024             symbolToMethod = this._pathSymbolToMethod;
       
  2025         if(commandArray)
       
  2026         {
       
  2027             this.clear();
       
  2028             len = commandArray.length || 0;
       
  2029             for(i = 0; i < len; i = i + 1)
       
  2030             {
       
  2031                 str = commandArray[i];
       
  2032                 methodSymbol = str.substr(0, 1);
       
  2033                 args = str.substr(1).match(SPLITARGSPATTERN);
       
  2034                 method = symbolToMethod[methodSymbol];
       
  2035                 if(method)
       
  2036                 {
       
  2037                     if(args)
       
  2038                     {
       
  2039                         this[method].apply(this, args);
       
  2040                     }
       
  2041                     else
       
  2042                     {
       
  2043                         this[method].apply(this);
       
  2044                     }
       
  2045                 }
       
  2046             }
       
  2047             this.end();
       
  2048         }
       
  2049     },
       
  2050 
       
  2051     /**
       
  2052      *  Destroys shape
       
  2053      *
       
  2054      *  @method destroy
       
  2055      */
       
  2056     destroy: function()
       
  2057     {
       
  2058         var graphic = this.get("graphic");
       
  2059         if(graphic)
       
  2060         {
       
  2061             graphic.removeShape(this);
       
  2062         }
       
  2063         else
       
  2064         {
       
  2065             this._destroy();
       
  2066         }
       
  2067     },
       
  2068 
       
  2069     /**
       
  2070      *  Implementation for shape destruction
       
  2071      *
       
  2072      *  @method destroy
       
  2073      *  @protected
       
  2074      */
       
  2075     _destroy: function()
       
  2076     {
       
  2077         if(this.node)
       
  2078         {
       
  2079             if(this._fillNode)
       
  2080             {
       
  2081                 this.node.removeChild(this._fillNode);
       
  2082                 this._fillNode = null;
       
  2083             }
       
  2084             if(this._strokeNode)
       
  2085             {
       
  2086                 this.node.removeChild(this._strokeNode);
       
  2087                 this._strokeNode = null;
       
  2088             }
       
  2089             Y.one(this.node).remove(true);
       
  2090         }
       
  2091     }
       
  2092 }, Y.VMLDrawing.prototype));
       
  2093 
       
  2094 VMLShape.ATTRS = {
       
  2095 	/**
       
  2096 	 * An array of x, y values which indicates the transformOrigin in which to rotate the shape. Valid values range between 0 and 1 representing a
       
  2097 	 * fraction of the shape's corresponding bounding box dimension. The default value is [0.5, 0.5].
       
  2098 	 *
       
  2099 	 * @config transformOrigin
       
  2100 	 * @type Array
       
  2101 	 */
       
  2102 	transformOrigin: {
       
  2103 		valueFn: function()
       
  2104 		{
       
  2105 			return [0.5, 0.5];
       
  2106 		}
       
  2107 	},
       
  2108 
       
  2109     /**
       
  2110      * <p>A string containing, in order, transform operations applied to the shape instance. The `transform` string can contain the following values:
       
  2111      *
       
  2112      *    <dl>
       
  2113      *        <dt>rotate</dt><dd>Rotates the shape clockwise around it transformOrigin.</dd>
       
  2114      *        <dt>translate</dt><dd>Specifies a 2d translation.</dd>
       
  2115      *        <dt>skew</dt><dd>Skews the shape around the x-axis and y-axis.</dd>
       
  2116      *        <dt>scale</dt><dd>Specifies a 2d scaling operation.</dd>
       
  2117      *        <dt>translateX</dt><dd>Translates the shape along the x-axis.</dd>
       
  2118      *        <dt>translateY</dt><dd>Translates the shape along the y-axis.</dd>
       
  2119      *        <dt>skewX</dt><dd>Skews the shape around the x-axis.</dd>
       
  2120      *        <dt>skewY</dt><dd>Skews the shape around the y-axis.</dd>
       
  2121      *        <dt>matrix</dt><dd>Specifies a 2D transformation matrix comprised of the specified six values.</dd>
       
  2122      *    </dl>
       
  2123      * </p>
       
  2124      * <p>Applying transforms through the transform attribute will reset the transform matrix and apply a new transform. The shape class also contains
       
  2125      * corresponding methods for each transform that will apply the transform to the current matrix. The below code illustrates how you might use the
       
  2126      * `transform` attribute to instantiate a recangle with a rotation of 45 degrees.</p>
       
  2127             var myRect = new Y.Rect({
       
  2128                 type:"rect",
       
  2129                 width: 50,
       
  2130                 height: 40,
       
  2131                 transform: "rotate(45)"
       
  2132             };
       
  2133      * <p>The code below would apply `translate` and `rotate` to an existing shape.</p>
       
  2134 
       
  2135         myRect.set("transform", "translate(40, 50) rotate(45)");
       
  2136 	 * @config transform
       
  2137      * @type String
       
  2138 	 */
       
  2139 	transform: {
       
  2140 		setter: function(val)
       
  2141 		{
       
  2142             var i,
       
  2143                 len,
       
  2144                 transform;
       
  2145             this.matrix.init();
       
  2146             this._normalizedMatrix.init();
       
  2147             this._transforms = this.matrix.getTransformArray(val);
       
  2148             len = this._transforms.length;
       
  2149             for(i = 0;i < len; ++i)
       
  2150             {
       
  2151                 transform = this._transforms[i];
       
  2152             }
       
  2153             this._transform = val;
       
  2154             return val;
       
  2155 		},
       
  2156 
       
  2157         getter: function()
       
  2158         {
       
  2159             return this._transform;
       
  2160         }
       
  2161 	},
       
  2162 
       
  2163 	/**
       
  2164 	 * Indicates the x position of shape.
       
  2165 	 *
       
  2166 	 * @config x
       
  2167 	 * @type Number
       
  2168 	 */
       
  2169 	x: {
       
  2170 		value: 0
       
  2171 	},
       
  2172 
       
  2173 	/**
       
  2174 	 * Indicates the y position of shape.
       
  2175 	 *
       
  2176 	 * @config y
       
  2177 	 * @type Number
       
  2178 	 */
       
  2179 	y: {
       
  2180 		value: 0
       
  2181 	},
       
  2182 
       
  2183 	/**
       
  2184 	 * Unique id for class instance.
       
  2185 	 *
       
  2186 	 * @config id
       
  2187 	 * @type String
       
  2188 	 */
       
  2189 	id: {
       
  2190 		valueFn: function()
       
  2191 		{
       
  2192 			return Y.guid();
       
  2193 		},
       
  2194 
       
  2195 		setter: function(val)
       
  2196 		{
       
  2197 			var node = this.node;
       
  2198 			if(node)
       
  2199 			{
       
  2200 				node.setAttribute("id", val);
       
  2201 			}
       
  2202 			return val;
       
  2203 		}
       
  2204 	},
       
  2205 
       
  2206 	/**
       
  2207 	 *
       
  2208 	 * @config width
       
  2209 	 */
       
  2210 	width: {
       
  2211 		value: 0
       
  2212 	},
       
  2213 
       
  2214 	/**
       
  2215 	 *
       
  2216 	 * @config height
       
  2217 	 */
       
  2218 	height: {
       
  2219 		value: 0
       
  2220 	},
       
  2221 
       
  2222 	/**
       
  2223 	 * Indicates whether the shape is visible.
       
  2224 	 *
       
  2225 	 * @config visible
       
  2226 	 * @type Boolean
       
  2227 	 */
       
  2228 	visible: {
       
  2229 		value: true,
       
  2230 
       
  2231 		setter: function(val){
       
  2232 			var node = this.node,
       
  2233 				visibility = val ? "visible" : "hidden";
       
  2234 			if(node)
       
  2235 			{
       
  2236 				node.style.visibility = visibility;
       
  2237 			}
       
  2238 			return val;
       
  2239 		}
       
  2240 	},
       
  2241 
       
  2242 	/**
       
  2243 	 * Contains information about the fill of the shape.
       
  2244      *  <dl>
       
  2245      *      <dt>color</dt><dd>The color of the fill.</dd>
       
  2246      *      <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the fill. The default value is 1.</dd>
       
  2247      *      <dt>type</dt><dd>Type of fill.
       
  2248      *          <dl>
       
  2249      *              <dt>solid</dt><dd>Solid single color fill. (default)</dd>
       
  2250      *              <dt>linear</dt><dd>Linear gradient fill.</dd>
       
  2251      *              <dt>radial</dt><dd>Radial gradient fill.</dd>
       
  2252      *          </dl>
       
  2253      *      </dd>
       
  2254      *  </dl>
       
  2255      *  <p>If a `linear` or `radial` is specified as the fill type. The following additional property is used:
       
  2256      *  <dl>
       
  2257      *      <dt>stops</dt><dd>An array of objects containing the following properties:
       
  2258      *          <dl>
       
  2259      *              <dt>color</dt><dd>The color of the stop.</dd>
       
  2260      *              <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the stop. The default value is 1.
       
  2261      *              Note: No effect for IE 6 - 8</dd>
       
  2262      *              <dt>offset</dt><dd>Number between 0 and 1 indicating where the color stop is positioned.</dd>
       
  2263      *          </dl>
       
  2264      *      </dd>
       
  2265      *      <p>Linear gradients also have the following property:</p>
       
  2266      *      <dt>rotation</dt><dd>Linear gradients flow left to right by default. The rotation property allows you to change the
       
  2267      *      flow by rotation. (e.g. A rotation of 180 would make the gradient pain from right to left.)</dd>
       
  2268      *      <p>Radial gradients have the following additional properties:</p>
       
  2269      *      <dt>r</dt><dd>Radius of the gradient circle.</dd>
       
  2270      *      <dt>fx</dt><dd>Focal point x-coordinate of the gradient.</dd>
       
  2271      *      <dt>fy</dt><dd>Focal point y-coordinate of the gradient.</dd>
       
  2272      *  </dl>
       
  2273      *  <p>The corresponding `SVGShape` class implements the following additional properties.</p>
       
  2274      *  <dl>
       
  2275      *      <dt>cx</dt><dd>
       
  2276      *          <p>The x-coordinate of the center of the gradient circle. Determines where the color stop begins. The default value 0.5.</p>
       
  2277      *          <p><strong>Note: </strong>Currently, this property is not implemented for corresponding `CanvasShape` and
       
  2278      *          `VMLShape` classes which are used on Android or IE 6 - 8.</p>
       
  2279      *      </dd>
       
  2280      *      <dt>cy</dt><dd>
       
  2281      *          <p>The y-coordinate of the center of the gradient circle. Determines where the color stop begins. The default value 0.5.</p>
       
  2282      *          <p><strong>Note: </strong>Currently, this property is not implemented for corresponding `CanvasShape` and `VMLShape`
       
  2283      *          classes which are used on Android or IE 6 - 8.</p>
       
  2284      *      </dd>
       
  2285      *  </dl>
       
  2286      *  <p>These properties are not currently implemented in `CanvasShape` or `VMLShape`.</p>
       
  2287 	 *
       
  2288 	 * @config fill
       
  2289 	 * @type Object
       
  2290 	 */
       
  2291 	fill: {
       
  2292 		valueFn: "_getDefaultFill",
       
  2293 
       
  2294 		setter: function(val)
       
  2295 		{
       
  2296 			var i,
       
  2297 				fill,
       
  2298 				tmpl = this.get("fill") || this._getDefaultFill();
       
  2299 
       
  2300 			if(val)
       
  2301 			{
       
  2302 				//ensure, fill type is solid if color is explicitly passed.
       
  2303 				if(val.hasOwnProperty("color"))
       
  2304 				{
       
  2305 					val.type = "solid";
       
  2306 				}
       
  2307 				for(i in val)
       
  2308 				{
       
  2309 					if(val.hasOwnProperty(i))
       
  2310 					{
       
  2311 						tmpl[i] = val[i];
       
  2312 					}
       
  2313 				}
       
  2314 			}
       
  2315 			fill = tmpl;
       
  2316 			if(fill && fill.color)
       
  2317 			{
       
  2318 				if(fill.color === undefined || fill.color === "none")
       
  2319 				{
       
  2320 					fill.color = null;
       
  2321 				}
       
  2322 			}
       
  2323 			this._fillFlag = true;
       
  2324             return fill;
       
  2325 		}
       
  2326 	},
       
  2327 
       
  2328 	/**
       
  2329 	 * Contains information about the stroke of the shape.
       
  2330      *  <dl>
       
  2331      *      <dt>color</dt><dd>The color of the stroke.</dd>
       
  2332      *      <dt>weight</dt><dd>Number that indicates the width of the stroke.</dd>
       
  2333      *      <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the stroke. The default value is 1.</dd>
       
  2334      *      <dt>dashstyle</dt>Indicates whether to draw a dashed stroke. When set to "none", a solid stroke is drawn. When set
       
  2335      *      to an array, the first index indicates the length of the dash. The second index indicates the length of gap.
       
  2336      *      <dt>linecap</dt><dd>Specifies the linecap for the stroke. The following values can be specified:
       
  2337      *          <dl>
       
  2338      *              <dt>butt (default)</dt><dd>Specifies a butt linecap.</dd>
       
  2339      *              <dt>square</dt><dd>Specifies a sqare linecap.</dd>
       
  2340      *              <dt>round</dt><dd>Specifies a round linecap.</dd>
       
  2341      *          </dl>
       
  2342      *      </dd>
       
  2343      *      <dt>linejoin</dt><dd>Specifies a linejoin for the stroke. The following values can be specified:
       
  2344      *          <dl>
       
  2345      *              <dt>round (default)</dt><dd>Specifies that the linejoin will be round.</dd>
       
  2346      *              <dt>bevel</dt><dd>Specifies a bevel for the linejoin.</dd>
       
  2347      *              <dt>miter limit</dt><dd>An integer specifying the miter limit of a miter linejoin. If you want to specify a linejoin
       
  2348      *              of miter, you simply specify the limit as opposed to having separate miter and miter limit values.</dd>
       
  2349      *          </dl>
       
  2350      *      </dd>
       
  2351      *  </dl>
       
  2352 	 *
       
  2353 	 * @config stroke
       
  2354 	 * @type Object
       
  2355 	 */
       
  2356 	stroke: {
       
  2357 		valueFn: "_getDefaultStroke",
       
  2358 
       
  2359 		setter: function(val)
       
  2360 		{
       
  2361 			var i,
       
  2362 				stroke,
       
  2363                 wt,
       
  2364 				tmpl = this.get("stroke") || this._getDefaultStroke();
       
  2365 			if(val)
       
  2366 			{
       
  2367                 if(val.hasOwnProperty("weight"))
       
  2368                 {
       
  2369                     wt = parseInt(val.weight, 10);
       
  2370                     if(!isNaN(wt))
       
  2371                     {
       
  2372                         val.weight = wt;
       
  2373                     }
       
  2374                 }
       
  2375 				for(i in val)
       
  2376 				{
       
  2377 					if(val.hasOwnProperty(i))
       
  2378 					{
       
  2379 						tmpl[i] = val[i];
       
  2380 					}
       
  2381 				}
       
  2382 			}
       
  2383 			stroke = tmpl;
       
  2384             this._strokeFlag = true;
       
  2385 			return stroke;
       
  2386 		}
       
  2387 	},
       
  2388 
       
  2389 	//Not used. Remove in future.
       
  2390     autoSize: {
       
  2391 		value: false
       
  2392 	},
       
  2393 
       
  2394 	// Only implemented in SVG
       
  2395 	// Determines whether the instance will receive mouse events.
       
  2396 	//
       
  2397 	// @config pointerEvents
       
  2398 	// @type string
       
  2399 	//
       
  2400 	pointerEvents: {
       
  2401 		value: "visiblePainted"
       
  2402 	},
       
  2403 
       
  2404 	/**
       
  2405 	 * Dom node for the shape.
       
  2406 	 *
       
  2407 	 * @config node
       
  2408 	 * @type HTMLElement
       
  2409 	 * @readOnly
       
  2410 	 */
       
  2411 	node: {
       
  2412 		readOnly: true,
       
  2413 
       
  2414 		getter: function()
       
  2415 		{
       
  2416 			return this.node;
       
  2417 		}
       
  2418 	},
       
  2419 
       
  2420     /**
       
  2421      * Represents an SVG Path string. This will be parsed and added to shape's API to represent the SVG data across all
       
  2422      * implementations. Note that when using VML or SVG implementations, part of this content will be added to the DOM using
       
  2423      * respective VML/SVG attributes. If your content comes from an untrusted source, you will need to ensure that no
       
  2424      * malicious code is included in that content.
       
  2425      *
       
  2426      * @config data
       
  2427      * @type String
       
  2428      */
       
  2429     data: {
       
  2430         setter: function(val)
       
  2431         {
       
  2432             if(this.get("node"))
       
  2433             {
       
  2434                 this._parsePathData(val);
       
  2435             }
       
  2436             return val;
       
  2437         }
       
  2438     },
       
  2439 
       
  2440 	/**
       
  2441 	 * Reference to the container Graphic.
       
  2442 	 *
       
  2443 	 * @config graphic
       
  2444 	 * @type Graphic
       
  2445 	 */
       
  2446 	graphic: {
       
  2447 		readOnly: true,
       
  2448 
       
  2449 		getter: function()
       
  2450 		{
       
  2451 			return this._graphic;
       
  2452 		}
       
  2453 	}
       
  2454 };
       
  2455 Y.VMLShape = VMLShape;
       
  2456 /**
       
  2457  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Path.html">`Path`</a> class.
       
  2458  * `VMLPath` is not intended to be used directly. Instead, use the <a href="Path.html">`Path`</a> class.
       
  2459  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
  2460  * capabilities, the <a href="Path.html">`Path`</a> class will point to the `VMLPath` class.
       
  2461  *
       
  2462  * @module graphics
       
  2463  * @class VMLPath
       
  2464  * @extends VMLShape
       
  2465  */
       
  2466 VMLPath = function()
       
  2467 {
       
  2468 	VMLPath.superclass.constructor.apply(this, arguments);
       
  2469 };
       
  2470 
       
  2471 VMLPath.NAME = "path";
       
  2472 Y.extend(VMLPath, Y.VMLShape);
       
  2473 VMLPath.ATTRS = Y.merge(Y.VMLShape.ATTRS, {
       
  2474 	/**
       
  2475 	 * Indicates the width of the shape
       
  2476 	 *
       
  2477 	 * @config width
       
  2478 	 * @type Number
       
  2479 	 */
       
  2480 	width: {
       
  2481 		getter: function()
       
  2482 		{
       
  2483 			var val = Math.max(this._right - this._left, 0);
       
  2484 			return val;
       
  2485 		}
       
  2486 	},
       
  2487 
       
  2488 	/**
       
  2489 	 * Indicates the height of the shape
       
  2490 	 *
       
  2491 	 * @config height
       
  2492 	 * @type Number
       
  2493 	 */
       
  2494 	height: {
       
  2495 		getter: function()
       
  2496 		{
       
  2497 			return Math.max(this._bottom - this._top, 0);
       
  2498 		}
       
  2499 	},
       
  2500 
       
  2501 	/**
       
  2502 	 * Indicates the path used for the node.
       
  2503 	 *
       
  2504 	 * @config path
       
  2505 	 * @type String
       
  2506      * @readOnly
       
  2507 	 */
       
  2508 	path: {
       
  2509 		readOnly: true,
       
  2510 
       
  2511 		getter: function()
       
  2512 		{
       
  2513 			return this._path;
       
  2514 		}
       
  2515 	}
       
  2516 });
       
  2517 Y.VMLPath = VMLPath;
       
  2518 /**
       
  2519  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Rect.html">`Rect`</a> class.
       
  2520  * `VMLRect` is not intended to be used directly. Instead, use the <a href="Rect.html">`Rect`</a> class.
       
  2521  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
  2522  * capabilities, the <a href="Rect.html">`Rect`</a> class will point to the `VMLRect` class.
       
  2523  *
       
  2524  * @module graphics
       
  2525  * @class VMLRect
       
  2526  * @constructor
       
  2527  */
       
  2528 VMLRect = function()
       
  2529 {
       
  2530 	VMLRect.superclass.constructor.apply(this, arguments);
       
  2531 };
       
  2532 VMLRect.NAME = "rect";
       
  2533 Y.extend(VMLRect, Y.VMLShape, {
       
  2534 	/**
       
  2535 	 * Indicates the type of shape
       
  2536 	 *
       
  2537 	 * @property _type
       
  2538 	 * @type String
       
  2539      * @private
       
  2540 	 */
       
  2541 	_type: "rect"
       
  2542 });
       
  2543 VMLRect.ATTRS = Y.VMLShape.ATTRS;
       
  2544 Y.VMLRect = VMLRect;
       
  2545 /**
       
  2546  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Ellipse.html">`Ellipse`</a> class.
       
  2547  * `VMLEllipse` is not intended to be used directly. Instead, use the <a href="Ellipse.html">`Ellipse`</a> class.
       
  2548  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
  2549  * capabilities, the <a href="Ellipse.html">`Ellipse`</a> class will point to the `VMLEllipse` class.
       
  2550  *
       
  2551  * @module graphics
       
  2552  * @class VMLEllipse
       
  2553  * @constructor
       
  2554  */
       
  2555 VMLEllipse = function()
       
  2556 {
       
  2557 	VMLEllipse.superclass.constructor.apply(this, arguments);
       
  2558 };
       
  2559 
       
  2560 VMLEllipse.NAME = "ellipse";
       
  2561 
       
  2562 Y.extend(VMLEllipse, Y.VMLShape, {
       
  2563 	/**
       
  2564 	 * Indicates the type of shape
       
  2565 	 *
       
  2566 	 * @property _type
       
  2567 	 * @type String
       
  2568      * @private
       
  2569 	 */
       
  2570 	_type: "oval"
       
  2571 });
       
  2572 VMLEllipse.ATTRS = Y.merge(Y.VMLShape.ATTRS, {
       
  2573 	/**
       
  2574 	 * Horizontal radius for the ellipse.
       
  2575 	 *
       
  2576 	 * @config xRadius
       
  2577 	 * @type Number
       
  2578 	 */
       
  2579 	xRadius: {
       
  2580 		lazyAdd: false,
       
  2581 
       
  2582 		getter: function()
       
  2583 		{
       
  2584 			var val = this.get("width");
       
  2585 			val = Math.round((val/2) * 100)/100;
       
  2586 			return val;
       
  2587 		},
       
  2588 
       
  2589 		setter: function(val)
       
  2590 		{
       
  2591 			var w = val * 2;
       
  2592 			this.set("width", w);
       
  2593 			return val;
       
  2594 		}
       
  2595 	},
       
  2596 
       
  2597 	/**
       
  2598 	 * Vertical radius for the ellipse.
       
  2599 	 *
       
  2600 	 * @config yRadius
       
  2601 	 * @type Number
       
  2602 	 * @readOnly
       
  2603 	 */
       
  2604 	yRadius: {
       
  2605 		lazyAdd: false,
       
  2606 
       
  2607 		getter: function()
       
  2608 		{
       
  2609 			var val = this.get("height");
       
  2610 			val = Math.round((val/2) * 100)/100;
       
  2611 			return val;
       
  2612 		},
       
  2613 
       
  2614 		setter: function(val)
       
  2615 		{
       
  2616 			var h = val * 2;
       
  2617 			this.set("height", h);
       
  2618 			return val;
       
  2619 		}
       
  2620 	}
       
  2621 });
       
  2622 Y.VMLEllipse = VMLEllipse;
       
  2623 /**
       
  2624  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Circle.html">`Circle`</a> class.
       
  2625  * `VMLCircle` is not intended to be used directly. Instead, use the <a href="Circle.html">`Circle`</a> class.
       
  2626  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
  2627  * capabilities, the <a href="Circle.html">`Circle`</a> class will point to the `VMLCircle` class.
       
  2628  *
       
  2629  * @module graphics
       
  2630  * @class VMLCircle
       
  2631  * @constructor
       
  2632  */
       
  2633 VMLCircle = function()
       
  2634 {
       
  2635 	VMLCircle.superclass.constructor.apply(this, arguments);
       
  2636 };
       
  2637 
       
  2638 VMLCircle.NAME = "circle";
       
  2639 
       
  2640 Y.extend(VMLCircle, VMLShape, {
       
  2641 	/**
       
  2642 	 * Indicates the type of shape
       
  2643 	 *
       
  2644 	 * @property _type
       
  2645 	 * @type String
       
  2646      * @private
       
  2647 	 */
       
  2648 	_type: "oval"
       
  2649 });
       
  2650 
       
  2651 VMLCircle.ATTRS = Y.merge(VMLShape.ATTRS, {
       
  2652 	/**
       
  2653 	 * Radius for the circle.
       
  2654 	 *
       
  2655 	 * @config radius
       
  2656 	 * @type Number
       
  2657 	 */
       
  2658 	radius: {
       
  2659 		lazyAdd: false,
       
  2660 
       
  2661 		value: 0
       
  2662 	},
       
  2663 
       
  2664 	/**
       
  2665 	 * Indicates the width of the shape
       
  2666 	 *
       
  2667 	 * @config width
       
  2668 	 * @type Number
       
  2669 	 */
       
  2670 	width: {
       
  2671         setter: function(val)
       
  2672         {
       
  2673             this.set("radius", val/2);
       
  2674             return val;
       
  2675         },
       
  2676 
       
  2677 		getter: function()
       
  2678 		{
       
  2679 			var radius = this.get("radius"),
       
  2680 			val = radius && radius > 0 ? radius * 2 : 0;
       
  2681 			return val;
       
  2682 		}
       
  2683 	},
       
  2684 
       
  2685 	/**
       
  2686 	 * Indicates the height of the shape
       
  2687 	 *
       
  2688 	 * @config height
       
  2689 	 * @type Number
       
  2690 	 */
       
  2691 	height: {
       
  2692         setter: function(val)
       
  2693         {
       
  2694             this.set("radius", val/2);
       
  2695             return val;
       
  2696         },
       
  2697 
       
  2698 		getter: function()
       
  2699 		{
       
  2700 			var radius = this.get("radius"),
       
  2701 			val = radius && radius > 0 ? radius * 2 : 0;
       
  2702 			return val;
       
  2703 		}
       
  2704 	}
       
  2705 });
       
  2706 Y.VMLCircle = VMLCircle;
       
  2707 /**
       
  2708  * Draws pie slices
       
  2709  *
       
  2710  * @module graphics
       
  2711  * @class VMLPieSlice
       
  2712  * @constructor
       
  2713  */
       
  2714 VMLPieSlice = function()
       
  2715 {
       
  2716 	VMLPieSlice.superclass.constructor.apply(this, arguments);
       
  2717 };
       
  2718 VMLPieSlice.NAME = "vmlPieSlice";
       
  2719 Y.extend(VMLPieSlice, Y.VMLShape, Y.mix({
       
  2720     /**
       
  2721      * Indicates the type of shape
       
  2722      *
       
  2723      * @property _type
       
  2724      * @type String
       
  2725      * @private
       
  2726      */
       
  2727     _type: "shape",
       
  2728 
       
  2729 	/**
       
  2730 	 * Change event listener
       
  2731 	 *
       
  2732 	 * @private
       
  2733 	 * @method _updateHandler
       
  2734 	 */
       
  2735 	_draw: function()
       
  2736 	{
       
  2737         var x = this.get("cx"),
       
  2738             y = this.get("cy"),
       
  2739             startAngle = this.get("startAngle"),
       
  2740             arc = this.get("arc"),
       
  2741             radius = this.get("radius");
       
  2742         this.clear();
       
  2743         this.drawWedge(x, y, startAngle, arc, radius);
       
  2744 		this.end();
       
  2745 	}
       
  2746  }, Y.VMLDrawing.prototype));
       
  2747 VMLPieSlice.ATTRS = Y.mix({
       
  2748     cx: {
       
  2749         value: 0
       
  2750     },
       
  2751 
       
  2752     cy: {
       
  2753         value: 0
       
  2754     },
       
  2755     /**
       
  2756      * Starting angle in relation to a circle in which to begin the pie slice drawing.
       
  2757      *
       
  2758      * @config startAngle
       
  2759      * @type Number
       
  2760      */
       
  2761     startAngle: {
       
  2762         value: 0
       
  2763     },
       
  2764 
       
  2765     /**
       
  2766      * Arc of the slice.
       
  2767      *
       
  2768      * @config arc
       
  2769      * @type Number
       
  2770      */
       
  2771     arc: {
       
  2772         value: 0
       
  2773     },
       
  2774 
       
  2775     /**
       
  2776      * Radius of the circle in which the pie slice is drawn
       
  2777      *
       
  2778      * @config radius
       
  2779      * @type Number
       
  2780      */
       
  2781     radius: {
       
  2782         value: 0
       
  2783     }
       
  2784 }, Y.VMLShape.ATTRS);
       
  2785 Y.VMLPieSlice = VMLPieSlice;
       
  2786 /**
       
  2787  * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Graphic.html">`Graphic`</a> class.
       
  2788  * `VMLGraphic` is not intended to be used directly. Instead, use the <a href="Graphic.html">`Graphic`</a> class.
       
  2789  * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
       
  2790  * capabilities, the <a href="Graphic.html">`Graphic`</a> class will point to the `VMLGraphic` class.
       
  2791  *
       
  2792  * @module graphics
       
  2793  * @class VMLGraphic
       
  2794  * @constructor
       
  2795  */
       
  2796 VMLGraphic = function() {
       
  2797     VMLGraphic.superclass.constructor.apply(this, arguments);
       
  2798 };
       
  2799 
       
  2800 VMLGraphic.NAME = "vmlGraphic";
       
  2801 
       
  2802 VMLGraphic.ATTRS = {
       
  2803     /**
       
  2804      * Whether or not to render the `Graphic` automatically after to a specified parent node after init. This can be a Node
       
  2805      * instance or a CSS selector string.
       
  2806      *
       
  2807      * @config render
       
  2808      * @type Node | String
       
  2809      */
       
  2810     render: {},
       
  2811 
       
  2812     /**
       
  2813 	 * Unique id for class instance.
       
  2814 	 *
       
  2815 	 * @config id
       
  2816 	 * @type String
       
  2817 	 */
       
  2818 	id: {
       
  2819 		valueFn: function()
       
  2820 		{
       
  2821 			return Y.guid();
       
  2822 		},
       
  2823 
       
  2824 		setter: function(val)
       
  2825 		{
       
  2826 			var node = this._node;
       
  2827 			if(node)
       
  2828 			{
       
  2829 				node.setAttribute("id", val);
       
  2830 			}
       
  2831 			return val;
       
  2832 		}
       
  2833 	},
       
  2834 
       
  2835     /**
       
  2836      * Key value pairs in which a shape instance is associated with its id.
       
  2837      *
       
  2838      *  @config shapes
       
  2839      *  @type Object
       
  2840      *  @readOnly
       
  2841      */
       
  2842     shapes: {
       
  2843         readOnly: true,
       
  2844 
       
  2845         getter: function()
       
  2846         {
       
  2847             return this._shapes;
       
  2848         }
       
  2849     },
       
  2850 
       
  2851     /**
       
  2852      *  Object containing size and coordinate data for the content of a Graphic in relation to the coordSpace node.
       
  2853      *
       
  2854      *  @config contentBounds
       
  2855      *  @type Object
       
  2856      */
       
  2857     contentBounds: {
       
  2858         readOnly: true,
       
  2859 
       
  2860         getter: function()
       
  2861         {
       
  2862             return this._contentBounds;
       
  2863         }
       
  2864     },
       
  2865 
       
  2866     /**
       
  2867      *  The html element that represents to coordinate system of the Graphic instance.
       
  2868      *
       
  2869      *  @config node
       
  2870      *  @type HTMLElement
       
  2871      */
       
  2872     node: {
       
  2873         readOnly: true,
       
  2874 
       
  2875         getter: function()
       
  2876         {
       
  2877             return this._node;
       
  2878         }
       
  2879     },
       
  2880 
       
  2881 	/**
       
  2882 	 * Indicates the width of the `Graphic`.
       
  2883 	 *
       
  2884 	 * @config width
       
  2885 	 * @type Number
       
  2886 	 */
       
  2887     width: {
       
  2888         setter: function(val)
       
  2889         {
       
  2890             if(this._node)
       
  2891             {
       
  2892                 this._node.style.width = val + "px";
       
  2893             }
       
  2894             return val;
       
  2895         }
       
  2896     },
       
  2897 
       
  2898 	/**
       
  2899 	 * Indicates the height of the `Graphic`.
       
  2900 	 *
       
  2901 	 * @config height
       
  2902 	 * @type Number
       
  2903 	 */
       
  2904     height: {
       
  2905         setter: function(val)
       
  2906         {
       
  2907             if(this._node)
       
  2908             {
       
  2909                 this._node.style.height = val + "px";
       
  2910             }
       
  2911             return val;
       
  2912         }
       
  2913     },
       
  2914 
       
  2915     /**
       
  2916      *  Determines the sizing of the Graphic.
       
  2917      *
       
  2918      *  <dl>
       
  2919      *      <dt>sizeContentToGraphic</dt><dd>The Graphic's width and height attributes are, either explicitly set through the
       
  2920      *      <code>width</code> and <code>height</code> attributes or are determined by the dimensions of the parent element. The
       
  2921      *      content contained in the Graphic will be sized to fit with in the Graphic instance's dimensions. When using this
       
  2922      *      setting, the <code>preserveAspectRatio</code> attribute will determine how the contents are sized.</dd>
       
  2923      *      <dt>sizeGraphicToContent</dt><dd>(Also accepts a value of true) The Graphic's width and height are determined by the
       
  2924      *      size and positioning of the content.</dd>
       
  2925      *      <dt>false</dt><dd>The Graphic's width and height attributes are, either explicitly set through the <code>width</code>
       
  2926      *      and <code>height</code> attributes or are determined by the dimensions of the parent element. The contents of the
       
  2927      *      Graphic instance are not affected by this setting.</dd>
       
  2928      *  </dl>
       
  2929      *
       
  2930      *
       
  2931      *  @config autoSize
       
  2932      *  @type Boolean | String
       
  2933      *  @default false
       
  2934      */
       
  2935     autoSize: {
       
  2936         value: false
       
  2937     },
       
  2938 
       
  2939     /**
       
  2940      * Determines how content is sized when <code>autoSize</code> is set to <code>sizeContentToGraphic</code>.
       
  2941      *
       
  2942      *  <dl>
       
  2943      *      <dt>none<dt><dd>Do not force uniform scaling. Scale the graphic content of the given element non-uniformly if necessary
       
  2944      *      such that the element's bounding box exactly matches the viewport rectangle.</dd>
       
  2945      *      <dt>xMinYMin</dt><dd>Force uniform scaling position along the top left of the Graphic's node.</dd>
       
  2946      *      <dt>xMidYMin</dt><dd>Force uniform scaling horizontally centered and positioned at the top of the Graphic's node.<dd>
       
  2947      *      <dt>xMaxYMin</dt><dd>Force uniform scaling positioned horizontally from the right and vertically from the top.</dd>
       
  2948      *      <dt>xMinYMid</dt>Force uniform scaling positioned horizontally from the left and vertically centered.</dd>
       
  2949      *      <dt>xMidYMid (the default)</dt><dd>Force uniform scaling with the content centered.</dd>
       
  2950      *      <dt>xMaxYMid</dt><dd>Force uniform scaling positioned horizontally from the right and vertically centered.</dd>
       
  2951      *      <dt>xMinYMax</dt><dd>Force uniform scaling positioned horizontally from the left and vertically from the bottom.</dd>
       
  2952      *      <dt>xMidYMax</dt><dd>Force uniform scaling horizontally centered and position vertically from the bottom.</dd>
       
  2953      *      <dt>xMaxYMax</dt><dd>Force uniform scaling positioned horizontally from the right and vertically from the bottom.</dd>
       
  2954      *  </dl>
       
  2955      *
       
  2956      * @config preserveAspectRatio
       
  2957      * @type String
       
  2958      * @default xMidYMid
       
  2959      */
       
  2960     preserveAspectRatio: {
       
  2961         value: "xMidYMid"
       
  2962     },
       
  2963 
       
  2964     /**
       
  2965      * The contentBounds will resize to greater values but not values. (for performance)
       
  2966      * When resizing the contentBounds down is desirable, set the resizeDown value to true.
       
  2967      *
       
  2968      * @config resizeDown
       
  2969      * @type Boolean
       
  2970      */
       
  2971     resizeDown: {
       
  2972         resizeDown: false
       
  2973     },
       
  2974 
       
  2975 	/**
       
  2976 	 * Indicates the x-coordinate for the instance.
       
  2977 	 *
       
  2978 	 * @config x
       
  2979 	 * @type Number
       
  2980 	 */
       
  2981     x: {
       
  2982         getter: function()
       
  2983         {
       
  2984             return this._x;
       
  2985         },
       
  2986 
       
  2987         setter: function(val)
       
  2988         {
       
  2989             this._x = val;
       
  2990             if(this._node)
       
  2991             {
       
  2992                 this._node.style.left = val + "px";
       
  2993             }
       
  2994             return val;
       
  2995         }
       
  2996     },
       
  2997 
       
  2998 	/**
       
  2999 	 * Indicates the y-coordinate for the instance.
       
  3000 	 *
       
  3001 	 * @config y
       
  3002 	 * @type Number
       
  3003 	 */
       
  3004     y: {
       
  3005         getter: function()
       
  3006         {
       
  3007             return this._y;
       
  3008         },
       
  3009 
       
  3010         setter: function(val)
       
  3011         {
       
  3012             this._y = val;
       
  3013             if(this._node)
       
  3014             {
       
  3015                 this._node.style.top = val + "px";
       
  3016             }
       
  3017             return val;
       
  3018         }
       
  3019     },
       
  3020 
       
  3021     /**
       
  3022      * Indicates whether or not the instance will automatically redraw after a change is made to a shape.
       
  3023      * This property will get set to false when batching operations.
       
  3024      *
       
  3025      * @config autoDraw
       
  3026      * @type Boolean
       
  3027      * @default true
       
  3028      * @private
       
  3029      */
       
  3030     autoDraw: {
       
  3031         value: true
       
  3032     },
       
  3033 
       
  3034     visible: {
       
  3035         value: true,
       
  3036 
       
  3037         setter: function(val)
       
  3038         {
       
  3039             this._toggleVisible(val);
       
  3040             return val;
       
  3041         }
       
  3042     }
       
  3043 };
       
  3044 
       
  3045 Y.extend(VMLGraphic, Y.GraphicBase, {
       
  3046     /**
       
  3047      * Sets the value of an attribute.
       
  3048      *
       
  3049      * @method set
       
  3050      * @param {String|Object} name The name of the attribute. Alternatively, an object of key value pairs can
       
  3051      * be passed in to set multiple attributes at once.
       
  3052      * @param {Any} value The value to set the attribute to. This value is ignored if an object is received as
       
  3053      * the name param.
       
  3054      */
       
  3055 	set: function()
       
  3056 	{
       
  3057 		var host = this,
       
  3058             attr = arguments[0],
       
  3059             redrawAttrs = {
       
  3060                 autoDraw: true,
       
  3061                 autoSize: true,
       
  3062                 preserveAspectRatio: true,
       
  3063                 resizeDown: true
       
  3064             },
       
  3065             key,
       
  3066             forceRedraw = false;
       
  3067 		AttributeLite.prototype.set.apply(host, arguments);
       
  3068         if(host._state.autoDraw === true && Y.Object.size(this._shapes) > 0)
       
  3069         {
       
  3070             if(Y_LANG.isString && redrawAttrs[attr])
       
  3071             {
       
  3072                 forceRedraw = true;
       
  3073             }
       
  3074             else if(Y_LANG.isObject(attr))
       
  3075             {
       
  3076                 for(key in redrawAttrs)
       
  3077                 {
       
  3078                     if(redrawAttrs.hasOwnProperty(key) && attr[key])
       
  3079                     {
       
  3080                         forceRedraw = true;
       
  3081                         break;
       
  3082                     }
       
  3083                 }
       
  3084             }
       
  3085         }
       
  3086         if(forceRedraw)
       
  3087         {
       
  3088             host._redraw();
       
  3089         }
       
  3090 	},
       
  3091 
       
  3092     /**
       
  3093      * Storage for `x` attribute.
       
  3094      *
       
  3095      * @property _x
       
  3096      * @type Number
       
  3097      * @private
       
  3098      */
       
  3099     _x: 0,
       
  3100 
       
  3101     /**
       
  3102      * Storage for `y` attribute.
       
  3103      *
       
  3104      * @property _y
       
  3105      * @type Number
       
  3106      * @private
       
  3107      */
       
  3108     _y: 0,
       
  3109 
       
  3110     /**
       
  3111      * Gets the current position of the graphic instance in page coordinates.
       
  3112      *
       
  3113      * @method getXY
       
  3114      * @return Array The XY position of the shape.
       
  3115      */
       
  3116     getXY: function()
       
  3117     {
       
  3118         var node = this.parentNode,
       
  3119             x = this.get("x"),
       
  3120             y = this.get("y"),
       
  3121             xy;
       
  3122         if(node)
       
  3123         {
       
  3124             xy = Y.one(node).getXY();
       
  3125             xy[0] += x;
       
  3126             xy[1] += y;
       
  3127         }
       
  3128         else
       
  3129         {
       
  3130             xy = Y.DOM._getOffset(this._node);
       
  3131         }
       
  3132         return xy;
       
  3133     },
       
  3134 
       
  3135     /**
       
  3136      * Initializes the class.
       
  3137      *
       
  3138      * @method initializer
       
  3139      * @private
       
  3140      */
       
  3141     initializer: function() {
       
  3142         var render = this.get("render"),
       
  3143             visibility = this.get("visible") ? "visible" : "hidden";
       
  3144         this._shapes = {};
       
  3145 		this._contentBounds = {
       
  3146             left: 0,
       
  3147             top: 0,
       
  3148             right: 0,
       
  3149             bottom: 0
       
  3150         };
       
  3151         this._node = this._createGraphic();
       
  3152         this._node.style.left = this.get("x") + "px";
       
  3153         this._node.style.top = this.get("y") + "px";
       
  3154         this._node.style.visibility = visibility;
       
  3155         this._node.setAttribute("id", this.get("id"));
       
  3156         if(render)
       
  3157         {
       
  3158             this.render(render);
       
  3159         }
       
  3160     },
       
  3161 
       
  3162     /**
       
  3163      * Adds the graphics node to the dom.
       
  3164      *
       
  3165      * @method render
       
  3166      * @param {HTMLElement} parentNode node in which to render the graphics node into.
       
  3167      */
       
  3168     render: function(render) {
       
  3169         var parentNode = Y.one(render),
       
  3170             w = this.get("width") || parseInt(parentNode.getComputedStyle("width"), 10),
       
  3171             h = this.get("height") || parseInt(parentNode.getComputedStyle("height"), 10);
       
  3172         parentNode = parentNode || DOCUMENT.body;
       
  3173         parentNode.appendChild(this._node);
       
  3174         this.parentNode = parentNode;
       
  3175         this.set("width", w);
       
  3176         this.set("height", h);
       
  3177         return this;
       
  3178     },
       
  3179 
       
  3180     /**
       
  3181      * Removes all nodes.
       
  3182      *
       
  3183      * @method destroy
       
  3184      */
       
  3185     destroy: function()
       
  3186     {
       
  3187         this.clear();
       
  3188         Y.one(this._node).remove(true);
       
  3189     },
       
  3190 
       
  3191     /**
       
  3192      * Generates a shape instance by type.
       
  3193      *
       
  3194      * @method addShape
       
  3195      * @param {Object} cfg attributes for the shape
       
  3196      * @return Shape
       
  3197      */
       
  3198     addShape: function(cfg)
       
  3199     {
       
  3200         cfg.graphic = this;
       
  3201         if(!this.get("visible"))
       
  3202         {
       
  3203             cfg.visible = false;
       
  3204         }
       
  3205         var ShapeClass = this._getShapeClass(cfg.type),
       
  3206             shape = new ShapeClass(cfg);
       
  3207         this._appendShape(shape);
       
  3208         shape._appendStrokeAndFill();
       
  3209         return shape;
       
  3210     },
       
  3211 
       
  3212     /**
       
  3213      * Adds a shape instance to the graphic instance.
       
  3214      *
       
  3215      * @method _appendShape
       
  3216      * @param {Shape} shape The shape instance to be added to the graphic.
       
  3217      * @private
       
  3218      */
       
  3219     _appendShape: function(shape)
       
  3220     {
       
  3221         var node = shape.node,
       
  3222             parentNode = this._frag || this._node;
       
  3223         if(this.get("autoDraw") || this.get("autoSize") === "sizeContentToGraphic")
       
  3224         {
       
  3225             parentNode.appendChild(node);
       
  3226         }
       
  3227         else
       
  3228         {
       
  3229             this._getDocFrag().appendChild(node);
       
  3230         }
       
  3231     },
       
  3232 
       
  3233     /**
       
  3234      * Removes a shape instance from from the graphic instance.
       
  3235      *
       
  3236      * @method removeShape
       
  3237      * @param {Shape|String} shape The instance or id of the shape to be removed.
       
  3238      */
       
  3239     removeShape: function(shape)
       
  3240     {
       
  3241         if(!(shape instanceof VMLShape))
       
  3242         {
       
  3243             if(Y_LANG.isString(shape))
       
  3244             {
       
  3245                 shape = this._shapes[shape];
       
  3246             }
       
  3247         }
       
  3248         if(shape && (shape instanceof VMLShape))
       
  3249         {
       
  3250             shape._destroy();
       
  3251             this._shapes[shape.get("id")] = null;
       
  3252             delete this._shapes[shape.get("id")];
       
  3253         }
       
  3254         if(this.get("autoDraw"))
       
  3255         {
       
  3256             this._redraw();
       
  3257         }
       
  3258     },
       
  3259 
       
  3260     /**
       
  3261      * Removes all shape instances from the dom.
       
  3262      *
       
  3263      * @method removeAllShapes
       
  3264      */
       
  3265     removeAllShapes: function()
       
  3266     {
       
  3267         var shapes = this._shapes,
       
  3268             i;
       
  3269         for(i in shapes)
       
  3270         {
       
  3271             if(shapes.hasOwnProperty(i))
       
  3272             {
       
  3273                 shapes[i].destroy();
       
  3274             }
       
  3275         }
       
  3276         this._shapes = {};
       
  3277     },
       
  3278 
       
  3279     /**
       
  3280      * Removes all child nodes.
       
  3281      *
       
  3282      * @method _removeChildren
       
  3283      * @param node
       
  3284      * @private
       
  3285      */
       
  3286     _removeChildren: function(node)
       
  3287     {
       
  3288         if(node.hasChildNodes())
       
  3289         {
       
  3290             var child;
       
  3291             while(node.firstChild)
       
  3292             {
       
  3293                 child = node.firstChild;
       
  3294                 this._removeChildren(child);
       
  3295                 node.removeChild(child);
       
  3296             }
       
  3297         }
       
  3298     },
       
  3299 
       
  3300     /**
       
  3301      * Clears the graphics object.
       
  3302      *
       
  3303      * @method clear
       
  3304      */
       
  3305     clear: function() {
       
  3306         this.removeAllShapes();
       
  3307         this._removeChildren(this._node);
       
  3308     },
       
  3309 
       
  3310     /**
       
  3311      * Toggles visibility
       
  3312      *
       
  3313      * @method _toggleVisible
       
  3314      * @param {Boolean} val indicates visibilitye
       
  3315      * @private
       
  3316      */
       
  3317     _toggleVisible: function(val)
       
  3318     {
       
  3319         var i,
       
  3320             shapes = this._shapes,
       
  3321             visibility = val ? "visible" : "hidden";
       
  3322         if(shapes)
       
  3323         {
       
  3324             for(i in shapes)
       
  3325             {
       
  3326                 if(shapes.hasOwnProperty(i))
       
  3327                 {
       
  3328                     shapes[i].set("visible", val);
       
  3329                 }
       
  3330             }
       
  3331         }
       
  3332         if(this._node)
       
  3333         {
       
  3334             this._node.style.visibility = visibility;
       
  3335         }
       
  3336         if(this._node)
       
  3337         {
       
  3338             this._node.style.visibility = visibility;
       
  3339         }
       
  3340     },
       
  3341 
       
  3342     /**
       
  3343      * Sets the size of the graphics object.
       
  3344      *
       
  3345      * @method setSize
       
  3346      * @param w {Number} width to set for the instance.
       
  3347      * @param h {Number} height to set for the instance.
       
  3348      */
       
  3349     setSize: function(w, h) {
       
  3350         w = Math.round(w);
       
  3351         h = Math.round(h);
       
  3352         this._node.style.width = w + 'px';
       
  3353         this._node.style.height = h + 'px';
       
  3354     },
       
  3355 
       
  3356     /**
       
  3357      * Sets the positon of the graphics object.
       
  3358      *
       
  3359      * @method setPosition
       
  3360      * @param {Number} x x-coordinate for the object.
       
  3361      * @param {Number} y y-coordinate for the object.
       
  3362      */
       
  3363     setPosition: function(x, y)
       
  3364     {
       
  3365         x = Math.round(x);
       
  3366         y = Math.round(y);
       
  3367         this._node.style.left = x + "px";
       
  3368         this._node.style.top = y + "px";
       
  3369     },
       
  3370 
       
  3371     /**
       
  3372      * Creates a group element
       
  3373      *
       
  3374      * @method _createGraphic
       
  3375      * @private
       
  3376      */
       
  3377     _createGraphic: function() {
       
  3378         var group = DOCUMENT.createElement(
       
  3379             '<group xmlns="urn:schemas-microsft.com:vml"' +
       
  3380             ' style="behavior:url(#default#VML);padding:0px 0px 0px 0px;display:block;position:absolute;top:0px;left:0px;zoom:1;"' +
       
  3381             '/>'
       
  3382         );
       
  3383         return group;
       
  3384     },
       
  3385 
       
  3386     /**
       
  3387      * Creates a graphic node
       
  3388      *
       
  3389      * @method _createGraphicNode
       
  3390      * @param {String} type node type to create
       
  3391      * @param {String} pe specified pointer-events value
       
  3392      * @return HTMLElement
       
  3393      * @private
       
  3394      */
       
  3395     _createGraphicNode: function(type)
       
  3396     {
       
  3397         return DOCUMENT.createElement(
       
  3398             '<' +
       
  3399             type +
       
  3400             ' xmlns="urn:schemas-microsft.com:vml"' +
       
  3401             ' style="behavior:url(#default#VML);display:inline-block;zoom:1;"' +
       
  3402             '/>'
       
  3403         );
       
  3404 
       
  3405     },
       
  3406 
       
  3407     /**
       
  3408      * Returns a shape based on the id of its dom node.
       
  3409      *
       
  3410      * @method getShapeById
       
  3411      * @param {String} id Dom id of the shape's node attribute.
       
  3412      * @return Shape
       
  3413      */
       
  3414     getShapeById: function(id)
       
  3415     {
       
  3416         return this._shapes[id];
       
  3417     },
       
  3418 
       
  3419     /**
       
  3420      * Returns a shape class. Used by `addShape`.
       
  3421      *
       
  3422      * @method _getShapeClass
       
  3423      * @param {Shape | String} val Indicates which shape class.
       
  3424      * @return Function
       
  3425      * @private
       
  3426      */
       
  3427     _getShapeClass: function(val)
       
  3428     {
       
  3429         var shape = this._shapeClass[val];
       
  3430         if(shape)
       
  3431         {
       
  3432             return shape;
       
  3433         }
       
  3434         return val;
       
  3435     },
       
  3436 
       
  3437     /**
       
  3438      * Look up for shape classes. Used by `addShape` to retrieve a class for instantiation.
       
  3439      *
       
  3440      * @property _shapeClass
       
  3441      * @type Object
       
  3442      * @private
       
  3443      */
       
  3444     _shapeClass: {
       
  3445         circle: Y.VMLCircle,
       
  3446         rect: Y.VMLRect,
       
  3447         path: Y.VMLPath,
       
  3448         ellipse: Y.VMLEllipse,
       
  3449         pieslice: Y.VMLPieSlice
       
  3450     },
       
  3451 
       
  3452 	/**
       
  3453 	 * Allows for creating multiple shapes in order to batch appending and redraw operations.
       
  3454 	 *
       
  3455 	 * @method batch
       
  3456 	 * @param {Function} method Method to execute.
       
  3457 	 */
       
  3458     batch: function(method)
       
  3459     {
       
  3460         var autoDraw = this.get("autoDraw");
       
  3461         this.set("autoDraw", false);
       
  3462         method.apply();
       
  3463         this.set("autoDraw", autoDraw);
       
  3464     },
       
  3465 
       
  3466     /**
       
  3467      * Returns a document fragment to for attaching shapes.
       
  3468      *
       
  3469      * @method _getDocFrag
       
  3470      * @return DocumentFragment
       
  3471      * @private
       
  3472      */
       
  3473     _getDocFrag: function()
       
  3474     {
       
  3475         if(!this._frag)
       
  3476         {
       
  3477             this._frag = DOCUMENT.createDocumentFragment();
       
  3478         }
       
  3479         return this._frag;
       
  3480     },
       
  3481 
       
  3482     /**
       
  3483      * Adds a shape to the redraw queue and calculates the contentBounds.
       
  3484      *
       
  3485      * @method addToRedrawQueue
       
  3486      * @param shape {VMLShape}
       
  3487      * @protected
       
  3488      */
       
  3489     addToRedrawQueue: function(shape)
       
  3490     {
       
  3491         var shapeBox,
       
  3492             box;
       
  3493         this._shapes[shape.get("id")] = shape;
       
  3494         if(!this.get("resizeDown"))
       
  3495         {
       
  3496             shapeBox = shape.getBounds();
       
  3497             box = this._contentBounds;
       
  3498             box.left = box.left < shapeBox.left ? box.left : shapeBox.left;
       
  3499             box.top = box.top < shapeBox.top ? box.top : shapeBox.top;
       
  3500             box.right = box.right > shapeBox.right ? box.right : shapeBox.right;
       
  3501             box.bottom = box.bottom > shapeBox.bottom ? box.bottom : shapeBox.bottom;
       
  3502             box.width = box.right - box.left;
       
  3503             box.height = box.bottom - box.top;
       
  3504             this._contentBounds = box;
       
  3505         }
       
  3506         if(this.get("autoDraw"))
       
  3507         {
       
  3508             this._redraw();
       
  3509         }
       
  3510     },
       
  3511 
       
  3512     /**
       
  3513      * Redraws all shapes.
       
  3514      *
       
  3515      * @method _redraw
       
  3516      * @private
       
  3517      */
       
  3518     _redraw: function()
       
  3519     {
       
  3520         var autoSize = this.get("autoSize"),
       
  3521             preserveAspectRatio,
       
  3522             node = this.parentNode,
       
  3523             nodeWidth = parseFloat(node.getComputedStyle("width")),
       
  3524             nodeHeight = parseFloat(node.getComputedStyle("height")),
       
  3525             xCoordOrigin = 0,
       
  3526             yCoordOrigin = 0,
       
  3527             box = this.get("resizeDown") ? this._getUpdatedContentBounds() : this._contentBounds,
       
  3528             left = box.left,
       
  3529             right = box.right,
       
  3530             top = box.top,
       
  3531             bottom = box.bottom,
       
  3532             contentWidth = right - left,
       
  3533             contentHeight = bottom - top,
       
  3534             aspectRatio,
       
  3535             xCoordSize,
       
  3536             yCoordSize,
       
  3537             scaledWidth,
       
  3538             scaledHeight,
       
  3539             visible = this.get("visible");
       
  3540         this._node.style.visibility = "hidden";
       
  3541         if(autoSize)
       
  3542         {
       
  3543             if(autoSize === "sizeContentToGraphic")
       
  3544             {
       
  3545                 preserveAspectRatio = this.get("preserveAspectRatio");
       
  3546                 if(preserveAspectRatio === "none" || contentWidth/contentHeight === nodeWidth/nodeHeight)
       
  3547                 {
       
  3548                     xCoordOrigin = left;
       
  3549                     yCoordOrigin = top;
       
  3550                     xCoordSize = contentWidth;
       
  3551                     yCoordSize = contentHeight;
       
  3552                 }
       
  3553                 else
       
  3554                 {
       
  3555                     if(contentWidth * nodeHeight/contentHeight > nodeWidth)
       
  3556                     {
       
  3557                         aspectRatio = nodeHeight/nodeWidth;
       
  3558                         xCoordSize = contentWidth;
       
  3559                         yCoordSize = contentWidth * aspectRatio;
       
  3560                         scaledHeight = (nodeWidth * (contentHeight/contentWidth)) * (yCoordSize/nodeHeight);
       
  3561                         yCoordOrigin = this._calculateCoordOrigin(preserveAspectRatio.slice(5).toLowerCase(), scaledHeight, yCoordSize);
       
  3562                         yCoordOrigin = top + yCoordOrigin;
       
  3563                         xCoordOrigin = left;
       
  3564                     }
       
  3565                     else
       
  3566                     {
       
  3567                         aspectRatio = nodeWidth/nodeHeight;
       
  3568                         xCoordSize = contentHeight * aspectRatio;
       
  3569                         yCoordSize = contentHeight;
       
  3570                         scaledWidth = (nodeHeight * (contentWidth/contentHeight)) * (xCoordSize/nodeWidth);
       
  3571                         xCoordOrigin = this._calculateCoordOrigin(preserveAspectRatio.slice(1, 4).toLowerCase(), scaledWidth, xCoordSize);
       
  3572                         xCoordOrigin = xCoordOrigin + left;
       
  3573                         yCoordOrigin = top;
       
  3574                     }
       
  3575                 }
       
  3576                 this._node.style.width = nodeWidth + "px";
       
  3577                 this._node.style.height = nodeHeight + "px";
       
  3578                 this._node.coordOrigin = xCoordOrigin + ", " + yCoordOrigin;
       
  3579             }
       
  3580             else
       
  3581             {
       
  3582                 xCoordSize = contentWidth;
       
  3583                 yCoordSize = contentHeight;
       
  3584                 this._node.style.width = contentWidth + "px";
       
  3585                 this._node.style.height = contentHeight + "px";
       
  3586                 this._state.width = contentWidth;
       
  3587                 this._state.height =  contentHeight;
       
  3588 
       
  3589             }
       
  3590             this._node.coordSize = xCoordSize + ", " + yCoordSize;
       
  3591         }
       
  3592         else
       
  3593         {
       
  3594             this._node.style.width = nodeWidth + "px";
       
  3595             this._node.style.height = nodeHeight + "px";
       
  3596             this._node.coordSize = nodeWidth + ", " + nodeHeight;
       
  3597         }
       
  3598         if(this._frag)
       
  3599         {
       
  3600             this._node.appendChild(this._frag);
       
  3601             this._frag = null;
       
  3602         }
       
  3603         if(visible)
       
  3604         {
       
  3605             this._node.style.visibility = "visible";
       
  3606         }
       
  3607     },
       
  3608 
       
  3609     /**
       
  3610      * Determines the value for either an x or y coordinate to be used for the <code>coordOrigin</code> of the Graphic.
       
  3611      *
       
  3612      * @method _calculateCoordOrigin
       
  3613      * @param {String} position The position for placement. Possible values are min, mid and max.
       
  3614      * @param {Number} size The total scaled size of the content.
       
  3615      * @param {Number} coordsSize The coordsSize for the Graphic.
       
  3616      * @return Number
       
  3617      * @private
       
  3618      */
       
  3619     _calculateCoordOrigin: function(position, size, coordsSize)
       
  3620     {
       
  3621         var coord;
       
  3622         switch(position)
       
  3623         {
       
  3624             case "min" :
       
  3625                 coord = 0;
       
  3626             break;
       
  3627             case "mid" :
       
  3628                 coord = (size - coordsSize)/2;
       
  3629             break;
       
  3630             case "max" :
       
  3631                 coord = (size - coordsSize);
       
  3632             break;
       
  3633         }
       
  3634         return coord;
       
  3635     },
       
  3636 
       
  3637     /**
       
  3638      * Recalculates and returns the `contentBounds` for the `Graphic` instance.
       
  3639      *
       
  3640      * @method _getUpdatedContentBounds
       
  3641      * @return {Object}
       
  3642      * @private
       
  3643      */
       
  3644     _getUpdatedContentBounds: function()
       
  3645     {
       
  3646         var bounds,
       
  3647             i,
       
  3648             shape,
       
  3649             queue = this._shapes,
       
  3650             box = {};
       
  3651         for(i in queue)
       
  3652         {
       
  3653             if(queue.hasOwnProperty(i))
       
  3654             {
       
  3655                 shape = queue[i];
       
  3656                 bounds = shape.getBounds();
       
  3657                 box.left = Y_LANG.isNumber(box.left) ? Math.min(box.left, bounds.left) : bounds.left;
       
  3658                 box.top = Y_LANG.isNumber(box.top) ? Math.min(box.top, bounds.top) : bounds.top;
       
  3659                 box.right = Y_LANG.isNumber(box.right) ? Math.max(box.right, bounds.right) : bounds.right;
       
  3660                 box.bottom = Y_LANG.isNumber(box.bottom) ? Math.max(box.bottom, bounds.bottom) : bounds.bottom;
       
  3661             }
       
  3662         }
       
  3663         box.left = Y_LANG.isNumber(box.left) ? box.left : 0;
       
  3664         box.top = Y_LANG.isNumber(box.top) ? box.top : 0;
       
  3665         box.right = Y_LANG.isNumber(box.right) ? box.right : 0;
       
  3666         box.bottom = Y_LANG.isNumber(box.bottom) ? box.bottom : 0;
       
  3667         this._contentBounds = box;
       
  3668         return box;
       
  3669     },
       
  3670 
       
  3671     /**
       
  3672      * Inserts shape on the top of the tree.
       
  3673      *
       
  3674      * @method _toFront
       
  3675      * @param {VMLShape} Shape to add.
       
  3676      * @private
       
  3677      */
       
  3678     _toFront: function(shape)
       
  3679     {
       
  3680         var contentNode = this._node;
       
  3681         if(shape instanceof Y.VMLShape)
       
  3682         {
       
  3683             shape = shape.get("node");
       
  3684         }
       
  3685         if(contentNode && shape)
       
  3686         {
       
  3687             contentNode.appendChild(shape);
       
  3688         }
       
  3689     },
       
  3690 
       
  3691     /**
       
  3692      * Inserts shape as the first child of the content node.
       
  3693      *
       
  3694      * @method _toBack
       
  3695      * @param {VMLShape} Shape to add.
       
  3696      * @private
       
  3697      */
       
  3698     _toBack: function(shape)
       
  3699     {
       
  3700         var contentNode = this._node,
       
  3701             targetNode;
       
  3702         if(shape instanceof Y.VMLShape)
       
  3703         {
       
  3704             shape = shape.get("node");
       
  3705         }
       
  3706         if(contentNode && shape)
       
  3707         {
       
  3708             targetNode = contentNode.firstChild;
       
  3709             if(targetNode)
       
  3710             {
       
  3711                 contentNode.insertBefore(shape, targetNode);
       
  3712             }
       
  3713             else
       
  3714             {
       
  3715                 contentNode.appendChild(shape);
       
  3716             }
       
  3717         }
       
  3718     }
       
  3719 });
       
  3720 Y.VMLGraphic = VMLGraphic;
       
  3721 
       
  3722 
       
  3723 
       
  3724 }, '3.10.3', {"requires": ["graphics"]});