184 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			184 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									FileLoader,
							 | 
						||
| 
								 | 
							
									Loader,
							 | 
						||
| 
								 | 
							
									ShapePath
							 | 
						||
| 
								 | 
							
								} from '../../three.module.min.js';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FontLoader extends Loader {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( manager ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										super( manager );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									load( url, onLoad, onProgress, onError ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const scope = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const loader = new FileLoader( this.manager );
							 | 
						||
| 
								 | 
							
										loader.setPath( this.path );
							 | 
						||
| 
								 | 
							
										loader.setRequestHeader( this.requestHeader );
							 | 
						||
| 
								 | 
							
										loader.setWithCredentials( this.withCredentials );
							 | 
						||
| 
								 | 
							
										loader.load( url, function ( text ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const font = scope.parse( JSON.parse( text ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( onLoad ) onLoad( font );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}, onProgress, onError );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									parse( json ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return new Font( json );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Font {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( data ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.isFont = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.type = 'Font';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.data = data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									generateShapes( text, size = 100 ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const shapes = [];
							 | 
						||
| 
								 | 
							
										const paths = createPaths( text, size, this.data );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											shapes.push( ...paths[ p ].toShapes() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return shapes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function createPaths( text, size, data ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const chars = Array.from( text );
							 | 
						||
| 
								 | 
							
									const scale = size / data.resolution;
							 | 
						||
| 
								 | 
							
									const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const paths = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									let offsetX = 0, offsetY = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for ( let i = 0; i < chars.length; i ++ ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const char = chars[ i ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( char === '\n' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											offsetX = 0;
							 | 
						||
| 
								 | 
							
											offsetY -= line_height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const ret = createPath( char, scale, offsetX, offsetY, data );
							 | 
						||
| 
								 | 
							
											offsetX += ret.offsetX;
							 | 
						||
| 
								 | 
							
											paths.push( ret.path );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return paths;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function createPath( char, scale, offsetX, offsetY, data ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( ! glyph ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const path = new ShapePath();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( glyph.o ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( let i = 0, l = outline.length; i < l; ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const action = outline[ i ++ ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											switch ( action ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case 'm': // moveTo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													x = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													y = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													path.moveTo( x, y );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case 'l': // lineTo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													x = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													y = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													path.lineTo( x, y );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case 'q': // quadraticCurveTo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													cpx = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													cpy = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
													cpx1 = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													cpy1 = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case 'b': // bezierCurveTo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													cpx = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													cpy = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
													cpx1 = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													cpy1 = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
													cpx2 = outline[ i ++ ] * scale + offsetX;
							 | 
						||
| 
								 | 
							
													cpy2 = outline[ i ++ ] * scale + offsetY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return { offsetX: glyph.ha * scale, path: path };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export { FontLoader, Font };
							 |