FontLoader.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import {
  2. FileLoader,
  3. Loader,
  4. ShapePath
  5. } from '../../../build/three.module.js';
  6. class FontLoader extends Loader {
  7. constructor( manager ) {
  8. super( manager );
  9. }
  10. load( url, onLoad, onProgress, onError ) {
  11. const scope = this;
  12. const loader = new FileLoader( this.manager );
  13. loader.setPath( this.path );
  14. loader.setRequestHeader( this.requestHeader );
  15. loader.setWithCredentials( scope.withCredentials );
  16. loader.load( url, function ( text ) {
  17. let json;
  18. try {
  19. json = JSON.parse( text );
  20. } catch ( e ) {
  21. console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
  22. json = JSON.parse( text.substring( 65, text.length - 2 ) );
  23. }
  24. const font = scope.parse( json );
  25. if ( onLoad ) onLoad( font );
  26. }, onProgress, onError );
  27. }
  28. parse( json ) {
  29. return new Font( json );
  30. }
  31. }
  32. //
  33. class Font {
  34. constructor( data ) {
  35. this.type = 'Font';
  36. this.data = data;
  37. }
  38. generateShapes( text, size = 100 ) {
  39. const shapes = [];
  40. const paths = createPaths( text, size, this.data );
  41. for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
  42. Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
  43. }
  44. return shapes;
  45. }
  46. }
  47. function createPaths( text, size, data ) {
  48. const chars = Array.from( text );
  49. const scale = size / data.resolution;
  50. const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
  51. const paths = [];
  52. let offsetX = 0, offsetY = 0;
  53. for ( let i = 0; i < chars.length; i ++ ) {
  54. const char = chars[ i ];
  55. if ( char === '\n' ) {
  56. offsetX = 0;
  57. offsetY -= line_height;
  58. } else {
  59. const ret = createPath( char, scale, offsetX, offsetY, data );
  60. offsetX += ret.offsetX;
  61. paths.push( ret.path );
  62. }
  63. }
  64. return paths;
  65. }
  66. function createPath( char, scale, offsetX, offsetY, data ) {
  67. const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
  68. if ( ! glyph ) {
  69. console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
  70. return;
  71. }
  72. const path = new ShapePath();
  73. let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
  74. if ( glyph.o ) {
  75. const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
  76. for ( let i = 0, l = outline.length; i < l; ) {
  77. const action = outline[ i ++ ];
  78. switch ( action ) {
  79. case 'm': // moveTo
  80. x = outline[ i ++ ] * scale + offsetX;
  81. y = outline[ i ++ ] * scale + offsetY;
  82. path.moveTo( x, y );
  83. break;
  84. case 'l': // lineTo
  85. x = outline[ i ++ ] * scale + offsetX;
  86. y = outline[ i ++ ] * scale + offsetY;
  87. path.lineTo( x, y );
  88. break;
  89. case 'q': // quadraticCurveTo
  90. cpx = outline[ i ++ ] * scale + offsetX;
  91. cpy = outline[ i ++ ] * scale + offsetY;
  92. cpx1 = outline[ i ++ ] * scale + offsetX;
  93. cpy1 = outline[ i ++ ] * scale + offsetY;
  94. path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
  95. break;
  96. case 'b': // bezierCurveTo
  97. cpx = outline[ i ++ ] * scale + offsetX;
  98. cpy = outline[ i ++ ] * scale + offsetY;
  99. cpx1 = outline[ i ++ ] * scale + offsetX;
  100. cpy1 = outline[ i ++ ] * scale + offsetY;
  101. cpx2 = outline[ i ++ ] * scale + offsetX;
  102. cpy2 = outline[ i ++ ] * scale + offsetY;
  103. path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
  104. break;
  105. }
  106. }
  107. }
  108. return { offsetX: glyph.ha * scale, path: path };
  109. }
  110. Font.prototype.isFont = true;
  111. export { FontLoader, Font };