@itwin/core-backend
Version:
iTwin.js backend components
143 lines • 5.7 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmbeddedFontFile = exports.CadFontFile = void 0;
exports.shxFontFileFromBlob = shxFontFileFromBlob;
exports.rscFontFileFromBlob = rscFontFileFromBlob;
exports.trueTypeFontFileFromFileName = trueTypeFontFileFromFileName;
const fs = require("fs");
const core_common_1 = require("@itwin/core-common");
const Symbols_1 = require("./Symbols");
const core_bentley_1 = require("@itwin/core-bentley");
const NativePlatform_1 = require("./NativePlatform");
class FontFileImpl {
[Symbols_1._implementationProhibited] = undefined;
faces;
get isEmbeddable() { return true; }
[Symbols_1._key];
[Symbols_1._faceProps];
constructor(faces) {
this.faces = faces.map((face) => {
return {
familyName: face.familyName,
isBold: face.faceName.startsWith("bold"),
isItalic: face.faceName.endsWith("italic"),
};
});
this[Symbols_1._faceProps] = faces;
// Sort the face props in canonical order so we can compare FontFiles for equivalent contents.
this[Symbols_1._faceProps].sort((a, b) => a.familyName.localeCompare(b.familyName) || a.faceName.localeCompare(b.faceName) || (0, core_bentley_1.compareNumbersOrUndefined)(a.subId, b.subId));
// Stringify the face props so that the key properties (and no other properties) appear in a canonical order. for trivial comparisons.
this[Symbols_1._key] = JSON.stringify(this[Symbols_1._faceProps], ["familyName", "faceName", "type", "subId"]);
}
}
/** Points to an OpenType font file on disk. */
class TrueTypeFontFile extends FontFileImpl {
#fileName;
#embeddable;
constructor(fileName, embeddable, faces) {
super(faces);
this.#fileName = fileName;
this.#embeddable = embeddable;
}
get type() { return core_common_1.FontType.TrueType; }
get isEmbeddable() { return this.#embeddable; }
[Symbols_1._getData]() {
return fs.readFileSync(this.#fileName);
}
}
/** Holds the binary representation of a SHX or RSC font in memory. */
class CadFontFile extends FontFileImpl {
#data;
#type;
constructor(data, type, faces) {
super(faces);
this.#data = data;
this.#type = type;
}
get type() { return this.#type; }
[Symbols_1._getData]() { return this.#data; }
}
exports.CadFontFile = CadFontFile;
/** Points to a font file in any format embedded in an iModel. */
class EmbeddedFontFile extends FontFileImpl {
// The value of the Id column for the row in the be_Prop table that embeds this font's data.
#db;
#id;
#type;
constructor(db, id, type, faces) {
super(faces);
this.#db = db;
this.#id = id;
this.#type = type;
}
get type() { return this.#type; }
[Symbols_1._getData]() {
const data = this.#db.queryFilePropertyBlob({
namespace: "dgn_Font",
name: "EmbeddedFaceData",
id: this.#id,
});
if (!data) {
throw new Error("Embedded font not found");
}
return data;
}
}
exports.EmbeddedFontFile = EmbeddedFontFile;
function shxFontFileFromBlob(args) {
if (args.familyName.length === 0) {
throw new Error("Font family name cannot be empty");
}
// An SHX file with fewer than 40 bytes isn't valid.
const minShxSize = 40;
const shxHeaders = [
"AutoCAD-86 unifont 1.0",
"AutoCAD-86 shapes 1.0",
"AutoCAD-86 shapes 1.1",
].map((shxHeader) => Array.from(shxHeader))
.map((chars) => new Uint8Array(chars.map((ch) => ch.charCodeAt(0))));
// See https://github.com/iTwin/imodel-native/blob/91f509c2175dc49ce1efcf5a906c9a9aa193451d/iModelCore/iModelPlatform/DgnCore/ShxFont.cpp#L44
function validateShx(blob) {
if (blob.length >= minShxSize) {
for (const header of shxHeaders) {
if (header.every((char, index) => char === blob[index])) {
return;
}
}
}
throw new Error("Failed to read font file");
}
validateShx(args.blob);
return new CadFontFile(args.blob, core_common_1.FontType.Shx, [{
faceName: "regular",
familyName: args.familyName,
type: core_common_1.FontType.Shx,
}]);
}
function rscFontFileFromBlob(args) {
if (args.familyName.length === 0) {
throw new Error("Font family name cannot be empty");
}
if (!NativePlatform_1.IModelNative.platform.isRscFontData(args.blob)) {
throw new Error("Failed to read font file");
}
return new CadFontFile(args.blob, core_common_1.FontType.Rsc, [{
faceName: "regular",
familyName: args.familyName,
type: core_common_1.FontType.Rsc,
encoding: args.encoding,
}]);
}
function trueTypeFontFileFromFileName(fileName) {
const metadata = NativePlatform_1.IModelNative.platform.getTrueTypeFontMetadata(fileName);
if (metadata.faces.length === 0) {
// The input was almost certainly not a TrueType font file.
throw new Error("Failed to read font file");
}
return new TrueTypeFontFile(fileName, metadata.embeddable, metadata.faces);
}
//# sourceMappingURL=FontFileImpl.js.map
;