import { FileLoader, Loader, ShapePath } from './three.module' 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(scope.withCredentials) loader.load( url, function (text) { let json try { json = JSON.parse(text) } catch (e) { console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ) json = JSON.parse(text.substring(65, text.length - 2)) } const font = scope.parse(json) if (onLoad) onLoad(font) }, onProgress, onError ) } parse(json) { return new Font(json) } } // class Font { constructor(data) { 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++) { Array.prototype.push.apply(shapes, 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 } } Font.prototype.isFont = true export { FontLoader, Font }