Skip to content

Commit 2297ce5

Browse files
authored
Merge pull request #16706 from Mugen87/dev30
JSM: Added module and TS file for TTFLoader.
2 parents 34cad85 + 743f639 commit 2297ce5

File tree

5 files changed

+226
-1
lines changed

5 files changed

+226
-1
lines changed

docs/manual/en/introduction/Import-via-modules.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ <h2>Importable Examples</h2>
190190
<li>SVGLoader</li>
191191
<li>TDSLoader</li>
192192
<li>TGALoader</li>
193+
<li>TTFLoader</li>
193194
<li>VRMLLoader</li>
194195
<li>VTKLoader</li>
195196
</ul>

examples/js/loaders/TTFLoader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ THREE.TTFLoader.prototype = {
6868

6969
}
7070

71-
glyph.path.commands.forEach( function ( command, i ) {
71+
glyph.path.commands.forEach( function ( command ) {
7272

7373
if ( command.type.toLowerCase() === 'c' ) {
7474

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {
2+
BufferGeometry,
3+
LoadingManager
4+
} from '../../../src/Three';
5+
6+
export class TTFLoader {
7+
constructor(manager?: LoadingManager);
8+
manager: LoadingManager;
9+
path: string;
10+
reversed: boolean;
11+
12+
load(url: string, onLoad: (json: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
13+
setPath(path: string): this;
14+
15+
parse(arraybuffer: ArrayBuffer): object;
16+
}

examples/jsm/loaders/TTFLoader.js

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/**
2+
* @author gero3 / https://github.com/gero3
3+
* @author tentone / https://github.com/tentone
4+
*
5+
* Requires opentype.js to be included in the project.
6+
* Loads TTF files and converts them into typeface JSON that can be used directly
7+
* to create THREE.Font objects.
8+
*/
9+
10+
import {
11+
DefaultLoadingManager,
12+
FileLoader
13+
} from "../../../build/three.module.js";
14+
15+
var TTFLoader = function ( manager ) {
16+
17+
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
18+
this.reversed = false;
19+
20+
};
21+
22+
TTFLoader.prototype = {
23+
24+
constructor: TTFLoader,
25+
26+
load: function ( url, onLoad, onProgress, onError ) {
27+
28+
var scope = this;
29+
30+
var loader = new FileLoader( this.manager );
31+
loader.setPath( this.path );
32+
loader.setResponseType( 'arraybuffer' );
33+
loader.load( url, function ( buffer ) {
34+
35+
onLoad( scope.parse( buffer ) );
36+
37+
}, onProgress, onError );
38+
39+
},
40+
41+
setPath: function ( value ) {
42+
43+
this.path = value;
44+
return this;
45+
46+
},
47+
48+
parse: function ( arraybuffer ) {
49+
50+
function convert( font, reversed ) {
51+
52+
var round = Math.round;
53+
54+
var glyphs = {};
55+
var scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 );
56+
57+
for ( var i = 0; i < font.glyphs.length; i ++ ) {
58+
59+
var glyph = font.glyphs.glyphs[ i ];
60+
61+
if ( glyph.unicode !== undefined ) {
62+
63+
var token = {
64+
ha: round( glyph.advanceWidth * scale ),
65+
x_min: round( glyph.xMin * scale ),
66+
x_max: round( glyph.xMax * scale ),
67+
o: ''
68+
};
69+
70+
if ( reversed ) {
71+
72+
glyph.path.commands = reverseCommands( glyph.path.commands );
73+
74+
}
75+
76+
glyph.path.commands.forEach( function ( command ) {
77+
78+
if ( command.type.toLowerCase() === 'c' ) {
79+
80+
command.type = 'b';
81+
82+
}
83+
84+
token.o += command.type.toLowerCase() + ' ';
85+
86+
if ( command.x !== undefined && command.y !== undefined ) {
87+
88+
token.o += round( command.x * scale ) + ' ' + round( command.y * scale ) + ' ';
89+
90+
}
91+
92+
if ( command.x1 !== undefined && command.y1 !== undefined ) {
93+
94+
token.o += round( command.x1 * scale ) + ' ' + round( command.y1 * scale ) + ' ';
95+
96+
}
97+
98+
if ( command.x2 !== undefined && command.y2 !== undefined ) {
99+
100+
token.o += round( command.x2 * scale ) + ' ' + round( command.y2 * scale ) + ' ';
101+
102+
}
103+
104+
} );
105+
106+
glyphs[ String.fromCharCode( glyph.unicode ) ] = token;
107+
108+
}
109+
110+
}
111+
112+
return {
113+
glyphs: glyphs,
114+
familyName: font.familyName,
115+
ascender: round( font.ascender * scale ),
116+
descender: round( font.descender * scale ),
117+
underlinePosition: font.tables.post.underlinePosition,
118+
underlineThickness: font.tables.post.underlineThickness,
119+
boundingBox: {
120+
xMin: font.tables.head.xMin,
121+
xMax: font.tables.head.xMax,
122+
yMin: font.tables.head.yMin,
123+
yMax: font.tables.head.yMax
124+
},
125+
resolution: 1000,
126+
original_font_information: font.tables.name
127+
};
128+
129+
}
130+
131+
function reverseCommands( commands ) {
132+
133+
var paths = [];
134+
var path;
135+
136+
commands.forEach( function ( c ) {
137+
138+
if ( c.type.toLowerCase() === 'm' ) {
139+
140+
path = [ c ];
141+
paths.push( path );
142+
143+
} else if ( c.type.toLowerCase() !== 'z' ) {
144+
145+
path.push( c );
146+
147+
}
148+
149+
} );
150+
151+
var reversed = [];
152+
153+
paths.forEach( function ( p ) {
154+
155+
var result = {
156+
type: 'm',
157+
x: p[ p.length - 1 ].x,
158+
y: p[ p.length - 1 ].y
159+
};
160+
161+
reversed.push( result );
162+
163+
for ( var i = p.length - 1; i > 0; i -- ) {
164+
165+
var command = p[ i ];
166+
var result = { type: command.type };
167+
168+
if ( command.x2 !== undefined && command.y2 !== undefined ) {
169+
170+
result.x1 = command.x2;
171+
result.y1 = command.y2;
172+
result.x2 = command.x1;
173+
result.y2 = command.y1;
174+
175+
} else if ( command.x1 !== undefined && command.y1 !== undefined ) {
176+
177+
result.x1 = command.x1;
178+
result.y1 = command.y1;
179+
180+
}
181+
182+
result.x = p[ i - 1 ].x;
183+
result.y = p[ i - 1 ].y;
184+
reversed.push( result );
185+
186+
}
187+
188+
} );
189+
190+
return reversed;
191+
192+
}
193+
194+
if ( typeof opentype === 'undefined' ) {
195+
196+
console.warn( 'THREE.TTFLoader: The loader requires opentype.js. Make sure it\'s included before using the loader.' );
197+
return null;
198+
199+
}
200+
201+
return convert( opentype.parse( arraybuffer ), this.reversed );
202+
203+
}
204+
205+
};
206+
207+
export { TTFLoader };

utils/modularize.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ var files = [
9494
{ path: 'loaders/SVGLoader.js', dependencies: [], ignoreList: [] },
9595
{ path: 'loaders/TDSLoader.js', dependencies: [], ignoreList: [] },
9696
{ path: 'loaders/TGALoader.js', dependencies: [], ignoreList: [] },
97+
{ path: 'loaders/TTFLoader.js', dependencies: [], ignoreList: [ 'Font' ] },
9798
{ path: 'loaders/VRMLLoader.js', dependencies: [], ignoreList: [] },
9899
{ path: 'loaders/VTKLoader.js', dependencies: [], ignoreList: [] },
99100

0 commit comments

Comments
 (0)