/**
* @module Pixi Flash
* @namespace pixiflash
*/
(function(undefined)
{
var PixiGraphics = PIXI.Graphics,
utils = pixiflash.utils,
DisplayObject = pixiflash.DisplayObject;
/**
* The class to emulate createjs.Graphics
* @class Graphics
* @extends PIXI.Graphics
* @constructor
*/
var Graphics = function()
{
PixiGraphics.call(this);
DisplayObject.call(this);
};
// Extend PIXI.Sprite
var s = PixiGraphics.prototype;
var p = Graphics.prototype = Object.create(s);
// Mixin the display object
DisplayObject.mixin(p);
//constructor for backwards/Flash exporting compatibility
p.initialize = Graphics;
// Assign to namespace
pixiflash.Graphics = Graphics;
/**
* Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}.
* @property {Object} BASE_64
* @static
* @final
* @private
* @readonly
**/
var BASE_64 = {
"A":0,"B":1,"C":2,"D":3,"E":4,"F":5,"G":6,"H":7,"I":8,
"J":9,"K":10,"L":11,"M":12,"N":13,"O":14,"P":15,"Q":16,"R":17,"S":18,
"T":19,"U":20,"V":21,"W":22,"X":23,"Y":24,"Z":25,"a":26,"b":27,"c":28,
"d":29,"e":30,"f":31,"g":32,"h":33,"i":34,"j":35,"k":36,"l":37,"m":38,
"n":39,"o":40,"p":41,"q":42,"r":43,"s":44,"t":45,"u":46,"v":47,"w":48,
"x":49,"y":50,"z":51,"0":52,"1":53,"2":54,"3":55,"4":56,"5":57,"6":58,
"7":59,"8":60,"9":61,"+":62,"/":63
};
/**
* Moves the drawing point to the specified position. A tiny API method "mt" also exists.
* @method mt
* @param {Number} x The x coordinate the drawing point should move to.
* @param {Number} y The y coordinate the drawing point should move to.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls).
**/
p.mt = p.moveTo;
/**
* Draws a line from the current drawing point to the specified position, which become the new current drawing
* point. A tiny API method "lt" also exists.
*
* For detailed information, read the
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#complex-shapes-(paths)">
* whatwg spec</a>.
* @method lt
* @param {Number} x The x coordinate the drawing point should draw to.
* @param {Number} y The y coordinate the drawing point should draw to.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.lt = function(x, y)
{
return this.op().lineTo(x, y);
};
/**
* Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x,
* cp2y). For detailed information, read the
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-beziercurveto">
* whatwg spec</a>. A tiny API method "bt" also exists.
* @method bt
* @param {Number} cp1x
* @param {Number} cp1y
* @param {Number} cp2x
* @param {Number} cp2y
* @param {Number} x
* @param {Number} y
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.bt = function(cp1x, cp1y, cp2x, cp2y, x, y)
{
return this.op().bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
};
/**
* Shortcut to drawRect.
* @method dr
* @param {Number} x
* @param {Number} y
* @param {Number} w Width of the rectangle
* @param {Number} h Height of the rectangle
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
/**
* Shortcut to drawRect.
* @method r
* @param {Number} x
* @param {Number} y
* @param {Number} w Width of the rectangle
* @param {Number} h Height of the rectangle
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
p.dr = p.r = p.drawRect;
/**
* Shortcut to drawRoundedRect.
* @method rr
* @param {Number} x
* @param {Number} y
* @param {Number} w Width of the rectangle
* @param {Number} h Height of the rectangle
* @param {Number} radius The corner radius
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
p.rr = p.drawRoundedRect;
/**
* Shortcut to drawRoundRectComplex. Not supported by pixiflash
* @method rc
* @param {Number} x
* @param {Number} y
* @param {Number} w Width of the rectangle
* @param {Number} h Height of the rectangle
* @param {Number} radius The corner radius
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
p.rc = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL)
{
if (DEBUG)
{
console.warn("Complex rounded rectangles not supported");
}
return this.rr(x, y, w, h, radiusTL);
};
/**
* Shortcut to drawCircle.
* @method dc
* @param {Number} x x coordinate center point of circle.
* @param {Number} y y coordinate center point of circle.
* @param {Number} radius Radius of circle.
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
p.dc = p.drawCircle;
/**
* Shortcut to arc.
* @method a
* @param {Number} x
* @param {Number} y
* @param {Number} radius
* @param {Number} startAngle Measured in radians.
* @param {Number} endAngle Measured in radians.
* @param {Boolean} anticlockwise
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @protected
* @chainable
**/
p.a = function(x, y, radius, startAngle, endAngle, anticlockwise)
{
return this.op().arc(x, y, radius, startAngle, endAngle, anticlockwise);
};
/**
* Shortcut to arcTo.
* @method at
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @param {Number} radius
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
* @chainable
* @protected
**/
p.at = function(x1, y1, x2, y2, radius)
{
return this.op().arcTo(x1, y1, x2, y2, radius);
};
/**
* Override the draw ellipse method
* @method de
* @param {Number} x [description]
* @param {Number} y [description]
* @param {Number} width [description]
* @param {Number} height [description]
*/
p.de = function(x, y, width, height)
{
// Math conversion
return this.drawEllipse(x + width / 2, y + height / 2, width / 2, height / 2);
};
/**
* Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed
* information, read the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-quadraticcurveto">
* whatwg spec</a>. A tiny API method "qt" also exists.
* @method qt
* @param {Number} cpx
* @param {Number} cpy
* @param {Number} x
* @param {Number} y
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.qt = function(cpx, cpy, x, y)
{
return this.op().quadraticCurveTo(cpx, cpy, x, y);
};
/**
* Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified
* since the fill or stroke was last set. A tiny API method "cp" also exists.
* @method cp
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.cp = function()
{
var currentPath = this.currentPath;
if (currentPath && currentPath.shape)
{
currentPath.shape.closed = true;
}
return this;
};
/**
* Open path method for drawing, ensure that the draw shape is not closed
* @method op
* @private
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
*/
p.op = function()
{
// Ensure that the draw shape is not closed
var currentPath = this.currentPath;
if (currentPath && currentPath.shape)
{
currentPath.shape.closed = false;
}
return this;
};
/**
* Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists.
* @method f
* @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to
* null will result in no fill.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.f = function(color)
{
if (color)
{
var rgb = utils.colorToHex(color);
var a = alphaFromColor(color);
this.beginFill(rgb, a);
}
else
{
this.beginFill(0, 0);
}
return this;
};
/**
* Placeholder method for a linear fill. Pixi does not support linear fills,
* so we just pick the first color in colorArray
* @method lf
* @param {Array} colorArray An array of CSS compatible color values @see `f`
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.lf = function(colorArray)
{
if (DEBUG)
{
console.warn("Linear gradient fills are not supported");
}
return this.f(colorArray[0]);
};
/**
* Placeholder method for a radial fill. Pixi does not support radial fills,
* so we just pick the first color in colorArray
* @method rf
* @param {Array} colorArray An array of CSS compatible color values @see `f`
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.rf = function(colorArray)
{
if (DEBUG)
{
console.warn("Radial gradient fills are not supported");
}
return this.f(colorArray[0]);
};
/**
* Placeholder method for a beginBitmapFill. Pixi does not support bitmap fills.
* @method bf
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.bf = function()
{
if (DEBUG)
{
console.warn("Bitmap fills are not supported");
}
return this.f("#000000");
};
/**
* Placeholder method for a setStrokeDash. Pixi does not support dashed strokes.
* @method sd
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.sd = function()
{
if (DEBUG)
{
console.warn("Dashed strokes are not supported");
}
return this;
};
/**
* Placeholder method for a beginBitmapStroke. Pixi does not support bitmap strokes.
* @method bs
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.bs = function()
{
if (DEBUG)
{
console.warn("Bitmap strokes are not supported");
}
return this;
};
/**
* Placeholder method for a beginLinearGradientStroke. Pixi does not support gradient strokes.
* @method ls
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.ls = function()
{
if (DEBUG)
{
console.warn("Linear gradient strokes are not supported");
}
return this;
};
/**
* Placeholder method for a beginRadialGradientStroke. Pixi does not support gradient strokes.
* @method rs
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.rs = function()
{
if (DEBUG)
{
console.warn("Radial gradient strokes are not supported");
}
return this;
};
/**
* Sets the stroke style. Like all drawing methods, this can be chained, so you can define
* the stroke style and color in a single line of code like so:
*
* myGraphics.setStrokeStyle(8,"round").beginStroke("#F00");
*
* A tiny API method "ss" also exists.
* @method ss
* @param {Number} thickness The width of the stroke.
* @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt,
* round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with
* the tiny API.
* @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet.
* One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel)
* for use with the tiny API.
* @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which
* controls at what point a mitered joint will be clipped.
* @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless
* of active transformations.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.ss = function(thickness, caps, joints, miterLimit, ignoreScale)
{
this.lineWidth = thickness;
return this;
};
/**
* Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists.
* @method s
* @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to
* null will result in no stroke.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.s = function(color)
{
if (color)
{
this.lineColor = utils.colorToHex(color);
this.lineAlpha = 1;
}
return this;
};
/**
* Decodes a compact encoded path string into a series of draw instructions.
* This format is not intended to be human readable, and is meant for use by authoring tools.
* The format uses a base64 character set, with each character representing 6 bits, to define a series of draw
* commands.
*
* Each command is comprised of a single "header" character followed by a variable number of alternating x and y
* position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the
* type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4
* indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the
* latter. Bits 5 and 6 are currently unused.
*
* Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo)
* parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the
* 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed
* by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the
* case of move operations which are absolute, this value is a delta from the previous x or y position (as
* appropriate).
*
* For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0.
* <br />A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per
* parameter.
* <br />n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits
* indicate 1500 tenths of a pixel.
* <br />AA - 000000000000. Absolute y position of 0.
* <br />I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter.
* <br />Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to
* provide an absolute position of +150.0px.
* <br />AAA - 000000000000000000. A y delta value of 0.
*
* A tiny API method "p" also exists.
* @method p
* @param {String} str The path string to decode.
* @return {pixiflash.Graphics} The Graphics instance the method is called on (useful for chaining calls.)
**/
p.p = function(str)
{
// Masking implentation doesn't call f(), must beginFill
if (!this.filling)
{
this.beginFill();
}
var instructions = [
this.mt,
this.lt,
this.qt,
this.bt,
this.cp
];
var paramCount = [2, 2, 4, 6, 0];
var i=0, l=str.length;
var params = [];
var x=0, y=0;
var base64 = BASE_64;
while (i<l)
{
var c = str.charAt(i);
var n = base64[c];
var fi = n>>3; // highest order bits 1-3 code for operation.
var f = instructions[fi];
// check that we have a valid instruction & that the unused bits are empty:
if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); }
var pl = paramCount[fi];
if (!fi) { x=y=0; } // move operations reset the position.
params.length = 0;
i++;
var charCount = (n>>2&1)+2; // 4th header bit indicates number size for this operation.
for (var p=0; p<pl; p++)
{
var num = base64[str.charAt(i)];
var sign = (num>>5) ? -1 : 1;
num = ((num&31)<<6)|(base64[str.charAt(i+1)]);
if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); }
num = sign*num/10;
if (p%2) { x = (num += x); }
else { y = (num += y); }
params[p] = num;
i += charCount;
}
f.apply(this,params);
}
return this;
};
/**
* Get the alpha color from color string
* @method alphaFromColor
* @private
* @param {String} color
*/
var alphaFromColor = function(color)
{
if (/^rgba\(/.test(color))
{
return parseFloat(color.substring(
color.lastIndexOf(',') + 1,
color.lastIndexOf(')')
));
}
return 1;
};
}());