text: /**
   * @author zz85 / http://www.lab4games.net/zz85/blog
   * @author alteredq / http://alteredqualia.com/
   *
   * For Text operations in three.js (See TextGeometry)
   *
   * It uses techniques used in:
   *
   *	Triangulation ported from AS3
   *		Simple Polygon Triangulation
   *		http://actionsnippet.com/?p=1462
   *
   * 	A Method to triangulate shapes with holes
   *		http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
   *
   */
  
  THREE.FontUtils = {
  
  	faces: {},
  
  	// Just for now. face[weight][style]
  
  	face: 'helvetiker',
  	weight: 'normal',
  	style: 'normal',
  	size: 150,
  	divisions: 10,
  
  	getFace: function () {
  
  		try {
  
  			return this.faces[ this.face.toLowerCase() ][ this.weight ][ this.style ];
  
  		} catch ( e ) {
  
  			throw "The font " + this.face + " with " + this.weight + " weight and " + this.style + " style is missing."
  
  		}
  
  	},
  
  	loadFace: function ( data ) {
  
  		var family = data.familyName.toLowerCase();
  
  		var ThreeFont = this;
  
  		ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {};
  
  		ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
  		ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  
  		ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  
  		return data;
  
  	},
  
  	drawText: function ( text ) {
  
  		// RenderText
  
  		var i,
  			face = this.getFace(),
  			scale = this.size / face.resolution,
  			offset = 0,
  			chars = String( text ).split( '' ),
  			length = chars.length;
  
  		var fontPaths = [];
  
  		for ( i = 0; i < length; i ++ ) {
  
  			var path = new THREE.Path();
  
  			var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path );
  			offset += ret.offset;
  
  			fontPaths.push( ret.path );
  
  		}
  
  		// get the width
  
  		var width = offset / 2;
  		//
  		// for ( p = 0; p < allPts.length; p++ ) {
  		//
  		// 	allPts[ p ].x -= width;
  		//
  		// }
  
  		//var extract = this.extractPoints( allPts, characterPts );
  		//extract.contour = allPts;
  
  		//extract.paths = fontPaths;
  		//extract.offset = width;
  
  		return { paths: fontPaths, offset: width };
  
  	},
  
  
  
  
  	extractGlyphPoints: function ( c, face, scale, offset, path ) {
  
  		var pts = [];
  
  		var b2 = THREE.ShapeUtils.b2;
  		var b3 = THREE.ShapeUtils.b3;
  
  		var i, i2, divisions,
  			outline, action, length,
  			scaleX, scaleY,
  			x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
  			laste,
  			glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
  
  		if ( ! glyph ) return;
  
  		if ( glyph.o ) {
  
  			outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
  			length = outline.length;
  
  			scaleX = scale;
  			scaleY = scale;
  
  			for ( i = 0; i < length; ) {
  
  				action = outline[ i ++ ];
  
  				//console.log( action );
  
  				switch ( action ) {
  
  				case 'm':
  
  					// Move To
  
  					x = outline[ i ++ ] * scaleX + offset;
  					y = outline[ i ++ ] * scaleY;
  
  					path.moveTo( x, y );
  					break;
  
  				case 'l':
  
  					// Line To
  
  					x = outline[ i ++ ] * scaleX + offset;
  					y = outline[ i ++ ] * scaleY;
  					path.lineTo( x, y );
  					break;
  
  				case 'q':
  
  					// QuadraticCurveTo
  
  					cpx  = outline[ i ++ ] * scaleX + offset;
  					cpy  = outline[ i ++ ] * scaleY;
  					cpx1 = outline[ i ++ ] * scaleX + offset;
  					cpy1 = outline[ i ++ ] * scaleY;
  
  					path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
  
  					laste = pts[ pts.length - 1 ];
  
  					if ( laste ) {
  
  						cpx0 = laste.x;
  						cpy0 = laste.y;
  
  						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  
  							var t = i2 / divisions;
  							b2( t, cpx0, cpx1, cpx );
  							b2( t, cpy0, cpy1, cpy );
  
  						}
  
  					}
  
  					break;
  
  				case 'b':
  
  					// Cubic Bezier Curve
  
  					cpx  = outline[ i ++ ] * scaleX + offset;
  					cpy  = outline[ i ++ ] * scaleY;
  					cpx1 = outline[ i ++ ] * scaleX + offset;
  					cpy1 = outline[ i ++ ] * scaleY;
  					cpx2 = outline[ i ++ ] * scaleX + offset;
  					cpy2 = outline[ i ++ ] * scaleY;
  
  					path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
  
  					laste = pts[ pts.length - 1 ];
  
  					if ( laste ) {
  
  						cpx0 = laste.x;
  						cpy0 = laste.y;
  
  						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  
  							var t = i2 / divisions;
  							b3( t, cpx0, cpx1, cpx2, cpx );
  							b3( t, cpy0, cpy1, cpy2, cpy );
  
  						}
  
  					}
  
  					break;
  
  				}
  
  			}
  
  		}
  
  
  
  		return { offset: glyph.ha * scale, path: path };
  
  	}
  
  };
  
  
  THREE.FontUtils.generateShapes = function ( text, parameters ) {
  
  	// Parameters
  
  	parameters = parameters || {};
  
  	var size = parameters.size !== undefined ? parameters.size : 100;
  	var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments : 4;
  
  	var font = parameters.font !== undefined ? parameters.font : 'helvetiker';
  	var weight = parameters.weight !== undefined ? parameters.weight : 'normal';
  	var style = parameters.style !== undefined ? parameters.style : 'normal';
  
  	THREE.FontUtils.size = size;
  	THREE.FontUtils.divisions = curveSegments;
  
  	THREE.FontUtils.face = font;
  	THREE.FontUtils.weight = weight;
  	THREE.FontUtils.style = style;
  
  	// Get a Font data json object
  
  	var data = THREE.FontUtils.drawText( text );
  
  	var paths = data.paths;
  	var shapes = [];
  
  	for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
  
  		Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
  
  	}
  
  	return shapes;
  
  };
  
  // To use the typeface.js face files, hook up the API
  
  THREE.typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };
  if ( typeof self !== 'undefined' ) self._typeface_js = THREE.typeface_js;