| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 | import {	FileLoader,	Loader} from '../../../build/three.module.js';import { opentype } from '../libs/opentype.module.min.js';/** * Requires opentype.js to be included in the project. * Loads TTF files and converts them into typeface JSON that can be used directly * to create THREE.Font objects. */class TTFLoader extends Loader {	constructor( manager ) {		super( manager );		this.reversed = false;	}	load( url, onLoad, onProgress, onError ) {		const scope = this;		const loader = new FileLoader( this.manager );		loader.setPath( this.path );		loader.setResponseType( 'arraybuffer' );		loader.setRequestHeader( this.requestHeader );		loader.setWithCredentials( this.withCredentials );		loader.load( url, function ( buffer ) {			try {				onLoad( scope.parse( buffer ) );			} catch ( e ) {				if ( onError ) {					onError( e );				} else {					console.error( e );				}				scope.manager.itemError( url );			}		}, onProgress, onError );	}	parse( arraybuffer ) {		function convert( font, reversed ) {			const round = Math.round;			const glyphs = {};			const scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 );			const glyphIndexMap = font.encoding.cmap.glyphIndexMap;			const unicodes = Object.keys( glyphIndexMap );			for ( let i = 0; i < unicodes.length; i ++ ) {				const unicode = unicodes[ i ];				const glyph = font.glyphs.glyphs[ glyphIndexMap[ unicode ] ];				if ( unicode !== undefined ) {					const token = {						ha: round( glyph.advanceWidth * scale ),						x_min: round( glyph.xMin * scale ),						x_max: round( glyph.xMax * scale ),						o: ''					};					if ( reversed ) {						glyph.path.commands = reverseCommands( glyph.path.commands );					}					glyph.path.commands.forEach( function ( command ) {						if ( command.type.toLowerCase() === 'c' ) {							command.type = 'b';						}						token.o += command.type.toLowerCase() + ' ';						if ( command.x !== undefined && command.y !== undefined ) {							token.o += round( command.x * scale ) + ' ' + round( command.y * scale ) + ' ';						}						if ( command.x1 !== undefined && command.y1 !== undefined ) {							token.o += round( command.x1 * scale ) + ' ' + round( command.y1 * scale ) + ' ';						}						if ( command.x2 !== undefined && command.y2 !== undefined ) {							token.o += round( command.x2 * scale ) + ' ' + round( command.y2 * scale ) + ' ';						}					} );					glyphs[ String.fromCodePoint( glyph.unicode ) ] = token;				}			}			return {				glyphs: glyphs,				familyName: font.getEnglishName( 'fullName' ),				ascender: round( font.ascender * scale ),				descender: round( font.descender * scale ),				underlinePosition: font.tables.post.underlinePosition,				underlineThickness: font.tables.post.underlineThickness,				boundingBox: {					xMin: font.tables.head.xMin,					xMax: font.tables.head.xMax,					yMin: font.tables.head.yMin,					yMax: font.tables.head.yMax				},				resolution: 1000,				original_font_information: font.tables.name			};		}		function reverseCommands( commands ) {			const paths = [];			let path;			commands.forEach( function ( c ) {				if ( c.type.toLowerCase() === 'm' ) {					path = [ c ];					paths.push( path );				} else if ( c.type.toLowerCase() !== 'z' ) {					path.push( c );				}			} );			const reversed = [];			paths.forEach( function ( p ) {				const result = {					type: 'm',					x: p[ p.length - 1 ].x,					y: p[ p.length - 1 ].y				};				reversed.push( result );				for ( let i = p.length - 1; i > 0; i -- ) {					const command = p[ i ];					const result = { type: command.type };					if ( command.x2 !== undefined && command.y2 !== undefined ) {						result.x1 = command.x2;						result.y1 = command.y2;						result.x2 = command.x1;						result.y2 = command.y1;					} else if ( command.x1 !== undefined && command.y1 !== undefined ) {						result.x1 = command.x1;						result.y1 = command.y1;					}					result.x = p[ i - 1 ].x;					result.y = p[ i - 1 ].y;					reversed.push( result );				}			} );			return reversed;		}		if ( typeof opentype === 'undefined' ) {			console.warn( 'THREE.TTFLoader: The loader requires opentype.js. Make sure it\'s included before using the loader.' );			return null;		}		return convert( opentype.parse( arraybuffer ), this.reversed ); // eslint-disable-line no-undef	}}export { TTFLoader };
 |