📄 TTFLoader.js
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 4 |
🧱 Classes | 1 |
📦 Imports | 3 |
📊 Variables & Constants | 15 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 examples/jsm/loaders/TTFLoader.js
📦 Imports¶
Name | Source |
---|---|
FileLoader |
three |
Loader |
three |
opentype |
../libs/opentype.module.js |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
scope |
this |
let/var | this |
✗ |
loader |
any |
let/var | new FileLoader( this.manager ) |
✗ |
round |
(x: number) => number |
let/var | Math.round |
✗ |
glyphs |
{} |
let/var | {} |
✗ |
scale |
number |
let/var | ( 100000 ) / ( ( font.unitsPerEm \|\| 2048 ) * 72 ) |
✗ |
glyphIndexMap |
any |
let/var | font.encoding.cmap.glyphIndexMap |
✗ |
unicode |
string |
let/var | unicodes[ i ] |
✗ |
glyph |
any |
let/var | font.glyphs.glyphs[ glyphIndexMap[ unicode ] ] |
✗ |
token |
{ ha: number; x_min: number; x_max: n... |
let/var | { ha: round( glyph.advanceWidth * scale ), x_min: round( glyph.xMin * scale )... |
✗ |
paths |
any[] |
let/var | [] |
✗ |
path |
any |
let/var | *not shown* |
✗ |
reversed |
any[] |
let/var | [] |
✗ |
result |
{ type: string; x: any; y: any; } |
let/var | { type: 'm', x: p[ p.length - 1 ].x, y: p[ p.length - 1 ].y } |
✗ |
command |
any |
let/var | p[ i ] |
✗ |
result |
{ type: any; } |
let/var | { type: command.type } |
✗ |
Functions¶
TTFLoader.load(url: string, onLoad: (arg0: any) => any, onProgress: onProgressCallback, onError: onErrorCallback): void
¶
JSDoc:
/**
* Starts loading from the given URL and passes the loaded TTF asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
Parameters:
url
string
onLoad
(arg0: any) => any
onProgress
onProgressCallback
onError
onErrorCallback
Returns: void
Calls:
loader.setPath
loader.setResponseType
loader.setRequestHeader
loader.setWithCredentials
loader.load
onLoad
scope.parse
onError
console.error
scope.manager.itemError
Code
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 );
}
TTFLoader.parse(arraybuffer: ArrayBuffer): any
¶
JSDoc:
/**
* Parses the given TTF data and returns a JSON for creating a font.
*
* @param {ArrayBuffer} arraybuffer - The raw TTF data as an array buffer.
* @return {Object} The result JSON.
*/
Parameters:
arraybuffer
ArrayBuffer
Returns: any
Calls:
Object.keys
round
reverseCommands
glyph.path.commands.forEach
command.type.toLowerCase
Array.isArray
glyph.unicodes.forEach
String.fromCodePoint
font.getEnglishName
commands.forEach
c.type.toLowerCase
paths.push
path.push
paths.forEach
reversed.push
convert
opentype.parse
Code
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 ) + ' ';
}
} );
if ( Array.isArray( glyph.unicodes ) && glyph.unicodes.length > 0 ) {
glyph.unicodes.forEach( function ( unicode ) {
glyphs[ String.fromCodePoint( unicode ) ] = token;
} );
} else {
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 );
}
convert(font: any, reversed: any): { glyphs: {}; familyName: any; ascender: number; descender: number; underlinePosition: any; underlineThickness: any; boundingBox: { xMin: any; xMax: any; yMin: any; yMax: any; }; resolution: number; original_font_information: any; }
¶
Parameters:
font
any
reversed
any
Returns: { glyphs: {}; familyName: any; ascender: number; descender: number; underlinePosition: any; underlineThickness: any; boundingBox: { xMin: any; xMax: any; yMin: any; yMax: any; }; resolution: number; original_font_information: any; }
Calls:
Object.keys
round
reverseCommands
glyph.path.commands.forEach
command.type.toLowerCase
Array.isArray
glyph.unicodes.forEach
String.fromCodePoint
font.getEnglishName
Code
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 ) + ' ';
}
} );
if ( Array.isArray( glyph.unicodes ) && glyph.unicodes.length > 0 ) {
glyph.unicodes.forEach( function ( unicode ) {
glyphs[ String.fromCodePoint( unicode ) ] = token;
} );
} else {
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
};
}
reverseCommands(commands: any): any[]
¶
Parameters:
commands
any
Returns: any[]
Calls:
commands.forEach
c.type.toLowerCase
paths.push
path.push
paths.forEach
reversed.push
Code
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;
}
Classes¶
TTFLoader
¶
Class Code
class TTFLoader extends Loader {
/**
* Constructs a new TTF loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {
super( manager );
/**
* Whether the TTF commands should be reversed or not.
*
* @type {boolean}
* @default false
*/
this.reversed = false;
}
/**
* Starts loading from the given URL and passes the loaded TTF asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
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 );
}
/**
* Parses the given TTF data and returns a JSON for creating a font.
*
* @param {ArrayBuffer} arraybuffer - The raw TTF data as an array buffer.
* @return {Object} The result JSON.
*/
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 ) + ' ';
}
} );
if ( Array.isArray( glyph.unicodes ) && glyph.unicodes.length > 0 ) {
glyph.unicodes.forEach( function ( unicode ) {
glyphs[ String.fromCodePoint( unicode ) ] = token;
} );
} else {
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 );
}
}
Methods¶
load(url: string, onLoad: (arg0: any) => any, onProgress: onProgressCallback, onError: onErrorCallback): void
¶
Code
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: ArrayBuffer): any
¶
Code
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 ) + ' ';
}
} );
if ( Array.isArray( glyph.unicodes ) && glyph.unicodes.length > 0 ) {
glyph.unicodes.forEach( function ( unicode ) {
glyphs[ String.fromCodePoint( unicode ) ] = token;
} );
} else {
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 );
}