You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
3.5 KiB
JavaScript
166 lines
3.5 KiB
JavaScript
11 months ago
|
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 }
|