first commit
This commit is contained in:
		
							
								
								
									
										214
									
								
								public/sdk/three/jsm/loaders/TTFLoader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								public/sdk/three/jsm/loaders/TTFLoader.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,214 @@ | ||||
| import { | ||||
| 	FileLoader, | ||||
| 	Loader | ||||
| } from 'three'; | ||||
| import opentype from '../libs/opentype.module.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; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		return convert( opentype.parse( arraybuffer ), this.reversed ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { TTFLoader }; | ||||
		Reference in New Issue
	
	Block a user