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