Skip to content

Commit

Permalink
Emit error events rather than throwing (#387)
Browse files Browse the repository at this point in the history
### Changelog
Added an `"error"` event to the LabelPool and FontManager.

### Docs

None

### Description

Rather than throwing errors, emit them via an "error" event.

For FG-9839
  • Loading branch information
jtbandes authored Jan 11, 2025
1 parent b958d66 commit bc8641f
Show file tree
Hide file tree
Showing 9 changed files with 512 additions and 37 deletions.
12 changes: 9 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
interval: monthly
labels: [] # disable default labels

- package-ecosystem: npm
directory: /
schedule:
interval: monthly
labels: [] # disable default labels

# Define groups of dependencies to be updated together
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
registry-url: https://registry.npmjs.org
cache: yarn

Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
registry-url: https://registry.npmjs.org
cache: yarn

Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"prettier.prettierPath": "./node_modules/prettier",
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"jest.jestCommandLine": "yarn test"
}
7 changes: 6 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { createDefaultEsmPreset } = require("ts-jest");

/** @type {import("ts-jest").JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest",
...createDefaultEsmPreset({}),
testMatch: ["<rootDir>/src/**/*.test.ts"],
setupFiles: ["jest-canvas-mock"],
};
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foxglove/three-text",
"version": "0.3.1",
"version": "0.4.0",
"description": "Render text in 3D using Signed Distance Fields",
"license": "MIT",
"repository": {
Expand All @@ -24,7 +24,7 @@
"build": "tsc -b tsconfig.json tsconfig.cjs.json",
"lint": "eslint --fix .",
"lint:ci": "eslint .",
"test": "echo 'nothing to test'",
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
Expand All @@ -49,13 +49,15 @@
"eslint-plugin-storybook": "0.11.0",
"globals": "15.12.0",
"jest": "29.7.0",
"jest-canvas-mock": "2.5.2",
"jest-environment-jsdom": "29.7.0",
"prettier": "3.3.3",
"react": "18.3.1",
"react-dom": "18.3.1",
"rimraf": "6.0.1",
"storybook": "7.6.16",
"three": "0.165.0",
"ts-jest": "29.1.2",
"ts-jest": "29.2.5",
"typescript": "5.6.3",
"typescript-eslint": "8.13.0"
},
Expand Down
18 changes: 18 additions & 0 deletions src/FontManager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/** @jest-environment jsdom */

import { FontManager } from "./FontManager";

describe("FontManager", () => {
it("emits error events", () => {
const fontManager = new FontManager({ fontSize: 500 });
const errors: Error[] = [];
fontManager.addEventListener("error", (err) => errors.push(err.error));
for (let i = 0; i < 1000; i++) {
fontManager.update(String.fromCodePoint(i));
if (errors.length > 0) {
break;
}
}
expect(errors).toEqual([new Error("Unable to fit all 226 characters in font atlas")]);
});
});
23 changes: 18 additions & 5 deletions src/FontManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ export type FontManagerOptions = {
fontSize?: number;
};

type EventMap = {
atlasChange: object;
error: { error: Error };
};

/**
* Manages the creation of a Signed Distance Field (SDF) font atlas, and performs text layout to
* generate attributes for rendering text using the atlas.
*/
export class FontManager extends EventDispatcher<{ atlasChange: object }> {
export class FontManager extends EventDispatcher<EventMap> {
private alphabet = "";
atlasData: AtlasData = {
data: new Uint8ClampedArray(),
Expand Down Expand Up @@ -99,9 +104,13 @@ export class FontManager extends EventDispatcher<{ atlasChange: object }> {
let maxAscent = 0;
for (const char of this.alphabet) {
if (charInfo[char] != undefined) {
throw new Error(
`Duplicate character in alphabet: ${char} (${char.codePointAt(0) ?? "undefined"})`,
);
this.dispatchEvent({
type: "error",
error: new Error(
`Duplicate character in alphabet: ${char} (${char.codePointAt(0) ?? "undefined"})`,
),
});
continue;
}
const sdf = tinysdf.draw(char);
if (x + sdf.width >= atlasWidth) {
Expand All @@ -110,7 +119,11 @@ export class FontManager extends EventDispatcher<{ atlasChange: object }> {
rowHeight = 0;
}
if (y + sdf.height >= atlasHeight) {
throw new Error(`Unable to fit all ${this.alphabet.length} characters in font atlas`);
this.dispatchEvent({
type: "error",
error: new Error(`Unable to fit all ${this.alphabet.length} characters in font atlas`),
});
continue;
}
rowHeight = Math.max(rowHeight, sdf.height);
lineHeight = Math.max(lineHeight, rowHeight);
Expand Down
11 changes: 10 additions & 1 deletion src/LabelPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,13 @@ export class Label extends THREE.Object3D {
}
}

export class LabelPool extends EventDispatcher<{ scaleFactorChange: object; atlasChange: object }> {
type EventMap = {
scaleFactorChange: object;
atlasChange: object;
error: { error: Error };
};

export class LabelPool extends EventDispatcher<EventMap> {
atlasTexture: THREE.DataTexture;

private availableLabels: Label[] = [];
Expand Down Expand Up @@ -407,6 +413,9 @@ export class LabelPool extends EventDispatcher<{ scaleFactorChange: object; atla
THREE.LinearFilter,
);

this.fontManager.addEventListener("error", (event) => {
this.dispatchEvent(event);
});
this.fontManager.addEventListener("atlasChange", () => {
this._updateAtlasTexture();
});
Expand Down
Loading

0 comments on commit bc8641f

Please sign in to comment.