From db79c106b75d94ac6b4ed637ed3e6ff4aca5b4c0 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 16:13:08 +0000 Subject: [PATCH] fix(text): load font atlases from explicit metrics and image URLs FontAtlasCache.getOrLoad now takes { metricsUrl, imageUrl } instead of resolving the image named in the JSON's atlasImage field next to the JSON, which broke under bundlers that hash asset names. Concurrent loads of the same atlas are shared, a conflicting image URL for the same metrics rejects, and the image's size is checked against atlasSize. atlasImage is removed from the data, the validator and the generator. The default font is exported as @forge-game-engine/forge/fonts/default/*.json and *.png so bundlers can import it, and the docs-site demos now import it that way instead of keeping a static copy. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01BnSddjDV7weKQBwDYkmgNA --- CHANGELOG.md | 8 + assets/fonts/default/default.json | 1 - design/font-atlas-loading.md | 2 +- .../docs/docs/asset-loading/index.md | 8 +- .../docs/docs/text/generating-a-font-atlas.md | 6 +- documentation-site/docs/docs/text/index.md | 42 +- .../docs/docs/text/loading-a-font-atlas.md | 86 +- .../docs/docs/text/rendering-text.md | 5 +- .../docs/docs/ui/labels-and-text.md | 7 +- .../pages/demos/layout-groups/_create-game.ts | 16 +- .../src/pages/demos/layout-groups/index.tsx | 12 +- .../src/pages/demos/text/_create-game.ts | 17 +- .../src/pages/demos/text/index.tsx | 8 +- .../pages/demos/ui-anchors/_create-game.ts | 13 +- .../src/pages/demos/ui-anchors/index.tsx | 8 +- .../src/pages/demos/ui-button/_create-game.ts | 14 +- .../src/pages/demos/ui-button/index.tsx | 12 +- .../demos/ui-canvas-group/_create-game.ts | 16 +- .../src/pages/demos/ui-canvas-group/index.tsx | 12 +- .../pages/demos/ui-dropdown/_create-game.ts | 16 +- .../src/pages/demos/ui-dropdown/index.tsx | 12 +- .../pages/demos/ui-main-menu/_create-game.ts | 16 +- .../src/pages/demos/ui-main-menu/index.tsx | 12 +- .../demos/ui-nested-resize/_create-game.ts | 21 +- .../pages/demos/ui-nested-resize/index.tsx | 12 +- .../demos/ui-progress-bar/_create-game.ts | 16 +- .../src/pages/demos/ui-progress-bar/index.tsx | 12 +- .../src/pages/demos/ui-slider/_create-game.ts | 14 +- .../src/pages/demos/ui-slider/index.tsx | 12 +- .../demos/ui-stress-test/_create-game.ts | 16 +- .../src/pages/demos/ui-stress-test/index.tsx | 12 +- .../src/pages/demos/ui-toggle/_create-game.ts | 14 +- .../src/pages/demos/ui-toggle/index.tsx | 12 +- .../ui-world-space-canvas/_create-game.ts | 16 +- .../demos/ui-world-space-canvas/index.tsx | 12 +- .../src/utils/image-modules.d.ts | 6 + .../static/fonts/default/License.txt | 102 -- .../static/fonts/default/default.json | 1529 ----------------- .../static/fonts/default/default.png | Bin 167824 -> 0 bytes e2e/fixtures/scenes/text-effects-overlap.ts | 11 +- package.json | 6 +- scripts/generate-font-atlas.mjs | 14 +- src/text/font-atlas/font-atlas-cache.test.ts | 184 +- src/text/font-atlas/font-atlas-cache.ts | 144 +- src/text/font-atlas/font-atlas-data.ts | 3 - .../font-atlas/font-atlas-file-data.test.ts | 2 - src/text/font-atlas/font-atlas-file-data.ts | 8 +- .../validate-font-atlas-data.test.ts | 9 +- .../font-atlas/validate-font-atlas-data.ts | 4 - .../rendering/create-text-renderable.test.ts | 1 - src/text/systems/text-shaping-system.test.ts | 1 - src/text/utilities/shape-text.test.ts | 1 - 52 files changed, 555 insertions(+), 1988 deletions(-) create mode 100644 documentation-site/src/utils/image-modules.d.ts delete mode 100644 documentation-site/static/fonts/default/License.txt delete mode 100644 documentation-site/static/fonts/default/default.json delete mode 100644 documentation-site/static/fonts/default/default.png diff --git a/CHANGELOG.md b/CHANGELOG.md index fe2f7e2ce..02e8296e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Added + +- **text:** The engine's default font can be imported through a bundler from `@forge-game-engine/forge/fonts/default/default.json` and `@forge-game-engine/forge/fonts/default/default.png`, so you no longer need to copy it out of `node_modules` + +#### Changed + +- **text:** `FontAtlasCache.getOrLoad` takes the URL of both atlas files, `getOrLoad({ metricsUrl, imageUrl })`, instead of finding the image next to the JSON, so atlases imported through Vite, webpack or another bundler that renames files now load. Pass the URLs your bundler gives you for the `.json` and `.png` (with Vite, `import metricsUrl from './my-font.json?url'` and `import imageUrl from './my-font.png'`), and look loaded atlases up with `get(metricsUrl)`. `getOrLoad` rejects if the image's size doesn't match the JSON's `atlasSize`, or if one `metricsUrl` is requested with two different image URLs. Concurrent calls for the same atlas now share one load. `FontAtlasCache` no longer implements `AssetCache` and its `load` method and `assets` map are no longer public; call `getOrLoad` instead. `FontAtlasData` and `FontAtlasFileData` no longer have an `atlasImage` field and `forge-generate-font-atlas` no longer writes one; existing JSON files that have it still load + ## [0.25.8] - 2026-10-03 #### Fixed diff --git a/assets/fonts/default/default.json b/assets/fonts/default/default.json index afc590a54..5a426250d 100644 --- a/assets/fonts/default/default.json +++ b/assets/fonts/default/default.json @@ -1,7 +1,6 @@ { "formatVersion": 2, "type": "msdf", - "atlasImage": "default.png", "atlasSize": { "width": 512, "height": 512 diff --git a/design/font-atlas-loading.md b/design/font-atlas-loading.md index d8329d366..7a29c97ea 100644 --- a/design/font-atlas-loading.md +++ b/design/font-atlas-loading.md @@ -2,7 +2,7 @@ | | | | ------------------------------------- | ------------------------------------------------------------------------------------------------ | -| **Status** | Draft, for review | +| **Status** | Implemented. `documentation-site/docs/docs/text` describes current behavior | | **Kind** | Defect | | **Found in** | Galactic Journey demo: `src/ui/create-ui.ts` (fonts served from `public/` to avoid hashed names) | | **Engine version at time of writing** | `0.25.8` | diff --git a/documentation-site/docs/docs/asset-loading/index.md b/documentation-site/docs/docs/asset-loading/index.md index a4f3cede4..f989e6933 100644 --- a/documentation-site/docs/docs/asset-loading/index.md +++ b/documentation-site/docs/docs/asset-loading/index.md @@ -12,10 +12,12 @@ and [`FontAtlasCache`](/Forge/docs/api/classes/FontAtlasCache) (see [Text](../text/index.md)), plus two supporting building blocks: - [`AssetCache`](/Forge/docs/api/interfaces/AssetCache): the common - `get` / `load` / `getOrLoad` contract that asset caches implement. - `ImageCache` and `FontAtlasCache` both implement it; if you add a cache - for another asset type (audio buffers, arbitrary JSON data), implement + `get` / `load` / `getOrLoad` contract for caches that load an asset from + a single URL, such as `ImageCache`. If you add a cache for another + single-file asset type (audio buffers, arbitrary JSON data), implement this interface so it behaves consistently with the rest of the engine. + `FontAtlasCache` loads each atlas from two URLs, so it has its own + `getOrLoad({ metricsUrl, imageUrl })` instead. - [`AssetRegistry`](/Forge/docs/api/classes/AssetRegistry): maps human-readable string IDs to compact numeric IDs, so hot-path code (like a per-frame animation system) can look up an asset by index instead of by diff --git a/documentation-site/docs/docs/text/generating-a-font-atlas.md b/documentation-site/docs/docs/text/generating-a-font-atlas.md index 3cea57d71..caea6c2ea 100644 --- a/documentation-site/docs/docs/text/generating-a-font-atlas.md +++ b/documentation-site/docs/docs/text/generating-a-font-atlas.md @@ -41,8 +41,10 @@ npm install -g msdf-bmfont-xml npx forge-generate-font-atlas --font my-font.ttf --charset ascii --out assets/fonts/my-font ``` -This writes `assets/fonts/my-font.png` and `assets/fonts/my-font.json`, which -[`FontAtlasCache`](./loading-a-font-atlas.md) loads together at runtime. +This writes `assets/fonts/my-font.png` and `assets/fonts/my-font.json`. +Load them with [`FontAtlasCache`](./loading-a-font-atlas.md), passing the +URL of each. Always replace both files together: the JSON's glyph +positions only match the image from the same run. | Flag | Default | Meaning | | -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- | diff --git a/documentation-site/docs/docs/text/index.md b/documentation-site/docs/docs/text/index.md index 6239e8c80..688d1606f 100644 --- a/documentation-site/docs/docs/text/index.md +++ b/documentation-site/docs/docs/text/index.md @@ -19,10 +19,8 @@ Three pieces make up the module: file, sized to your game's actual `charset`. - [`FontAtlasCache`](/Forge/docs/api/classes/FontAtlasCache), which loads that JSON/image pair at runtime into a - [`FontAtlas`](/Forge/docs/api/interfaces/FontAtlas), following the same - [`AssetCache`](/Forge/docs/api/interfaces/AssetCache) contract as the - rest of the engine's asset loading (see - [Asset Loading](../asset-loading/index.md)). + [`FontAtlas`](/Forge/docs/api/interfaces/FontAtlas) (see + [Loading a Font Atlas](./loading-a-font-atlas.md)). - [`addTextComponent`](/Forge/docs/api/functions/addTextComponent) and [`createTextShapingEcsSystem`](/Forge/docs/api/functions/createTextShapingEcsSystem), which draw a string from a loaded `FontAtlas` through the render system @@ -31,34 +29,44 @@ Three pieces make up the module: ## Quick start The engine ships a pre-generated default atlas (Liberation Sans, SIL Open -Font License 1.1) at `assets/fonts/default/` (`default.json`, `default.png`, -and a `License.txt` with the font's attribution) inside the -`@forge-game-engine/forge` package itself, so you can render text with zero -font setup - no `.ttf`, no `forge-generate-font-atlas` run, nothing to -license or commit yourself. `FontAtlasCache.getOrLoad` just needs those -three files reachable at a URL, the same as any atlas you generate -yourself, so copy (or have your build script copy) them from -`node_modules/@forge-game-engine/forge/assets/fonts/default/` into your -project's own served assets directory - most bundlers don't serve -`node_modules` directly: +Font License 1.1) inside the `@forge-game-engine/forge` package, so you can +render text with zero font setup - no `.ttf`, no `forge-generate-font-atlas` +run. Import its two files through the package's `fonts/default` exports and +pass the URLs your bundler gives you (this is Vite; see +[Loading a Font Atlas](./loading-a-font-atlas.md#importing-atlases-through-a-bundler) +for webpack): ```ts +import defaultFontMetricsUrl from '@forge-game-engine/forge/fonts/default/default.json?url'; +import defaultFontImageUrl from '@forge-game-engine/forge/fonts/default/default.png'; import { FontAtlasCache } from '@forge-game-engine/forge/text'; const fontAtlasCache = new FontAtlasCache(); -const fontAtlas = await fontAtlasCache.getOrLoad('assets/fonts/default.json'); +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: defaultFontMetricsUrl, + imageUrl: defaultFontImageUrl, +}); ``` +The font's attribution is in `assets/fonts/default/License.txt` in the +package. + When you need your own font (a different look, or characters the default atlas's ASCII charset doesn't cover), generate one: ```bash npm install --save-dev msdf-bmfont-xml -npx forge-generate-font-atlas --font my-font.ttf --charset ascii --out assets/fonts/my-font +npx forge-generate-font-atlas --font my-font.ttf --charset ascii --out src/fonts/my-font ``` ```ts -const fontAtlas = await fontAtlasCache.getOrLoad('assets/fonts/my-font.json'); +import myFontMetricsUrl from './fonts/my-font.json?url'; +import myFontImageUrl from './fonts/my-font.png'; + +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: myFontMetricsUrl, + imageUrl: myFontImageUrl, +}); console.log(fontAtlas.data.glyphs.get('A'.codePointAt(0)!)); ``` diff --git a/documentation-site/docs/docs/text/loading-a-font-atlas.md b/documentation-site/docs/docs/text/loading-a-font-atlas.md index 36beec8c3..d7135b5b7 100644 --- a/documentation-site/docs/docs/text/loading-a-font-atlas.md +++ b/documentation-site/docs/docs/text/loading-a-font-atlas.md @@ -5,26 +5,80 @@ sidebar_position: 2 # Loading a Font Atlas [`FontAtlasCache`](/Forge/docs/api/classes/FontAtlasCache) loads a -generated atlas's JSON metrics and PNG texture into a -[`FontAtlas`](/Forge/docs/api/interfaces/FontAtlas). +generated atlas's metrics JSON and PNG image into a +[`FontAtlas`](/Forge/docs/api/interfaces/FontAtlas). Pass it the URL of +each file: ```ts import { FontAtlasCache } from '@forge-game-engine/forge/text'; const fontAtlasCache = new FontAtlasCache(); -const fontAtlas = await fontAtlasCache.getOrLoad('assets/fonts/my-font.json'); +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: 'assets/fonts/my-font.json', + imageUrl: 'assets/fonts/my-font.png', +}); ``` -Any atlas works here, including the default one the engine ships at -`assets/fonts/default/default.json` (see [Text](./index.md)'s Quick start) - -there's nothing default-atlas-specific about loading it. +The two URLs are independent: the image doesn't have to be in the same +directory as the JSON, or keep its original file name. -## Cache keys point at the JSON file +## Importing atlases through a bundler -`getOrLoad('assets/fonts/my-font.json')` fetches that file, then loads -whatever image its `atlasImage` field names, resolved relative to the JSON -file itself (so the `.png` doesn't have to share the exact base name, -though `forge-generate-font-atlas` always names them to match). +Bundlers rename the assets they emit (`my-font.png` becomes something like +`my-font-3f2a9c.png`), so import both files and pass the URLs the bundler +gives you rather than writing paths by hand. + +With Vite, import the PNG directly and the JSON with `?url`, which gives +its URL instead of its parsed contents: + +```ts +import { FontAtlasCache } from '@forge-game-engine/forge/text'; +import myFontMetricsUrl from './fonts/my-font.json?url'; +import myFontImageUrl from './fonts/my-font.png'; + +const fontAtlasCache = new FontAtlasCache(); +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: myFontMetricsUrl, + imageUrl: myFontImageUrl, +}); +``` + +With webpack 5, use `new URL(path, import.meta.url)` for both files. The +path must be a string literal for webpack to find the file: + +```ts +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: new URL('./fonts/my-font.json', import.meta.url).href, + imageUrl: new URL('./fonts/my-font.png', import.meta.url).href, +}); +``` + +If your webpack config runs `file-loader` or `url-loader` on images +(Docusaurus does), those loaders also process `new URL` image requests, and +the emitted `.png` contains JavaScript instead of the image, so it fails to +load. Import the PNG instead (`import myFontImageUrl from +'./fonts/my-font.png'`) and keep `new URL` for the JSON. + +The engine's default font (see [Text](./index.md)'s Quick start) is +imported the same way, from the package's `fonts/default` exports: + +```ts +import defaultFontMetricsUrl from '@forge-game-engine/forge/fonts/default/default.json?url'; +import defaultFontImageUrl from '@forge-game-engine/forge/fonts/default/default.png'; +``` + +## Gotchas + +- **Keep the JSON and PNG from the same generator run.** `getOrLoad` + rejects if the image's size doesn't match the JSON's `atlasSize`. Two + different atlases generated at the same texture size still pass that + check, and render garbled glyphs, so regenerate and replace both files + together. +- **One image per metrics URL.** The cache is keyed by `metricsUrl`. + Requesting the same `metricsUrl` with a different `imageUrl` rejects. +- **Requesting an atlas again doesn't reload it.** Repeated and concurrent + `getOrLoad` calls for the same `metricsUrl` share one load, so the + `Promise.all` pattern in the worked example below fetches each file once. ## Reading glyph metrics @@ -73,8 +127,14 @@ import { FontAtlasCache } from '@forge-game-engine/forge/text'; const fontAtlasCache = new FontAtlasCache(); const [headingAtlas, bodyAtlas] = await Promise.all([ - fontAtlasCache.getOrLoad('assets/fonts/heading.json'), - fontAtlasCache.getOrLoad('assets/fonts/body.json'), + fontAtlasCache.getOrLoad({ + metricsUrl: 'assets/fonts/heading.json', + imageUrl: 'assets/fonts/heading.png', + }), + fontAtlasCache.getOrLoad({ + metricsUrl: 'assets/fonts/body.json', + imageUrl: 'assets/fonts/body.png', + }), ]); const capitalA = bodyAtlas.data.glyphs.get('A'.codePointAt(0)!); diff --git a/documentation-site/docs/docs/text/rendering-text.md b/documentation-site/docs/docs/text/rendering-text.md index 0be3fcfea..20a9d7147 100644 --- a/documentation-site/docs/docs/text/rendering-text.md +++ b/documentation-site/docs/docs/text/rendering-text.md @@ -23,7 +23,10 @@ import { } from '@forge-game-engine/forge/text'; const fontAtlasCache = new FontAtlasCache(); -const fontAtlas = await fontAtlasCache.getOrLoad('assets/fonts/body.json'); +const fontAtlas = await fontAtlasCache.getOrLoad({ + metricsUrl: 'assets/fonts/body.json', + imageUrl: 'assets/fonts/body.png', +}); const label = world.createEntity(); addPositionComponent(world, label, { local: { x: 400, y: 300 } }); diff --git a/documentation-site/docs/docs/ui/labels-and-text.md b/documentation-site/docs/docs/ui/labels-and-text.md index 7b6ef46ac..29299afb2 100644 --- a/documentation-site/docs/docs/ui/labels-and-text.md +++ b/documentation-site/docs/docs/ui/labels-and-text.md @@ -14,9 +14,10 @@ atlas): import { FontAtlasCache } from '@forge-game-engine/forge/text'; import { createLabel, UiAnchor } from '@forge-game-engine/forge/ui'; -const fontAtlas = await new FontAtlasCache().getOrLoad( - 'assets/fonts/default.json', -); +const fontAtlas = await new FontAtlasCache().getOrLoad({ + metricsUrl: 'assets/fonts/my-font.json', + imageUrl: 'assets/fonts/my-font.png', +}); createLabel(world, panel, { text: 'Play', diff --git a/documentation-site/src/pages/demos/layout-groups/_create-game.ts b/documentation-site/src/pages/demos/layout-groups/_create-game.ts index deda36464..35ace1378 100644 --- a/documentation-site/src/pages/demos/layout-groups/_create-game.ts +++ b/documentation-site/src/pages/demos/layout-groups/_create-game.ts @@ -4,6 +4,7 @@ import { Time, } from '@forge-game-engine/forge/common'; import { EcsWorld } from '@forge-game-engine/forge/ecs'; +import defaultFontImageUrl from '@forge-game-engine/forge/fonts/default/default.png'; import { actionResetTypes, Axis2dAction, @@ -139,12 +140,9 @@ function createUiInputs( * (the Menu's buttons, the Options panel's Music slider and Fullscreen * toggle) is clickable and keyboard/gamepad-focus-navigable via * `createUiInputs`. - * @param fontAtlasUrl - The URL of the font atlas JSON to load. * @returns The created game. */ -export const createLayoutGroupsGame = async ( - fontAtlasUrl: string, -): Promise => { +export const createLayoutGroupsGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -156,7 +154,15 @@ export const createLayoutGroupsGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const { mouseInputSource, submitInput, navigateInput } = createUiInputs( world, diff --git a/documentation-site/src/pages/demos/layout-groups/index.tsx b/documentation-site/src/pages/demos/layout-groups/index.tsx index 5f7f696bf..f8d96d3f0 100644 --- a/documentation-site/src/pages/demos/layout-groups/index.tsx +++ b/documentation-site/src/pages/demos/layout-groups/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createLayoutGroupsGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import menuCode from '!!raw-loader!./_create-menu'; @@ -10,13 +9,6 @@ import optionsFormCode from '!!raw-loader!./_create-options-form'; import { Demo } from '@site/src/components/Demo'; export default function LayoutGroups(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createLayoutGroupsGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( void, ): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); @@ -65,7 +64,15 @@ export const createTextGame = async ( }); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const whiteImage = await renderContext.imageCache.getOrLoad( getAssetUrl('img/White.png'), diff --git a/documentation-site/src/pages/demos/text/index.tsx b/documentation-site/src/pages/demos/text/index.tsx index edfbfb1c8..6c378b5ed 100644 --- a/documentation-site/src/pages/demos/text/index.tsx +++ b/documentation-site/src/pages/demos/text/index.tsx @@ -1,5 +1,4 @@ import React, { JSX, useCallback, useRef, useState } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { createTextGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import createGuideBoxCode from '!!raw-loader!./_create-guide-box'; @@ -25,9 +24,6 @@ import { import { PlaygroundControls } from './_PlaygroundControls'; export default function Text(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const playgroundRef = useRef(null); const [text, setText] = useState(playgroundDefaults.text); const [size, setSize] = useState(playgroundDefaults.size); @@ -59,10 +55,10 @@ export default function Text(): JSX.Element { const createGame = useCallback( () => - createTextGame(fontAtlasUrl, (playground) => { + createTextGame((playground) => { playgroundRef.current = playground; }), - [fontAtlasUrl], + [], ); const handleTextChange = (value: string) => { diff --git a/documentation-site/src/pages/demos/ui-anchors/_create-game.ts b/documentation-site/src/pages/demos/ui-anchors/_create-game.ts index 197fa136c..f5bef1eb5 100644 --- a/documentation-site/src/pages/demos/ui-anchors/_create-game.ts +++ b/documentation-site/src/pages/demos/ui-anchors/_create-game.ts @@ -3,6 +3,7 @@ import { createTransformEcsSystem, } from '@forge-game-engine/forge/common'; import { EcsWorld } from '@forge-game-engine/forge/ecs'; +import defaultFontImageUrl from '@forge-game-engine/forge/fonts/default/default.png'; import { addSpriteComponent, calculateVisibleWorldSize, @@ -91,13 +92,11 @@ const playgroundTintColor = new Color(0.95, 0.55, 0.2, 1); * aspect ratio, so toggling fullscreen (or dragging the playground's * controls) keeps each one exactly where its anchor says it should be, at * any window shape. - * @param fontAtlasUrl - The URL of the font atlas JSON to load. * @param onPlaygroundReady - Called once the playground panel's live * components exist, so the page can wire its controls up to them. * @returns The created game. */ export const createAnchorsGame = async ( - fontAtlasUrl: string, onPlaygroundReady?: (playground: AnchorPlayground) => void, ): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); @@ -109,7 +108,15 @@ export const createAnchorsGame = async ( }); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); registerUiSystems(world, renderContext, time); diff --git a/documentation-site/src/pages/demos/ui-anchors/index.tsx b/documentation-site/src/pages/demos/ui-anchors/index.tsx index 27b01d4dc..dce53b345 100644 --- a/documentation-site/src/pages/demos/ui-anchors/index.tsx +++ b/documentation-site/src/pages/demos/ui-anchors/index.tsx @@ -1,5 +1,4 @@ import React, { JSX, useCallback, useRef, useState } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { createAnchorsGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import createAnchorPlaygroundCode from '!!raw-loader!./_create-anchor-playground'; @@ -30,9 +29,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiAnchors(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const playgroundRef = useRef(null); const [presetName, setPresetName] = useState( anchorPlaygroundDefaults.presetName, @@ -52,10 +48,10 @@ export default function UiAnchors(): JSX.Element { const createGame = useCallback( () => - createAnchorsGame(fontAtlasUrl, (playground) => { + createAnchorsGame((playground) => { playgroundRef.current = playground; }), - [fontAtlasUrl], + [], ); const handlePresetNameChange = (value: AnchorPlaygroundPresetName) => { diff --git a/documentation-site/src/pages/demos/ui-button/_create-game.ts b/documentation-site/src/pages/demos/ui-button/_create-game.ts index 8dc5b89e1..7f5482717 100644 --- a/documentation-site/src/pages/demos/ui-button/_create-game.ts +++ b/documentation-site/src/pages/demos/ui-button/_create-game.ts @@ -4,6 +4,7 @@ import { Time, } from '@forge-game-engine/forge/common'; import { EcsWorld } from '@forge-game-engine/forge/ecs'; +import defaultFontImageUrl from '@forge-game-engine/forge/fonts/default/default.png'; import { actionResetTypes, Axis2dAction, @@ -139,10 +140,9 @@ function createUiInputs( * path, updating a status label with which one was last invoked. Hovering * a button also focuses it, so the highlight follows the mouse the same * way it follows the keyboard. - * @param fontAtlasUrl - The URL of the font atlas JSON to load. * @returns The created game. */ -export const createButtonGame = async (fontAtlasUrl: string): Promise => { +export const createButtonGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -154,7 +154,15 @@ export const createButtonGame = async (fontAtlasUrl: string): Promise => { await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const { mouseInputSource, submitInput, navigateInput } = createUiInputs( world, diff --git a/documentation-site/src/pages/demos/ui-button/index.tsx b/documentation-site/src/pages/demos/ui-button/index.tsx index 2157708e3..abf8a40ea 100644 --- a/documentation-site/src/pages/demos/ui-button/index.tsx +++ b/documentation-site/src/pages/demos/ui-button/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createButtonGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; @@ -19,13 +18,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiButton(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createButtonGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createCanvasGroupGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -110,7 +108,15 @@ export const createCanvasGroupGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const mouseInputSource = createPointerInput(world, time, game); diff --git a/documentation-site/src/pages/demos/ui-canvas-group/index.tsx b/documentation-site/src/pages/demos/ui-canvas-group/index.tsx index 204935b1d..5b63f3409 100644 --- a/documentation-site/src/pages/demos/ui-canvas-group/index.tsx +++ b/documentation-site/src/pages/demos/ui-canvas-group/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createCanvasGroupGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; @@ -18,13 +17,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiCanvasGroup(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createCanvasGroupGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createDropdownGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -101,7 +99,15 @@ export const createDropdownGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const mouseInputSource = createPointerInput(world, time, game); diff --git a/documentation-site/src/pages/demos/ui-dropdown/index.tsx b/documentation-site/src/pages/demos/ui-dropdown/index.tsx index 95dd96268..501cbd892 100644 --- a/documentation-site/src/pages/demos/ui-dropdown/index.tsx +++ b/documentation-site/src/pages/demos/ui-dropdown/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createDropdownGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; @@ -18,13 +17,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiDropdown(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createDropdownGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createUiMainMenuGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -167,7 +165,15 @@ export const createUiMainMenuGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const { mouseInputSource, submitInput, navigateInput } = createUiInputs( world, diff --git a/documentation-site/src/pages/demos/ui-main-menu/index.tsx b/documentation-site/src/pages/demos/ui-main-menu/index.tsx index 58e9b8196..ce3a45bca 100644 --- a/documentation-site/src/pages/demos/ui-main-menu/index.tsx +++ b/documentation-site/src/pages/demos/ui-main-menu/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createUiMainMenuGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import mainMenuCode from '!!raw-loader!./_create-main-menu'; @@ -23,13 +22,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiMainMenu(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createUiMainMenuGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createNestedResizeGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -94,7 +89,15 @@ export const createNestedResizeGame = async ( }); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const mouseInputSource = createPointerInput(world, time, game); diff --git a/documentation-site/src/pages/demos/ui-nested-resize/index.tsx b/documentation-site/src/pages/demos/ui-nested-resize/index.tsx index bfa53e5bc..9abc74d5f 100644 --- a/documentation-site/src/pages/demos/ui-nested-resize/index.tsx +++ b/documentation-site/src/pages/demos/ui-nested-resize/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createNestedResizeGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import liveMotionComponentCode from '!!raw-loader!./_live-motion.component'; @@ -8,13 +7,6 @@ import liveMotionSystemCode from '!!raw-loader!./_live-motion.system'; import { Demo } from '@site/src/components/Demo'; export default function UiNestedResize(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createNestedResizeGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createProgressBarGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -89,7 +87,15 @@ export const createProgressBarGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); registerUiSystems(world, renderContext, time); diff --git a/documentation-site/src/pages/demos/ui-progress-bar/index.tsx b/documentation-site/src/pages/demos/ui-progress-bar/index.tsx index 1b1f7280d..8a6f1d96a 100644 --- a/documentation-site/src/pages/demos/ui-progress-bar/index.tsx +++ b/documentation-site/src/pages/demos/ui-progress-bar/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createProgressBarGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import pulseComponentCode from '!!raw-loader!./_pulse.component'; @@ -8,13 +7,6 @@ import pulseSystemCode from '!!raw-loader!./_pulse.system'; import { Demo } from '@site/src/components/Demo'; export default function UiProgressBar(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createProgressBarGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createSliderGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -88,7 +88,15 @@ export const createSliderGame = async (fontAtlasUrl: string): Promise => { await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const mouseInputSource = createPointerInput(world, time, game); diff --git a/documentation-site/src/pages/demos/ui-slider/index.tsx b/documentation-site/src/pages/demos/ui-slider/index.tsx index 521f17cc8..ad8063ca6 100644 --- a/documentation-site/src/pages/demos/ui-slider/index.tsx +++ b/documentation-site/src/pages/demos/ui-slider/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createSliderGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; @@ -18,13 +17,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiSlider(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createSliderGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createUiStressTestGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -102,7 +100,15 @@ export const createUiStressTestGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); registerUiSystems(world, renderContext, time); diff --git a/documentation-site/src/pages/demos/ui-stress-test/index.tsx b/documentation-site/src/pages/demos/ui-stress-test/index.tsx index d80e702ba..928d5d84c 100644 --- a/documentation-site/src/pages/demos/ui-stress-test/index.tsx +++ b/documentation-site/src/pages/demos/ui-stress-test/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createUiStressTestGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import spawnerComponentCode from '!!raw-loader!./_stress-test-spawner.component'; @@ -9,13 +8,6 @@ import fpsMonitorSystemCode from '!!raw-loader!./_fps-monitor.system'; import { Demo } from '@site/src/components/Demo'; export default function UiStressTest(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createUiStressTestGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( => { +export const createToggleGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); createCamera(world, { @@ -104,7 +104,15 @@ export const createToggleGame = async (fontAtlasUrl: string): Promise => { await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); const mouseInputSource = createPointerInput(world, time, game); diff --git a/documentation-site/src/pages/demos/ui-toggle/index.tsx b/documentation-site/src/pages/demos/ui-toggle/index.tsx index 7744ed6db..c5adece94 100644 --- a/documentation-site/src/pages/demos/ui-toggle/index.tsx +++ b/documentation-site/src/pages/demos/ui-toggle/index.tsx @@ -1,5 +1,4 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createToggleGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; @@ -18,13 +17,6 @@ const badgeStyle: React.CSSProperties = { }; export default function UiToggle(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createToggleGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( { * the enemy. The right enemy's has no parent and is placed above it with its * `anchoredPosition`, so it stays upright regardless of which way the enemy * is facing. - * @param fontAtlasUrl - The URL of the font atlas JSON to load. * @returns The created game. */ -export const createWorldSpaceCanvasGame = async ( - fontAtlasUrl: string, -): Promise => { +export const createWorldSpaceCanvasGame = async (): Promise => { const { game, world, renderContext, time } = createGame('demo-game'); const worldCamera = createCamera(world, { @@ -236,7 +234,15 @@ export const createWorldSpaceCanvasGame = async ( await createBackdrop(world, renderContext); const fontAtlasCache = new FontAtlasCache(renderContext.imageCache); - const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad(fontAtlasUrl); + const fontAtlas: FontAtlas = await fontAtlasCache.getOrLoad({ + // Importing the JSON would give its parsed contents, so `new URL` asks + // webpack for its URL instead. + metricsUrl: new URL( + '@forge-game-engine/forge/fonts/default/default.json', + import.meta.url, + ).href, + imageUrl: defaultFontImageUrl, + }); // Registered once for the whole world, before either // createSpinningEnemyWithHealthBar call creates its own canvas below - diff --git a/documentation-site/src/pages/demos/ui-world-space-canvas/index.tsx b/documentation-site/src/pages/demos/ui-world-space-canvas/index.tsx index 861127134..730021a75 100644 --- a/documentation-site/src/pages/demos/ui-world-space-canvas/index.tsx +++ b/documentation-site/src/pages/demos/ui-world-space-canvas/index.tsx @@ -1,18 +1,10 @@ -import React, { JSX, useCallback } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import React, { JSX } from 'react'; import { createWorldSpaceCanvasGame } from './_create-game'; import gameCode from '!!raw-loader!./_create-game'; import { Demo } from '@site/src/components/Demo'; export default function UiWorldSpaceCanvas(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - const fontAtlasUrl = `${siteConfig.baseUrl}fonts/default/default.json`; - const createGame = useCallback( - () => createWorldSpaceCanvasGame(fontAtlasUrl), - [fontAtlasUrl], - ); - return ( ); diff --git a/documentation-site/src/utils/image-modules.d.ts b/documentation-site/src/utils/image-modules.d.ts new file mode 100644 index 000000000..15d1b9334 --- /dev/null +++ b/documentation-site/src/utils/image-modules.d.ts @@ -0,0 +1,6 @@ +// Docusaurus's webpack config emits imported images as files and gives the +// importing module their URL. +declare module '*.png' { + const url: string; + export default url; +} diff --git a/documentation-site/static/fonts/default/License.txt b/documentation-site/static/fonts/default/License.txt deleted file mode 100644 index 793a2791d..000000000 --- a/documentation-site/static/fonts/default/License.txt +++ /dev/null @@ -1,102 +0,0 @@ - Liberation Sans (MSDF atlas, Forge's shipped default font atlas) - - Font: Liberation Sans Regular - Digitized data copyright (c) 2010 Google Corporation with Reserved Font Arimo, Tinos and Cousine. - Copyright (c) 2012 Red Hat, Inc. with Reserved Font Name Liberation. - Source: https://github.com/liberationfonts - - default.png and default.json in this directory are a multi-channel - signed distance field (MSDF) atlas generated from this font via - `npm run generate-font-atlas` (see scripts/generate-font-atlas.mjs), so - `@forge-game-engine/forge/text` has a font to render with out of the box, - with zero asset setup required. - - ------------------------------ - - License: SIL Open Font License, Version 1.1 - https://scripts.sil.org/OFL - - SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 - - PREAMBLE - The goals of the Open Font License (OFL) are to stimulate worldwide - development of collaborative font projects, to support the font creation - efforts of academic and linguistic communities, and to provide a free and - open framework in which fonts may be shared and improved in partnership - with others. - - The OFL allows the licensed fonts to be used, studied, modified and - redistributed freely as long as they are not sold by themselves. The - fonts, including any derivative works, can be bundled, embedded, - redistributed and/or sold with any software provided that any reserved - names are not used by derivative works. The fonts and derivatives, - however, cannot be released under any other type of license. The - requirement for fonts to remain under this license does not apply to any - document created using the fonts or their derivatives. - - DEFINITIONS - "Font Software" refers to the set of files released by the Copyright - Holder(s) under this license and clearly marked as such. This may include - source files, build scripts and documentation. - - "Reserved Font Name" refers to any names specified as such after the - copyright statement(s). - - "Original Version" refers to the collection of Font Software components - as distributed by the Copyright Holder(s). - - "Modified Version" refers to any derivative made by adding to, deleting, - or substituting, in part or in whole, any of the components of the - Original Version, by changing formats or by porting the Font Software to - a new environment. - - "Author" refers to any designer, engineer, programmer, technical writer - or other person who contributed to the Font Software. - - PERMISSION & CONDITIONS - Permission is hereby granted, free of charge, to any person obtaining a - copy of the Font Software, to use, study, copy, merge, embed, modify, - redistribute, and sell modified and unmodified copies of the Font - Software, subject to the following conditions: - - 1) Neither the Font Software nor any of its individual components, in - Original or Modified Versions, may be sold by itself. - - 2) Original or Modified Versions of the Font Software may be bundled, - redistributed and/or sold with any software, provided that each copy - contains the above copyright notice and this license. These can be - included either as stand-alone text files, human-readable headers or - in the appropriate machine-readable metadata fields within text or - binary files as long as those fields can be easily viewed by the user. - - 3) No Modified Version of the Font Software may use the Reserved Font - Name(s) unless explicit written permission is granted by the - corresponding Copyright Holder. This restriction only applies to the - primary font name as presented to the users. - - 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font - Software shall not be used to promote, endorse or advertise any - Modified Version, except to acknowledge the contribution(s) of the - Copyright Holder(s) and the Author(s) or with their explicit written - permission. - - 5) The Font Software, modified or unmodified, in part or in whole, must - be distributed entirely under this license, and must not be - distributed under any other license. The requirement for fonts to - remain under this license does not apply to any document created - using the Font Software. - - TERMINATION - This license becomes null and void if any of the above conditions are - not met. - - DISCLAIMER - THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE - COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL - DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER - DEALINGS IN THE FONT SOFTWARE. diff --git a/documentation-site/static/fonts/default/default.json b/documentation-site/static/fonts/default/default.json deleted file mode 100644 index afc590a54..000000000 --- a/documentation-site/static/fonts/default/default.json +++ /dev/null @@ -1,1529 +0,0 @@ -{ - "formatVersion": 2, - "type": "msdf", - "atlasImage": "default.png", - "atlasSize": { - "width": 512, - "height": 512 - }, - "distanceRange": 16, - "metrics": { - "lineHeight": 1.0952380952380953, - "ascender": 0.9285714285714286, - "descender": -0.40476190476190477, - "capHeight": 0.8809523809523809 - }, - "glyphs": [ - { - "codePoint": 40, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.5238095238095238, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0, - "top": 1, - "right": 0.052734375, - "bottom": 0.892578125 - } - }, - { - "codePoint": 41, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.9047619047619048, - "right": 0.4523809523809524, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0, - "top": 0.890625, - "right": 0.052734375, - "bottom": 0.783203125 - } - }, - { - "codePoint": 87, - "advance": 0.9523809523809523, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.8809523809523809, - "right": 1.119047619047619, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0, - "top": 0.78125, - "right": 0.107421875, - "bottom": 0.693359375 - } - }, - { - "codePoint": 91, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.4523809523809524, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.0546875, - "top": 1, - "right": 0.1015625, - "bottom": 0.892578125 - } - }, - { - "codePoint": 93, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.9047619047619048, - "right": 0.38095238095238093, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.0546875, - "top": 0.890625, - "right": 0.1015625, - "bottom": 0.783203125 - } - }, - { - "codePoint": 106, - "advance": 0.21428571428571427, - "planeBounds": { - "left": -0.21428571428571427, - "top": 0.9047619047619048, - "right": 0.35714285714285715, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.103515625, - "top": 1, - "right": 0.150390625, - "bottom": 0.892578125 - } - }, - { - "codePoint": 123, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.9047619047619048, - "right": 0.5238095238095238, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.103515625, - "top": 0.890625, - "right": 0.16015625, - "bottom": 0.783203125 - } - }, - { - "codePoint": 124, - "advance": 0.2619047619047619, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.9047619047619048, - "right": 0.35714285714285715, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.15234375, - "top": 1, - "right": 0.189453125, - "bottom": 0.892578125 - } - }, - { - "codePoint": 125, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.9047619047619048, - "right": 0.5238095238095238, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0, - "top": 0.69140625, - "right": 0.056640625, - "bottom": 0.583984375 - } - }, - { - "codePoint": 81, - "advance": 0.7857142857142857, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.9285714285714286, - "bottom": -0.38095238095238093 - }, - "atlasBounds": { - "left": 0, - "top": 0.58203125, - "right": 0.087890625, - "bottom": 0.478515625 - } - }, - { - "codePoint": 64, - "advance": 1.0238095238095237, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 1.119047619047619, - "bottom": -0.3333333333333333 - }, - "atlasBounds": { - "left": 0.05859375, - "top": 0.69140625, - "right": 0.16015625, - "bottom": 0.58984375 - } - }, - { - "codePoint": 36, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.9285714285714286, - "right": 0.7142857142857143, - "bottom": -0.2619047619047619 - }, - "atlasBounds": { - "left": 0, - "top": 0.4765625, - "right": 0.07421875, - "bottom": 0.37890625 - } - }, - { - "codePoint": 37, - "advance": 0.8809523809523809, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 1.0238095238095237, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.109375, - "top": 0.78125, - "right": 0.20703125, - "bottom": 0.693359375 - } - }, - { - "codePoint": 47, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.9047619047619048, - "right": 0.47619047619047616, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.162109375, - "top": 0.890625, - "right": 0.216796875, - "bottom": 0.798828125 - } - }, - { - "codePoint": 92, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.9047619047619048, - "right": 0.47619047619047616, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.19140625, - "top": 1, - "right": 0.24609375, - "bottom": 0.908203125 - } - }, - { - "codePoint": 98, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.7142857142857143, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0, - "top": 0.376953125, - "right": 0.068359375, - "bottom": 0.28515625 - } - }, - { - "codePoint": 100, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.9047619047619048, - "right": 0.6904761904761905, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0, - "top": 0.283203125, - "right": 0.068359375, - "bottom": 0.19140625 - } - }, - { - "codePoint": 103, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.6904761904761905, - "bottom": -0.38095238095238093 - }, - "atlasBounds": { - "left": 0, - "top": 0.189453125, - "right": 0.068359375, - "bottom": 0.09765625 - } - }, - { - "codePoint": 112, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.7380952380952381, - "right": 0.7142857142857143, - "bottom": -0.38095238095238093 - }, - "atlasBounds": { - "left": 0, - "top": 0.095703125, - "right": 0.068359375, - "bottom": 0.00390625 - } - }, - { - "codePoint": 113, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.6904761904761905, - "bottom": -0.38095238095238093 - }, - "atlasBounds": { - "left": 0.0703125, - "top": 0.376953125, - "right": 0.138671875, - "bottom": 0.28515625 - } - }, - { - "codePoint": 121, - "advance": 0.5, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.7142857142857143, - "right": 0.6904761904761905, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.076171875, - "top": 0.4765625, - "right": 0.1484375, - "bottom": 0.384765625 - } - }, - { - "codePoint": 48, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.08984375, - "top": 0.587890625, - "right": 0.16015625, - "bottom": 0.498046875 - } - }, - { - "codePoint": 51, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.0703125, - "top": 0.283203125, - "right": 0.140625, - "bottom": 0.193359375 - } - }, - { - "codePoint": 54, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.6904761904761905, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.140625, - "top": 0.3828125, - "right": 0.208984375, - "bottom": 0.29296875 - } - }, - { - "codePoint": 56, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.150390625, - "top": 0.49609375, - "right": 0.220703125, - "bottom": 0.40625 - } - }, - { - "codePoint": 57, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.6904761904761905, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.0703125, - "top": 0.19140625, - "right": 0.138671875, - "bottom": 0.1015625 - } - }, - { - "codePoint": 67, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.8809523809523809, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.0703125, - "top": 0.099609375, - "right": 0.154296875, - "bottom": 0.009765625 - } - }, - { - "codePoint": 71, - "advance": 0.7857142857142857, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.8809523809523809, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.140625, - "top": 0.19140625, - "right": 0.224609375, - "bottom": 0.1015625 - } - }, - { - "codePoint": 79, - "advance": 0.7857142857142857, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.9285714285714286, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.142578125, - "top": 0.291015625, - "right": 0.23046875, - "bottom": 0.201171875 - } - }, - { - "codePoint": 83, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.8095238095238095, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.15625, - "top": 0.099609375, - "right": 0.234375, - "bottom": 0.009765625 - } - }, - { - "codePoint": 102, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.9047619047619048, - "right": 0.47619047619047616, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.2265625, - "top": 0.19921875, - "right": 0.279296875, - "bottom": 0.109375 - } - }, - { - "codePoint": 104, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.236328125, - "top": 0.107421875, - "right": 0.302734375, - "bottom": 0.017578125 - } - }, - { - "codePoint": 105, - "advance": 0.21428571428571427, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.35714285714285715, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.2109375, - "top": 0.404296875, - "right": 0.25, - "bottom": 0.314453125 - } - }, - { - "codePoint": 107, - "advance": 0.5, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.232421875, - "top": 0.3125, - "right": 0.298828125, - "bottom": 0.22265625 - } - }, - { - "codePoint": 108, - "advance": 0.21428571428571427, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.9047619047619048, - "right": 0.35714285714285715, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.28125, - "top": 0.220703125, - "right": 0.3203125, - "bottom": 0.130859375 - } - }, - { - "codePoint": 119, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.7142857142857143, - "right": 0.9047619047619048, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.3046875, - "top": 0.12890625, - "right": 0.39453125, - "bottom": 0.0546875 - } - }, - { - "codePoint": 33, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.8809523809523809, - "right": 0.38095238095238093, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.162109375, - "top": 0.69140625, - "right": 0.201171875, - "bottom": 0.603515625 - } - }, - { - "codePoint": 35, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.8809523809523809, - "right": 0.7380952380952381, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.162109375, - "top": 0.6015625, - "right": 0.23828125, - "bottom": 0.513671875 - } - }, - { - "codePoint": 38, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.8333333333333334, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.203125, - "top": 0.69140625, - "right": 0.28515625, - "bottom": 0.603515625 - } - }, - { - "codePoint": 49, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.208984375, - "top": 0.796875, - "right": 0.275390625, - "bottom": 0.708984375 - } - }, - { - "codePoint": 50, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.22265625, - "top": 0.51171875, - "right": 0.291015625, - "bottom": 0.423828125 - } - }, - { - "codePoint": 52, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.240234375, - "top": 0.6015625, - "right": 0.3125, - "bottom": 0.513671875 - } - }, - { - "codePoint": 53, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.21875, - "top": 0.90625, - "right": 0.2890625, - "bottom": 0.818359375 - } - }, - { - "codePoint": 55, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.248046875, - "top": 1, - "right": 0.31640625, - "bottom": 0.912109375 - } - }, - { - "codePoint": 63, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.251953125, - "top": 0.421875, - "right": 0.322265625, - "bottom": 0.333984375 - } - }, - { - "codePoint": 65, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.8809523809523809, - "right": 0.8571428571428571, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.29296875, - "top": 0.51171875, - "right": 0.37890625, - "bottom": 0.423828125 - } - }, - { - "codePoint": 66, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.7857142857142857, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.30078125, - "top": 0.33203125, - "right": 0.375, - "bottom": 0.244140625 - } - }, - { - "codePoint": 68, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8571428571428571, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.32421875, - "top": 0.421875, - "right": 0.404296875, - "bottom": 0.333984375 - } - }, - { - "codePoint": 69, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8095238095238095, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.322265625, - "top": 0.2421875, - "right": 0.3984375, - "bottom": 0.154296875 - } - }, - { - "codePoint": 70, - "advance": 0.6190476190476191, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.7619047619047619, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.376953125, - "top": 0.33203125, - "right": 0.44921875, - "bottom": 0.244140625 - } - }, - { - "codePoint": 72, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8095238095238095, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.27734375, - "top": 0.81640625, - "right": 0.353515625, - "bottom": 0.728515625 - } - }, - { - "codePoint": 73, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.8809523809523809, - "right": 0.38095238095238093, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.291015625, - "top": 0.91015625, - "right": 0.330078125, - "bottom": 0.822265625 - } - }, - { - "codePoint": 74, - "advance": 0.5, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.6190476190476191, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.318359375, - "top": 1, - "right": 0.3828125, - "bottom": 0.912109375 - } - }, - { - "codePoint": 75, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8333333333333334, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.33203125, - "top": 0.91015625, - "right": 0.41015625, - "bottom": 0.822265625 - } - }, - { - "codePoint": 76, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.384765625, - "top": 1, - "right": 0.453125, - "bottom": 0.912109375 - } - }, - { - "codePoint": 77, - "advance": 0.8333333333333334, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.9285714285714286, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.287109375, - "top": 0.7265625, - "right": 0.373046875, - "bottom": 0.638671875 - } - }, - { - "codePoint": 78, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8095238095238095, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.35546875, - "top": 0.8203125, - "right": 0.431640625, - "bottom": 0.732421875 - } - }, - { - "codePoint": 80, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.7857142857142857, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.412109375, - "top": 0.91015625, - "right": 0.486328125, - "bottom": 0.822265625 - } - }, - { - "codePoint": 82, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8571428571428571, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.455078125, - "top": 1, - "right": 0.53515625, - "bottom": 0.912109375 - } - }, - { - "codePoint": 84, - "advance": 0.6190476190476191, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.7857142857142857, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.314453125, - "top": 0.63671875, - "right": 0.392578125, - "bottom": 0.548828125 - } - }, - { - "codePoint": 85, - "advance": 0.7142857142857143, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.8809523809523809, - "right": 0.8333333333333334, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.375, - "top": 0.73046875, - "right": 0.453125, - "bottom": 0.642578125 - } - }, - { - "codePoint": 86, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.8809523809523809, - "right": 0.8571428571428571, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.43359375, - "top": 0.8203125, - "right": 0.51953125, - "bottom": 0.732421875 - } - }, - { - "codePoint": 88, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.8333333333333334, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.48828125, - "top": 0.91015625, - "right": 0.5703125, - "bottom": 0.822265625 - } - }, - { - "codePoint": 89, - "advance": 0.6666666666666666, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.8333333333333334, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.537109375, - "top": 1, - "right": 0.619140625, - "bottom": 0.912109375 - } - }, - { - "codePoint": 90, - "advance": 0.6190476190476191, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.7619047619047619, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.380859375, - "top": 0.546875, - "right": 0.45703125, - "bottom": 0.458984375 - } - }, - { - "codePoint": 109, - "advance": 0.8333333333333334, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.7380952380952381, - "right": 0.9523809523809523, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.39453125, - "top": 0.640625, - "right": 0.482421875, - "bottom": 0.564453125 - } - }, - { - "codePoint": 59, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.7142857142857143, - "right": 0.38095238095238093, - "bottom": -0.3333333333333333 - }, - "atlasBounds": { - "left": 0.455078125, - "top": 0.73046875, - "right": 0.494140625, - "bottom": 0.64453125 - } - }, - { - "codePoint": 116, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8333333333333334, - "right": 0.47619047619047616, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.40625, - "top": 0.45703125, - "right": 0.458984375, - "bottom": 0.373046875 - } - }, - { - "codePoint": 95, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.21428571428571427, - "top": 0.047619047619047616, - "right": 0.7380952380952381, - "bottom": -0.40476190476190477 - }, - "atlasBounds": { - "left": 0.40625, - "top": 0.37109375, - "right": 0.484375, - "bottom": 0.333984375 - } - }, - { - "codePoint": 97, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.7619047619047619, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.458984375, - "top": 0.5625, - "right": 0.533203125, - "bottom": 0.486328125 - } - }, - { - "codePoint": 99, - "advance": 0.5, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.6666666666666666, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.484375, - "top": 0.642578125, - "right": 0.55078125, - "bottom": 0.56640625 - } - }, - { - "codePoint": 101, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.49609375, - "top": 0.73046875, - "right": 0.56640625, - "bottom": 0.654296875 - } - }, - { - "codePoint": 110, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.7380952380952381, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.521484375, - "top": 0.8203125, - "right": 0.587890625, - "bottom": 0.744140625 - } - }, - { - "codePoint": 111, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7380952380952381, - "right": 0.7142857142857143, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.572265625, - "top": 0.91015625, - "right": 0.642578125, - "bottom": 0.833984375 - } - }, - { - "codePoint": 114, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.7380952380952381, - "right": 0.5238095238095238, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.62109375, - "top": 1, - "right": 0.673828125, - "bottom": 0.923828125 - } - }, - { - "codePoint": 115, - "advance": 0.5, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.7380952380952381, - "right": 0.6428571428571429, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.4609375, - "top": 0.484375, - "right": 0.52734375, - "bottom": 0.408203125 - } - }, - { - "codePoint": 117, - "advance": 0.5476190476190477, - "planeBounds": { - "left": -0.11904761904761904, - "top": 0.7142857142857143, - "right": 0.6904761904761905, - "bottom": -0.21428571428571427 - }, - "atlasBounds": { - "left": 0.396484375, - "top": 0.15234375, - "right": 0.462890625, - "bottom": 0.076171875 - } - }, - { - "codePoint": 58, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.7142857142857143, - "right": 0.38095238095238093, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.396484375, - "top": 0.07421875, - "right": 0.435546875, - "bottom": 0 - } - }, - { - "codePoint": 118, - "advance": 0.5, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.7142857142857143, - "right": 0.6904761904761905, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.4375, - "top": 0.07421875, - "right": 0.509765625, - "bottom": 0 - } - }, - { - "codePoint": 120, - "advance": 0.5, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.7142857142857143, - "right": 0.6666666666666666, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.400390625, - "top": 0.2421875, - "right": 0.470703125, - "bottom": 0.16796875 - } - }, - { - "codePoint": 122, - "advance": 0.5, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7142857142857143, - "right": 0.6428571428571429, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.451171875, - "top": 0.33203125, - "right": 0.515625, - "bottom": 0.2578125 - } - }, - { - "codePoint": 43, - "advance": 0.5952380952380952, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7619047619047619, - "right": 0.7142857142857143, - "bottom": -0.11904761904761904 - }, - "atlasBounds": { - "left": 0.486328125, - "top": 0.40625, - "right": 0.556640625, - "bottom": 0.333984375 - } - }, - { - "codePoint": 60, - "advance": 0.5952380952380952, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7619047619047619, - "right": 0.7142857142857143, - "bottom": -0.11904761904761904 - }, - "atlasBounds": { - "left": 0.529296875, - "top": 0.484375, - "right": 0.599609375, - "bottom": 0.412109375 - } - }, - { - "codePoint": 62, - "advance": 0.5952380952380952, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.7619047619047619, - "right": 0.7142857142857143, - "bottom": -0.11904761904761904 - }, - "atlasBounds": { - "left": 0.53515625, - "top": 0.564453125, - "right": 0.60546875, - "bottom": 0.4921875 - } - }, - { - "codePoint": 126, - "advance": 0.5952380952380952, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.5952380952380952, - "right": 0.7380952380952381, - "bottom": 0.09523809523809523 - }, - "atlasBounds": { - "left": 0.3046875, - "top": 0.052734375, - "right": 0.376953125, - "bottom": 0.01171875 - } - }, - { - "codePoint": 61, - "advance": 0.5952380952380952, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.6904761904761905, - "right": 0.7142857142857143, - "bottom": -0.023809523809523808 - }, - "atlasBounds": { - "left": 0.552734375, - "top": 0.65234375, - "right": 0.623046875, - "bottom": 0.59375 - } - }, - { - "codePoint": 94, - "advance": 0.47619047619047616, - "planeBounds": { - "left": -0.19047619047619047, - "top": 0.8809523809523809, - "right": 0.6428571428571429, - "bottom": 0.14285714285714285 - }, - "atlasBounds": { - "left": 0.568359375, - "top": 0.7421875, - "right": 0.63671875, - "bottom": 0.681640625 - } - }, - { - "codePoint": 42, - "advance": 0.38095238095238093, - "planeBounds": { - "left": -0.16666666666666666, - "top": 0.8809523809523809, - "right": 0.5714285714285714, - "bottom": 0.14285714285714285 - }, - "atlasBounds": { - "left": 0.58984375, - "top": 0.83203125, - "right": 0.650390625, - "bottom": 0.771484375 - } - }, - { - "codePoint": 34, - "advance": 0.35714285714285715, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.5, - "bottom": 0.2857142857142857 - }, - "atlasBounds": { - "left": 0.64453125, - "top": 0.921875, - "right": 0.697265625, - "bottom": 0.873046875 - } - }, - { - "codePoint": 44, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.2857142857142857, - "right": 0.38095238095238093, - "bottom": -0.3333333333333333 - }, - "atlasBounds": { - "left": 0.67578125, - "top": 1, - "right": 0.71484375, - "bottom": 0.94921875 - } - }, - { - "codePoint": 45, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.5, - "right": 0.47619047619047616, - "bottom": 0.047619047619047616 - }, - "atlasBounds": { - "left": 0.64453125, - "top": 0.87109375, - "right": 0.6953125, - "bottom": 0.833984375 - } - }, - { - "codePoint": 39, - "advance": 0.19047619047619047, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.8809523809523809, - "right": 0.3333333333333333, - "bottom": 0.2857142857142857 - }, - "atlasBounds": { - "left": 0.46484375, - "top": 0.166015625, - "right": 0.50390625, - "bottom": 0.1171875 - } - }, - { - "codePoint": 96, - "advance": 0.3333333333333333, - "planeBounds": { - "left": -0.14285714285714285, - "top": 0.9285714285714286, - "right": 0.4523809523809524, - "bottom": 0.40476190476190477 - }, - "atlasBounds": { - "left": 0.47265625, - "top": 0.255859375, - "right": 0.521484375, - "bottom": 0.212890625 - } - }, - { - "codePoint": 46, - "advance": 0.2857142857142857, - "planeBounds": { - "left": -0.09523809523809523, - "top": 0.2857142857142857, - "right": 0.38095238095238093, - "bottom": -0.19047619047619047 - }, - "atlasBounds": { - "left": 0.46484375, - "top": 0.115234375, - "right": 0.50390625, - "bottom": 0.076171875 - } - }, - { - "codePoint": 32, - "advance": 0.2857142857142857, - "planeBounds": null, - "atlasBounds": null - } - ], - "kerning": {} -} diff --git a/documentation-site/static/fonts/default/default.png b/documentation-site/static/fonts/default/default.png deleted file mode 100644 index b484d79bbbebf1cd95290a06f0730956c2187c9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167824 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

SW=x&fn~9lA69tbN%^giOD@+ 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%0DlRDJFDO@`o5bj0n%J1Vp^`_mHdo^%oEgVB7MQ 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 diff --git a/e2e/fixtures/scenes/text-effects-overlap.ts b/e2e/fixtures/scenes/text-effects-overlap.ts index c74d48ddd..65b9b4eca 100644 --- a/e2e/fixtures/scenes/text-effects-overlap.ts +++ b/e2e/fixtures/scenes/text-effects-overlap.ts @@ -9,6 +9,7 @@ import { createRenderEcsSystem, createTextShapingEcsSystem, createTransformEcsSystem, + CURRENT_FONT_ATLAS_FORMAT_VERSION, EcsWorld, FontAtlas, Time, @@ -239,9 +240,8 @@ export const createScene: CreateScene = async ( const fontAtlas: FontAtlas = { data: { - formatVersion: 1, + formatVersion: CURRENT_FONT_ATLAS_FORMAT_VERSION, type: 'msdf', - atlasImage: 'synthetic.png', atlasSize: { width: SYNTHETIC_GLYPH_TILE_SIZE, height: SYNTHETIC_GLYPH_TILE_SIZE, @@ -251,7 +251,12 @@ export const createScene: CreateScene = async ( // ink (which spans exactly 1 em vertically around its own center, by // construction) on the entity's position - see the derivation this // module's own doc comment gives for `advanceEm`. - metrics: { lineHeight: 1, ascender: 0.5, descender: 0.5 }, + metrics: { + lineHeight: 1, + ascender: 0.5, + descender: 0.5, + capHeight: 0.5, + }, glyphs: new Map([ [ ATLAS_A_CODE_POINT, diff --git a/package.json b/package.json index 572858bc3..ebc37d332 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,9 @@ "types": "./dist/finite-state-machine/index.d.ts", "default": "./dist/finite-state-machine/index.js" } - } + }, + "./fonts/default/default.json": "./assets/fonts/default/default.json", + "./fonts/default/default.png": "./assets/fonts/default/default.png" }, "types": "./dist/index.d.ts", "bin": { @@ -132,7 +134,7 @@ "test:e2e": "playwright test --config e2e/playwright.config.ts", "pretest:e2e:ui": "node -e \"console.log('[e2e] npm run test:e2e:ui starting', new Date().toISOString())\"", "test:e2e:ui": "playwright test --config e2e/playwright.config.ts --ui", - "check-exports": "attw --pack . --ignore-rules false-esm internal-resolution-error --profile esm-only", + "check-exports": "attw --pack . --ignore-rules false-esm internal-resolution-error --profile esm-only --exclude-entrypoints ./fonts/default/default.json ./fonts/default/default.png", "check-types": "tsc --noEmit --project tsconfig.ci.json", "check-types:e2e": "tsc --noEmit --project e2e/tsconfig.json", "cspell": "cspell \"**\"", diff --git a/scripts/generate-font-atlas.mjs b/scripts/generate-font-atlas.mjs index d8b3967a8..68fbea75a 100755 --- a/scripts/generate-font-atlas.mjs +++ b/scripts/generate-font-atlas.mjs @@ -192,7 +192,7 @@ function computeCapHeight(glyphs, fallback) { * versioned `FontAtlasFileData` schema (see `src/text/font-atlas`), so * runtime consumers never depend on a third-party generator's own format. */ -function normalizeBmfontJson(raw, atlasImageFilename) { +function normalizeBmfontJson(raw) { if (raw.distanceField?.fieldType !== 'msdf') { throw new Error( `Expected a "msdf" distance field, got "${raw.distanceField?.fieldType}". Forge's text renderer only supports MSDF atlases.`, @@ -229,7 +229,6 @@ function normalizeBmfontJson(raw, atlasImageFilename) { return { formatVersion: CURRENT_FONT_ATLAS_FORMAT_VERSION, type: 'msdf', - atlasImage: atlasImageFilename, atlasSize: { width: scaleW, height: scaleH }, distanceRange: raw.distanceField.distanceRange, metrics: { @@ -318,8 +317,7 @@ async function main() { } const raw = JSON.parse(font.data); - const atlasImageFilename = `${resolveOutBasename(resolvedOutPath)}.png`; - const fileData = normalizeBmfontJson(raw, atlasImageFilename); + const fileData = normalizeBmfontJson(raw); writeFileSync(`${resolvedOutPath}.png`, textures[0].texture); writeFileSync(`${resolvedOutPath}.json`, JSON.stringify(fileData, null, 2)); @@ -329,14 +327,6 @@ async function main() { ); } -function resolveOutBasename(resolvedOutPath) { - const separatorIndex = resolvedOutPath.lastIndexOf('/'); - - return separatorIndex === -1 - ? resolvedOutPath - : resolvedOutPath.slice(separatorIndex + 1); -} - try { await main(); } catch (error) { diff --git a/src/text/font-atlas/font-atlas-cache.test.ts b/src/text/font-atlas/font-atlas-cache.test.ts index 82846f7a8..967ee8682 100644 --- a/src/text/font-atlas/font-atlas-cache.test.ts +++ b/src/text/font-atlas/font-atlas-cache.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from 'vitest'; +import { afterEach, describe, expect, it, vi } from 'vitest'; import { ImageCache } from '../../asset-loading/index.js'; import { CURRENT_FONT_ATLAS_FORMAT_VERSION } from './font-atlas-data.js'; import type { FontAtlasFileData } from './font-atlas-file-data.js'; @@ -7,7 +7,6 @@ import { FontAtlasCache } from './font-atlas-cache.js'; const buildValidJson = (): FontAtlasFileData => ({ formatVersion: CURRENT_FONT_ATLAS_FORMAT_VERSION, type: 'msdf', - atlasImage: 'my-font.png', atlasSize: { width: 512, height: 512 }, distanceRange: 4, metrics: { lineHeight: 1.2, ascender: 0.9, descender: -0.2, capHeight: 0.7 }, @@ -22,6 +21,11 @@ const buildValidJson = (): FontAtlasFileData => ({ kerning: {}, }); +const urls = { + metricsUrl: 'assets/fonts/my-font.json', + imageUrl: 'assets/fonts/my-font.png', +}; + function mockFetchJsonResponse(json: unknown, ok = true): void { vi.stubGlobal( 'fetch', @@ -34,86 +38,180 @@ function mockFetchJsonResponse(json: unknown, ok = true): void { ); } +function createImage(width = 512, height = 512): HTMLImageElement { + const image = new Image(); + + Object.defineProperty(image, 'naturalWidth', { value: width }); + Object.defineProperty(image, 'naturalHeight', { value: height }); + + return image; +} + +function createImageCache(image = createImage()): ImageCache { + const imageCache = new ImageCache(); + + vi.spyOn(imageCache, 'getOrLoad').mockResolvedValue(image); + + return imageCache; +} + describe('FontAtlasCache', () => { + afterEach(() => { + vi.unstubAllGlobals(); + }); + it('should throw when getting a font atlas that has not been loaded', () => { const fontAtlasCache = new FontAtlasCache(); expect(() => fontAtlasCache.get('assets/fonts/my-font.json')).toThrow( - 'Font atlas with key "assets/fonts/my-font.json" not found in store.', + 'Font atlas with metrics URL "assets/fonts/my-font.json" not found in store.', ); }); it('should load and cache a valid font atlas', async () => { mockFetchJsonResponse(buildValidJson()); - const mockImage = new Image(); - const imageCache = new ImageCache(); - const getOrLoadSpy = vi - .spyOn(imageCache, 'getOrLoad') - .mockResolvedValue(mockImage); - + const image = createImage(); + const imageCache = createImageCache(image); const fontAtlasCache = new FontAtlasCache(imageCache); - const fontAtlas = await fontAtlasCache.getOrLoad( - 'assets/fonts/my-font.json', - ); + const fontAtlas = await fontAtlasCache.getOrLoad(urls); expect(fetch).toHaveBeenCalledWith('assets/fonts/my-font.json'); - expect(getOrLoadSpy).toHaveBeenCalledWith('assets/fonts/my-font.png'); - expect(fontAtlas.image).toBe(mockImage); + expect(imageCache.getOrLoad).toHaveBeenCalledWith( + 'assets/fonts/my-font.png', + ); + expect(fontAtlas.image).toBe(image); expect(fontAtlas.data.glyphs.get(65)?.advance).toBeCloseTo(0.6); expect(fontAtlasCache.get('assets/fonts/my-font.json')).toBe(fontAtlas); }); - it('should resolve the atlas image relative to a nested key', async () => { - mockFetchJsonResponse(buildValidJson()); + it.each([ + { + name: 'different directories with query strings', + metricsUrl: '/assets/metrics/my-font.json?v=a/b', + imageUrl: '/static/images/my-font-3f2a.png?v=c/d#e', + }, + { + name: 'blob URLs', + metricsUrl: 'blob:https://example.com/0f1e2d3c', + imageUrl: 'blob:https://example.com/4b5a6978', + }, + ])( + 'should load the image from its own URL ($name)', + async ({ metricsUrl, imageUrl }) => { + mockFetchJsonResponse(buildValidJson()); + + const imageCache = createImageCache(); + const fontAtlasCache = new FontAtlasCache(imageCache); + await fontAtlasCache.getOrLoad({ metricsUrl, imageUrl }); - const imageCache = new ImageCache(); - const getOrLoadSpy = vi - .spyOn(imageCache, 'getOrLoad') - .mockResolvedValue(new Image()); + expect(fetch).toHaveBeenCalledWith(metricsUrl); + expect(imageCache.getOrLoad).toHaveBeenCalledWith(imageUrl); + }, + ); + it('should load a metrics file that still names its atlas image', async () => { + mockFetchJsonResponse({ ...buildValidJson(), atlasImage: 'other.png' }); + + const imageCache = createImageCache(); const fontAtlasCache = new FontAtlasCache(imageCache); - await fontAtlasCache.getOrLoad('assets/fonts/heading/my-font.json'); + await fontAtlasCache.getOrLoad(urls); - expect(getOrLoadSpy).toHaveBeenCalledWith( - 'assets/fonts/heading/my-font.png', + expect(imageCache.getOrLoad).toHaveBeenCalledWith( + 'assets/fonts/my-font.png', ); }); - it('should resolve the atlas image relative to a root-level key', async () => { + it('should not re-fetch a font atlas that is already cached', async () => { mockFetchJsonResponse(buildValidJson()); - const imageCache = new ImageCache(); - const getOrLoadSpy = vi - .spyOn(imageCache, 'getOrLoad') - .mockResolvedValue(new Image()); + const fontAtlasCache = new FontAtlasCache(createImageCache()); + const first = await fontAtlasCache.getOrLoad(urls); + const second = await fontAtlasCache.getOrLoad(urls); + expect(fetch).toHaveBeenCalledTimes(1); + expect(second).toBe(first); + }); + + it('should share one load between concurrent requests for the same atlas', async () => { + mockFetchJsonResponse(buildValidJson()); + + const imageCache = createImageCache(); const fontAtlasCache = new FontAtlasCache(imageCache); - await fontAtlasCache.getOrLoad('my-font.json'); + const [first, second] = await Promise.all([ + fontAtlasCache.getOrLoad(urls), + fontAtlasCache.getOrLoad({ ...urls }), + ]); - expect(getOrLoadSpy).toHaveBeenCalledWith('my-font.png'); + expect(fetch).toHaveBeenCalledTimes(1); + expect(imageCache.getOrLoad).toHaveBeenCalledTimes(1); + expect(second).toBe(first); }); - it('should not re-fetch a font atlas that is already cached', async () => { + it('should throw when a loading atlas is requested with a different image', async () => { mockFetchJsonResponse(buildValidJson()); - const imageCache = new ImageCache(); - vi.spyOn(imageCache, 'getOrLoad').mockResolvedValue(new Image()); + const fontAtlasCache = new FontAtlasCache(createImageCache()); + const firstLoad = fontAtlasCache.getOrLoad(urls); - const fontAtlasCache = new FontAtlasCache(imageCache); - await fontAtlasCache.getOrLoad('assets/fonts/my-font.json'); - await fontAtlasCache.getOrLoad('assets/fonts/my-font.json'); + await expect( + fontAtlasCache.getOrLoad({ ...urls, imageUrl: 'other-font.png' }), + ).rejects.toThrow( + 'Font atlas "assets/fonts/my-font.json" was already requested with image "assets/fonts/my-font.png", so it can\'t also be loaded with image "other-font.png".', + ); + await expect(firstLoad).resolves.toBeDefined(); + }); - expect(fetch).toHaveBeenCalledTimes(1); + it('should throw when a loaded atlas is requested with a different image', async () => { + mockFetchJsonResponse(buildValidJson()); + + const fontAtlasCache = new FontAtlasCache(createImageCache()); + await fontAtlasCache.getOrLoad(urls); + + await expect( + fontAtlasCache.getOrLoad({ ...urls, imageUrl: 'other-font.png' }), + ).rejects.toThrow(/was already requested with image/); + }); + + it("should throw when the image's size doesn't match the metrics' atlasSize", async () => { + mockFetchJsonResponse(buildValidJson()); + + const fontAtlasCache = new FontAtlasCache( + createImageCache(createImage(256, 512)), + ); + + await expect(fontAtlasCache.getOrLoad(urls)).rejects.toThrow( + 'Font atlas image "assets/fonts/my-font.png" is 256x512, but the metrics at "assets/fonts/my-font.json" expect 512x512. Check that both files come from the same generated atlas.', + ); + expect(() => fontAtlasCache.get(urls.metricsUrl)).toThrow( + /not found in store/, + ); + }); + + it('should load again after a failed load', async () => { + mockFetchJsonResponse({}, false); + + const fontAtlasCache = new FontAtlasCache(createImageCache()); + + await expect(fontAtlasCache.getOrLoad(urls)).rejects.toThrow( + /Failed to load font atlas JSON/, + ); + + mockFetchJsonResponse(buildValidJson()); + + await expect(fontAtlasCache.getOrLoad(urls)).resolves.toBeDefined(); }); it('should throw a descriptive error when the JSON fetch fails', async () => { mockFetchJsonResponse({}, false); - const fontAtlasCache = new FontAtlasCache(); + const fontAtlasCache = new FontAtlasCache(createImageCache()); await expect( - fontAtlasCache.getOrLoad('assets/fonts/missing-font.json'), + fontAtlasCache.getOrLoad({ + metricsUrl: 'assets/fonts/missing-font.json', + imageUrl: 'assets/fonts/missing-font.png', + }), ).rejects.toThrow( 'Failed to load font atlas JSON at "assets/fonts/missing-font.json": 404 Not Found', ); @@ -122,10 +220,10 @@ describe('FontAtlasCache', () => { it('should throw a descriptive error when the JSON is malformed', async () => { mockFetchJsonResponse({ formatVersion: 999 }); - const fontAtlasCache = new FontAtlasCache(); + const fontAtlasCache = new FontAtlasCache(createImageCache()); - await expect( - fontAtlasCache.getOrLoad('assets/fonts/broken-font.json'), - ).rejects.toThrow(/unsupported formatVersion "999"/); + await expect(fontAtlasCache.getOrLoad(urls)).rejects.toThrow( + /unsupported formatVersion "999"/, + ); }); }); diff --git a/src/text/font-atlas/font-atlas-cache.ts b/src/text/font-atlas/font-atlas-cache.ts index 08549c067..6c346d1cc 100644 --- a/src/text/font-atlas/font-atlas-cache.ts +++ b/src/text/font-atlas/font-atlas-cache.ts @@ -1,89 +1,135 @@ -import { type AssetCache, ImageCache } from '../../asset-loading/index.js'; +import { ImageCache } from '../../asset-loading/index.js'; import type { FontAtlas } from './font-atlas.js'; +import type { FontAtlasData } from './font-atlas-data.js'; import { toFontAtlasData } from './font-atlas-file-data.js'; import { validateFontAtlasFileData } from './validate-font-atlas-data.js'; /** - * Loads and caches `FontAtlas`es: a metrics JSON file plus its atlas image, - * keyed by the JSON file's path (e.g. `getOrLoad('assets/fonts/my-font.json')` - * loads that file, which in turn points at its own atlas image, resolved - * relative to the JSON file). + * The two files a font atlas is loaded from. Pass the URLs your bundler + * gives you for each file (e.g. Vite's `import url from './font.json?url'` + * and `import url from './font.png'`), so content-hashed file names work. */ -export class FontAtlasCache implements AssetCache { - public assets = new Map(); +export interface FontAtlasUrls { + /** The URL of the atlas's metrics JSON file. */ + metricsUrl: string; + /** The URL of the atlas's image, generated together with the metrics. */ + imageUrl: string; +} + +interface FontAtlasLoad { + readonly imageUrl: string; + readonly promise: Promise; +} + +/** + * Loads and caches `FontAtlas`es from a metrics JSON file and its atlas + * image, keyed by the metrics file's URL. + */ +export class FontAtlasCache { private readonly _imageCache: ImageCache; + private readonly _loads = new Map(); + private readonly _fontAtlases = new Map(); constructor(imageCache: ImageCache = new ImageCache()) { this._imageCache = imageCache; } /** - * Retrieves a font atlas from the cache. - * @param key - The path of the font atlas's JSON file. + * Retrieves a loaded font atlas from the cache. + * @param metricsUrl - The URL of the font atlas's metrics JSON file. * @returns The cached font atlas. - * @throws Will throw an error if the font atlas is not found in the cache. + * @throws Will throw an error if the font atlas hasn't finished loading. */ - public get(key: string): FontAtlas { - const fontAtlas = this.assets.get(key); + public get(metricsUrl: string): FontAtlas { + const fontAtlas = this._fontAtlases.get(metricsUrl); if (!fontAtlas) { - throw new Error(`Font atlas with key "${key}" not found in store.`); + throw new Error( + `Font atlas with metrics URL "${metricsUrl}" not found in store.`, + ); } return fontAtlas; } /** - * Loads a font atlas's JSON metrics and image from the specified key and - * caches it. - * @param key - The path of the font atlas's JSON file. - * @returns A promise that resolves when the font atlas is loaded and cached. - * @throws Will throw an error if the JSON fails to fetch, is malformed, or - * is an unsupported/incompatible atlas format. + * Retrieves a font atlas from the cache, loading it the first time it's + * requested. Concurrent calls for the same atlas share one load. + * @param urls - The URLs of the atlas's metrics JSON file and image. + * @returns A promise that resolves to the font atlas. + * @throws Will throw an error if `urls.metricsUrl` was already requested + * with a different image URL, if the JSON fails to fetch, is malformed or + * is an unsupported atlas format, if the image fails to load, or if the + * image's size doesn't match the metrics' `atlasSize`. */ - public async load(key: string): Promise { - const response = await fetch(key); + public async getOrLoad(urls: FontAtlasUrls): Promise { + const { metricsUrl, imageUrl } = urls; + const existingLoad = this._loads.get(metricsUrl); - if (!response.ok) { - throw new Error( - `Failed to load font atlas JSON at "${key}": ${response.status} ${response.statusText}`, - ); + if (existingLoad) { + if (existingLoad.imageUrl !== imageUrl) { + throw new Error( + `Font atlas "${metricsUrl}" was already requested with image "${existingLoad.imageUrl}", so it can't also be loaded with image "${imageUrl}".`, + ); + } + + return existingLoad.promise; } - const rawJson: unknown = await response.json(); - const fileData = validateFontAtlasFileData(rawJson, key); - const data = toFontAtlasData(fileData); - const imagePath = resolveRelativeToKey(key, data.atlasImage); - const image = await this._imageCache.getOrLoad(imagePath); + const promise = this._load(metricsUrl, imageUrl); + + this._loads.set(metricsUrl, { imageUrl, promise }); + + try { + return await promise; + } catch (error) { + if (this._loads.get(metricsUrl)?.promise === promise) { + this._loads.delete(metricsUrl); + } - this.assets.set(key, { data, image }); + throw error; + } } - /** - * Retrieves a font atlas from the cache if it exists, otherwise loads and - * caches it. - * @param key - The key of the font atlas to retrieve or load. - * @returns A promise that resolves to the font atlas. - */ - public async getOrLoad(key: string): Promise { - if (!this.assets.has(key)) { - await this.load(key); + private async _load( + metricsUrl: string, + imageUrl: string, + ): Promise { + const [data, image] = await Promise.all([ + loadFontAtlasData(metricsUrl), + this._imageCache.getOrLoad(imageUrl), + ]); + + const { width, height } = data.atlasSize; + + if (image.naturalWidth !== width || image.naturalHeight !== height) { + throw new Error( + `Font atlas image "${imageUrl}" is ${image.naturalWidth}x${image.naturalHeight}, but the metrics at "${metricsUrl}" expect ${width}x${height}. Check that both files come from the same generated atlas.`, + ); } - return this.get(key); + const fontAtlas: FontAtlas = { data, image }; + + this._fontAtlases.set(metricsUrl, fontAtlas); + + return fontAtlas; } } /** - * Resolves `relativePath` against the directory `key` sits in, the same way - * `FontAtlasData.atlasImage` is documented as being relative to its own - * JSON file. + * Fetches, validates and converts the metrics JSON at `metricsUrl`. */ -function resolveRelativeToKey(key: string, relativePath: string): string { - const lastSlashIndex = key.lastIndexOf('/'); - const directory = - lastSlashIndex === -1 ? '' : key.slice(0, lastSlashIndex + 1); +async function loadFontAtlasData(metricsUrl: string): Promise { + const response = await fetch(metricsUrl); + + if (!response.ok) { + throw new Error( + `Failed to load font atlas JSON at "${metricsUrl}": ${response.status} ${response.statusText}`, + ); + } + + const rawJson: unknown = await response.json(); - return `${directory}${relativePath}`; + return toFontAtlasData(validateFontAtlasFileData(rawJson, metricsUrl)); } diff --git a/src/text/font-atlas/font-atlas-data.ts b/src/text/font-atlas/font-atlas-data.ts index fd9a606a8..8bb67d62e 100644 --- a/src/text/font-atlas/font-atlas-data.ts +++ b/src/text/font-atlas/font-atlas-data.ts @@ -90,9 +90,6 @@ export interface FontAtlasData { /** `'msdf'` for v1; reserved for `'mtsdf'` later. */ type: 'msdf'; - /** Atlas texture path, relative to this atlas's JSON file. */ - atlasImage: string; - /** Atlas texture pixel dimensions. */ atlasSize: AtlasSize; diff --git a/src/text/font-atlas/font-atlas-file-data.test.ts b/src/text/font-atlas/font-atlas-file-data.test.ts index 4ea3a74bd..8718feb70 100644 --- a/src/text/font-atlas/font-atlas-file-data.test.ts +++ b/src/text/font-atlas/font-atlas-file-data.test.ts @@ -11,7 +11,6 @@ import { const buildFileData = (): FontAtlasFileData => ({ formatVersion: CURRENT_FONT_ATLAS_FORMAT_VERSION, type: 'msdf', - atlasImage: 'my-font.png', atlasSize: { width: 512, height: 512 }, distanceRange: 4, metrics: { lineHeight: 1.2, ascender: 0.9, descender: -0.2, capHeight: 0.7 }, @@ -40,7 +39,6 @@ describe('toFontAtlasData', () => { expect(result.formatVersion).toBe(CURRENT_FONT_ATLAS_FORMAT_VERSION); expect(result.type).toBe('msdf'); - expect(result.atlasImage).toBe('my-font.png'); expect(result.atlasSize).toEqual({ width: 512, height: 512 }); expect(result.distanceRange).toBe(4); expect(result.metrics).toEqual({ diff --git a/src/text/font-atlas/font-atlas-file-data.ts b/src/text/font-atlas/font-atlas-file-data.ts index e61f21b06..4da631420 100644 --- a/src/text/font-atlas/font-atlas-file-data.ts +++ b/src/text/font-atlas/font-atlas-file-data.ts @@ -7,8 +7,8 @@ import { } from './font-atlas-data.js'; /** - * The on-disk, JSON-serializable shape of a committed font atlas asset - * (`.json`, sitting alongside `.png`). This is the same data as + * The on-disk, JSON-serializable shape of a font atlas's metrics file + * (`.json`, generated together with its `.png` image). This is the same data as * `FontAtlasData`, except `glyphs`/`kerning` use JSON-safe arrays/records * instead of `Map`s. `toFontAtlasData` converts one into the other. */ @@ -19,9 +19,6 @@ export interface FontAtlasFileData { /** `'msdf'` for v1; reserved for `'mtsdf'` later. */ type: 'msdf'; - /** Atlas texture path, relative to this JSON file. */ - atlasImage: string; - /** Atlas texture pixel dimensions. */ atlasSize: AtlasSize; @@ -48,7 +45,6 @@ export function toFontAtlasData(fileData: FontAtlasFileData): FontAtlasData { return { formatVersion: fileData.formatVersion, type: fileData.type, - atlasImage: fileData.atlasImage, atlasSize: fileData.atlasSize, distanceRange: fileData.distanceRange, metrics: fileData.metrics, diff --git a/src/text/font-atlas/validate-font-atlas-data.test.ts b/src/text/font-atlas/validate-font-atlas-data.test.ts index 1830592a9..66220976f 100644 --- a/src/text/font-atlas/validate-font-atlas-data.test.ts +++ b/src/text/font-atlas/validate-font-atlas-data.test.ts @@ -9,7 +9,6 @@ import { validateFontAtlasFileData } from './validate-font-atlas-data.js'; const buildValidJson = (): FontAtlasFileData => ({ formatVersion: CURRENT_FONT_ATLAS_FORMAT_VERSION, type: 'msdf', - atlasImage: 'my-font.png', atlasSize: { width: 512, height: 512 }, distanceRange: 4, metrics: { lineHeight: 1.2, ascender: 0.9, descender: -0.2, capHeight: 0.7 }, @@ -64,12 +63,10 @@ describe('validateFontAtlasFileData', () => { ); }); - it('should throw when atlasImage is missing or empty', () => { - const json = { ...buildValidJson(), atlasImage: '' }; + it('should accept a file that still names its atlas image', () => { + const json = { ...buildValidJson(), atlasImage: 'my-font.png' }; - expect(() => validateFontAtlasFileData(json, 'fixture.json')).toThrow( - /atlasImage must be a non-empty string/, - ); + expect(validateFontAtlasFileData(json, 'fixture.json')).toBe(json); }); it('should throw when atlasSize is non-positive', () => { diff --git a/src/text/font-atlas/validate-font-atlas-data.ts b/src/text/font-atlas/validate-font-atlas-data.ts index 58890766f..934af52b4 100644 --- a/src/text/font-atlas/validate-font-atlas-data.ts +++ b/src/text/font-atlas/validate-font-atlas-data.ts @@ -43,10 +43,6 @@ export function validateFontAtlasFileData( fail(`unsupported type "${String(data.type)}", expected "msdf".`); } - if (typeof data.atlasImage !== 'string' || data.atlasImage.length === 0) { - fail('atlasImage must be a non-empty string.'); - } - validateAtlasSize(data.atlasSize, fail); validateDistanceRange(data.distanceRange, fail); validateMetrics(data.metrics, fail); diff --git a/src/text/rendering/create-text-renderable.test.ts b/src/text/rendering/create-text-renderable.test.ts index 93eacc10a..a745f2a08 100644 --- a/src/text/rendering/create-text-renderable.test.ts +++ b/src/text/rendering/create-text-renderable.test.ts @@ -41,7 +41,6 @@ describe('createTextRenderable', () => { data: { formatVersion: 2, type: 'msdf', - atlasImage: 'fixture.png', atlasSize: { width: 512, height: 512 }, distanceRange: 4, metrics: { diff --git a/src/text/systems/text-shaping-system.test.ts b/src/text/systems/text-shaping-system.test.ts index 7da10fc85..54d686b8d 100644 --- a/src/text/systems/text-shaping-system.test.ts +++ b/src/text/systems/text-shaping-system.test.ts @@ -30,7 +30,6 @@ function buildFontAtlas(): FontAtlas { data: { formatVersion: 2, type: 'msdf', - atlasImage: 'fixture.png', atlasSize: { width: 256, height: 256 }, distanceRange: 4, metrics: { diff --git a/src/text/utilities/shape-text.test.ts b/src/text/utilities/shape-text.test.ts index 7d71db149..475167cc7 100644 --- a/src/text/utilities/shape-text.test.ts +++ b/src/text/utilities/shape-text.test.ts @@ -11,7 +11,6 @@ function buildFixtureFontAtlasData(): FontAtlasData { return { formatVersion: 2, type: 'msdf', - atlasImage: 'fixture.png', atlasSize: { width: 256, height: 256 }, distanceRange: 4, // `capHeight: 0.7` intentionally matches "A"/"V"'s own `planeBounds.top`