@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
96 lines (95 loc) • 3.01 kB
JavaScript
;
import { ShapePath } from "three";
export class Font {
constructor(data) {
this.data = data;
this.isFont = true;
this.type = "font";
}
generateShapes(text, options = {}) {
if (options.size == null) {
options.size = 100;
}
if (options.isCCW == null) {
options.isCCW = false;
}
const allShapes = [];
const allPaths = createPaths(text, options.size, this.data);
for (const pathsForChar of allPaths) {
const shapesForChar = [];
for (const path of pathsForChar) {
const shapes = path.toShapes(options.isCCW);
shapesForChar.push(...shapes);
}
allShapes.push(shapesForChar);
}
return allShapes;
}
}
function createPaths(text, size, data) {
const chars = Array.from(text);
const scale = size / data.resolution;
const lineHeight = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
const allPaths = [];
let offsetX = 0, offsetY = 0;
for (let i = 0; i < chars.length; i++) {
const char = chars[i];
const pathsForChar = [];
if (char === "\n") {
offsetX = 0;
offsetY -= lineHeight;
} else {
const ret = createPath(char, scale, offsetX, offsetY, data);
if (ret) {
offsetX += ret.offsetX;
pathsForChar.push(ret.path);
}
}
allPaths.push(pathsForChar);
}
return allPaths;
}
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":
x = outline[i++] * scale + offsetX;
y = outline[i++] * scale + offsetY;
path.moveTo(x, y);
break;
case "l":
x = outline[i++] * scale + offsetX;
y = outline[i++] * scale + offsetY;
path.lineTo(x, y);
break;
case "q":
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":
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 };
}