three-stdlib
Version:
stand-alone library of threejs examples
133 lines (132 loc) • 4.35 kB
JavaScript
import { Loader, FileLoader } from "three";
import { parse as parseBuffer } from "../libs/opentype.js";
class TTFLoader extends Loader {
constructor(manager) {
super(manager);
this.reversed = false;
}
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(parseBuffer(buffer));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(arraybuffer) {
function convert(font, reversed) {
const round = Math.round;
const glyphs = {};
const scale = 1e5 / ((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 !== void 0) {
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 !== void 0 && command.y !== void 0) {
token.o += round(command.x * scale) + " " + round(command.y * scale) + " ";
}
if (command.x1 !== void 0 && command.y1 !== void 0) {
token.o += round(command.x1 * scale) + " " + round(command.y1 * scale) + " ";
}
if (command.x2 !== void 0 && command.y2 !== void 0) {
token.o += round(command.x2 * scale) + " " + round(command.y2 * scale) + " ";
}
});
glyphs[String.fromCodePoint(glyph.unicode)] = token;
}
}
return {
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: 1e3,
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 result2 = { type: command.type };
if (command.x2 !== void 0 && command.y2 !== void 0) {
result2.x1 = command.x2;
result2.y1 = command.y2;
result2.x2 = command.x1;
result2.y2 = command.y1;
} else if (command.x1 !== void 0 && command.y1 !== void 0) {
result2.x1 = command.x1;
result2.y1 = command.y1;
}
result2.x = p[i - 1].x;
result2.y = p[i - 1].y;
reversed.push(result2);
}
});
return reversed;
}
return convert(parseBuffer(arraybuffer), this.reversed);
}
}
export {
TTFLoader
};
//# sourceMappingURL=TTFLoader.js.map