You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

276 lines
5.4 KiB

/**
* @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;