FontUtils.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /**
  2. * @author zz85 / http://www.lab4games.net/zz85/blog
  3. * @author alteredq / http://alteredqualia.com/
  4. *
  5. * For Text operations in three.js (See TextGeometry)
  6. *
  7. * It uses techniques used in:
  8. *
  9. * Triangulation ported from AS3
  10. * Simple Polygon Triangulation
  11. * http://actionsnippet.com/?p=1462
  12. *
  13. * A Method to triangulate shapes with holes
  14. * http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
  15. *
  16. */
  17. THREE.FontUtils = {
  18. faces: {},
  19. // Just for now. face[weight][style]
  20. face: 'helvetiker',
  21. weight: 'normal',
  22. style: 'normal',
  23. size: 150,
  24. divisions: 10,
  25. getFace: function () {
  26. try {
  27. return this.faces[ this.face.toLowerCase() ][ this.weight ][ this.style ];
  28. } catch ( e ) {
  29. throw "The font " + this.face + " with " + this.weight + " weight and " + this.style + " style is missing."
  30. }
  31. },
  32. loadFace: function ( data ) {
  33. var family = data.familyName.toLowerCase();
  34. var ThreeFont = this;
  35. ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {};
  36. ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
  37. ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  38. ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  39. return data;
  40. },
  41. drawText: function ( text ) {
  42. // RenderText
  43. var i,
  44. face = this.getFace(),
  45. scale = this.size / face.resolution,
  46. offset = 0,
  47. chars = String( text ).split( '' ),
  48. length = chars.length;
  49. var fontPaths = [];
  50. for ( i = 0; i < length; i ++ ) {
  51. var path = new THREE.Path();
  52. var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path );
  53. offset += ret.offset;
  54. fontPaths.push( ret.path );
  55. }
  56. // get the width
  57. var width = offset / 2;
  58. //
  59. // for ( p = 0; p < allPts.length; p++ ) {
  60. //
  61. // allPts[ p ].x -= width;
  62. //
  63. // }
  64. //var extract = this.extractPoints( allPts, characterPts );
  65. //extract.contour = allPts;
  66. //extract.paths = fontPaths;
  67. //extract.offset = width;
  68. return { paths: fontPaths, offset: width };
  69. },
  70. extractGlyphPoints: function ( c, face, scale, offset, path ) {
  71. var pts = [];
  72. var b2 = THREE.ShapeUtils.b2;
  73. var b3 = THREE.ShapeUtils.b3;
  74. var i, i2, divisions,
  75. outline, action, length,
  76. scaleX, scaleY,
  77. x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
  78. laste,
  79. glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
  80. if ( ! glyph ) return;
  81. if ( glyph.o ) {
  82. outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
  83. length = outline.length;
  84. scaleX = scale;
  85. scaleY = scale;
  86. for ( i = 0; i < length; ) {
  87. action = outline[ i ++ ];
  88. //console.log( action );
  89. switch ( action ) {
  90. case 'm':
  91. // Move To
  92. x = outline[ i ++ ] * scaleX + offset;
  93. y = outline[ i ++ ] * scaleY;
  94. path.moveTo( x, y );
  95. break;
  96. case 'l':
  97. // Line To
  98. x = outline[ i ++ ] * scaleX + offset;
  99. y = outline[ i ++ ] * scaleY;
  100. path.lineTo( x, y );
  101. break;
  102. case 'q':
  103. // QuadraticCurveTo
  104. cpx = outline[ i ++ ] * scaleX + offset;
  105. cpy = outline[ i ++ ] * scaleY;
  106. cpx1 = outline[ i ++ ] * scaleX + offset;
  107. cpy1 = outline[ i ++ ] * scaleY;
  108. path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
  109. laste = pts[ pts.length - 1 ];
  110. if ( laste ) {
  111. cpx0 = laste.x;
  112. cpy0 = laste.y;
  113. for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  114. var t = i2 / divisions;
  115. b2( t, cpx0, cpx1, cpx );
  116. b2( t, cpy0, cpy1, cpy );
  117. }
  118. }
  119. break;
  120. case 'b':
  121. // Cubic Bezier Curve
  122. cpx = outline[ i ++ ] * scaleX + offset;
  123. cpy = outline[ i ++ ] * scaleY;
  124. cpx1 = outline[ i ++ ] * scaleX + offset;
  125. cpy1 = outline[ i ++ ] * scaleY;
  126. cpx2 = outline[ i ++ ] * scaleX + offset;
  127. cpy2 = outline[ i ++ ] * scaleY;
  128. path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
  129. laste = pts[ pts.length - 1 ];
  130. if ( laste ) {
  131. cpx0 = laste.x;
  132. cpy0 = laste.y;
  133. for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  134. var t = i2 / divisions;
  135. b3( t, cpx0, cpx1, cpx2, cpx );
  136. b3( t, cpy0, cpy1, cpy2, cpy );
  137. }
  138. }
  139. break;
  140. }
  141. }
  142. }
  143. return { offset: glyph.ha * scale, path: path };
  144. }
  145. };
  146. THREE.FontUtils.generateShapes = function ( text, parameters ) {
  147. // Parameters
  148. parameters = parameters || {};
  149. var size = parameters.size !== undefined ? parameters.size : 100;
  150. var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments : 4;
  151. var font = parameters.font !== undefined ? parameters.font : 'helvetiker';
  152. var weight = parameters.weight !== undefined ? parameters.weight : 'normal';
  153. var style = parameters.style !== undefined ? parameters.style : 'normal';
  154. THREE.FontUtils.size = size;
  155. THREE.FontUtils.divisions = curveSegments;
  156. THREE.FontUtils.face = font;
  157. THREE.FontUtils.weight = weight;
  158. THREE.FontUtils.style = style;
  159. // Get a Font data json object
  160. var data = THREE.FontUtils.drawText( text );
  161. var paths = data.paths;
  162. var shapes = [];
  163. for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
  164. Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
  165. }
  166. return shapes;
  167. };
  168. // To use the typeface.js face files, hook up the API
  169. THREE.typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };
  170. if ( typeof self !== 'undefined' ) self._typeface_js = THREE.typeface_js;