@solidrt/flux-types 0.0.67 → 0.0.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,8 @@ rely on must be named.
48
48
  - `flux:*` modules: `flux:http`, `flux:fs`, `flux:sqlite`, `flux:subprocess`,
49
49
  `flux:p2p`, `flux:net`, `flux:mdns`, `flux:process`, `flux:tty`, `flux:path`, `flux:wasm`,
50
50
  and (on a gui-enabled runtime)
51
- `flux:camera`, `flux:microphone`, `flux:audio`, `flux:gpu`, `flux:spatial`.
51
+ `flux:camera`, `flux:microphone`, `flux:audio`, `flux:gpu`, `flux:spatial`,
52
+ `flux:font`.
52
53
  - Web-standard globals: `console`, `fetch` + `Headers`/`Request`/`Response`,
53
54
  `setTimeout`/`setInterval`/`queueMicrotask`, `performance`, `WebSocket`,
54
55
  `TextEncoder`/`TextDecoder`, `crypto.subtle.digest`. These are deliberate subsets matching exactly what
package/gui/font.d.ts ADDED
@@ -0,0 +1,137 @@
1
+ // The glyph engine (gui-enabled runtime only): a registered font shaped on
2
+ // the runtime's own shaper, its glyphs rasterized into an atlas texture a
3
+ // consumer samples itself - the sprite layer's world-space text, a terminal
4
+ // grid, anything that draws glyph quads. `<text>` does not draw through
5
+ // this; it is the primitive beneath that for text the tree cannot carry.
6
+ //
7
+ // A font handle is one face (family, weight, style) with one atlas of one
8
+ // cell kind. Prepare text over it to get units whose glyphs are named and
9
+ // placed, ask for the cells of the glyphs you draw, then draw each glyph as
10
+ // a quad at its placement sampling the atlas rect. Cells are made on a
11
+ // worker thread and land at a later frame: draw a glyph whose cell has not
12
+ // arrived as nothing at its advance, and re-read the cells when the promise
13
+ // resolves.
14
+
15
+ declare module "flux:font" {
16
+ import type { TextureId } from "flux:gpu"
17
+ import type { PreparedText } from "flux:rendertree"
18
+
19
+ /** A created font, valid until {@link destroyFont}. */
20
+ type FontId = number
21
+
22
+ /**
23
+ * The face a font shapes and rasterizes with: the same vocabulary as a
24
+ * `<text>`'s font props, resolved the same way (a role alias such as
25
+ * "sans", "serif" or "mono", or a registered family name; an unknown
26
+ * family falls back to sans). `fontSize` is the size a "mask" atlas is
27
+ * made at and the default size {@link prepareText} shapes at; an "msdf"
28
+ * atlas is size-independent.
29
+ */
30
+ type FontFace = {
31
+ fontFamily?: "sans" | "serif" | "mono" | (string & {})
32
+ fontSize?: number
33
+ fontStyle?: "normal" | "italic"
34
+ fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
35
+ /** Width as a percentage of normal (CSS font-stretch), on the font's width axis; default 100. */
36
+ fontStretch?: number
37
+ /** Line height as a multiplier of the size, 0 for the font's own line. */
38
+ lineHeight?: number
39
+ }
40
+
41
+ /** Options for {@link createFont}. */
42
+ type FontAtlasOptions = {
43
+ /**
44
+ * What the atlas holds. "msdf" (default): multi-channel signed distance
45
+ * fields at `size` texels per em, one cell for every zoom; the consumer
46
+ * decodes the field in its shader (the sprite layer's text does).
47
+ * "mask": coverage masks at the face's pixel size, premultiplied white,
48
+ * drawn 1:1 as a plain texture - a terminal, a HUD at a fixed size.
49
+ */
50
+ cells?: "mask" | "msdf"
51
+ /** Texels per em of the cells: the face's `fontSize` for a mask atlas, 48 for an msdf one. */
52
+ size?: number
53
+ /** msdf only: the distance range in texels (default 8), the room an outline has. */
54
+ range?: number
55
+ /** Keep a mip chain on the atlas texture: default true for msdf (sampled at every zoom), false for mask. */
56
+ mipmap?: boolean
57
+ /** Debug label of the atlas texture. */
58
+ label?: string
59
+ }
60
+
61
+ /** The atlas of a font: its texture, its current size and what its cells are. */
62
+ type FontAtlas = {
63
+ texture: TextureId
64
+ /** Current size in texels. The atlas grows as glyphs arrive; a change of size means EVERY cell moved, so re-read placements with {@link glyphCells}. */
65
+ width: number
66
+ height: number
67
+ cells: "mask" | "msdf"
68
+ /** Texels per em the cells were made at. */
69
+ size: number
70
+ /** The face's size: what {@link prepareText} shapes at by default (the runtime's text default when the face named none). */
71
+ fontSize: number
72
+ /** msdf: the distance range in texels; 0 for a mask atlas. */
73
+ range: number
74
+ }
75
+
76
+ /**
77
+ * Where a glyph's cell sits in the atlas (`x`, `y`, `width`, `height`,
78
+ * texels) and how the cell sits on the glyph: `left` texels right of the
79
+ * glyph origin, `top` texels above the baseline. To draw a glyph placed
80
+ * at pen (px, py) in a text prepared at `fontSize`, scale by
81
+ * `fontSize / atlas.size` and put the cell's top-left at
82
+ * `(px + left * s, py + ascent - top * s)`.
83
+ */
84
+ type GlyphCell = {
85
+ glyph: number
86
+ x: number
87
+ y: number
88
+ width: number
89
+ height: number
90
+ left: number
91
+ top: number
92
+ }
93
+
94
+ /** Options for {@link prepareText} over a font. */
95
+ type FontPrepareOptions = {
96
+ /** Pixels per em to shape at; default the face's `fontSize`. */
97
+ fontSize?: number
98
+ /** Line height multiplier; default the face's. */
99
+ lineHeight?: number
100
+ /** Also report each unit's caret stops (one pass over the cluster map). */
101
+ carets?: boolean
102
+ }
103
+
104
+ /**
105
+ * Create a font: one face with an empty atlas. Throws on an unknown cells
106
+ * kind or a non-positive size. The atlas texture exists from here, so a
107
+ * layer can declare it at creation and draw from it as cells arrive.
108
+ */
109
+ function createFont(face?: FontFace, options?: FontAtlasOptions): FontId
110
+ /** Free the font and its atlas texture. Requests still pending on it reject. */
111
+ function destroyFont(font: FontId): void
112
+ /** The font's atlas as it is now. */
113
+ function fontAtlas(font: FontId): FontAtlas
114
+ /**
115
+ * Shape `text` on the font (the runtime's own shaper): the same
116
+ * `PreparedText` as `flux:rendertree`'s, every unit also carrying its
117
+ * `glyphs` - ids and pen positions, kerned, in pixels at `fontSize` -
118
+ * for app-side line breaking with `layoutNextLine` and glyph placement.
119
+ * The font is one face and its atlas holds that face's cells only, so a
120
+ * character the face lacks shapes to its missing glyph (id 0) with no
121
+ * fallback to another font, where a `<text>` would borrow the glyph;
122
+ * whitespace and control characters the face lacks take the space's
123
+ * advance.
124
+ */
125
+ function prepareText(font: FontId, text: string, options?: FontPrepareOptions): PreparedText
126
+ /**
127
+ * Make the cells of `glyphs` (ids from prepared units) that the atlas
128
+ * does not hold yet, on the worker thread. Resolves once every glyph is
129
+ * placed or has failed (a glyph the font cannot rasterize, or an atlas
130
+ * at the device's texture size cap), with one {@link GlyphCell} per
131
+ * requested glyph, null for a failed one. Work in flight: `settle`
132
+ * waits for it. Rejects if the font is destroyed first.
133
+ */
134
+ function requestGlyphs(font: FontId, glyphs: number[]): Promise<(GlyphCell | null)[]>
135
+ /** The cells of `glyphs` as the atlas holds them now, null for a glyph not (yet) in it. */
136
+ function glyphCells(font: FontId, glyphs: number[]): (GlyphCell | null)[]
137
+ }
package/gui/gpu.d.ts CHANGED
@@ -358,13 +358,20 @@ declare module "flux:gpu" {
358
358
  * for byte formats, Float32Array for float formats).
359
359
  */
360
360
  export function createMutableTexture(data: Uint8Array | Float32Array | Uint32Array, width: number, height: number, opts?: SamplerOptions & TextureFormatOption & LabelOption): TextureId
361
+ /** A rect of a texture, in texels from its top-left: the third argument of {@link uploadTexture}. */
362
+ export type TextureRect = { x: number, y: number, width: number, height: number }
361
363
  /**
362
364
  * Replace a mutable texture's pixels; the frame size and required view
363
365
  * type (Uint8Array for byte formats, Float32Array for float formats)
364
366
  * follow the format the id was created with. `data` may hold several
365
- * frames; `offset` (default 0) selects which frame to upload.
367
+ * frames; a numeric `at` (default 0) selects which frame to upload. A
368
+ * rect `at` uploads `data` as exactly that rect of the texture instead -
369
+ * `data` then holds `width * height` pixels - and the rect must lie
370
+ * inside the texture (GL's texSubImage2D with an offset): how a runtime
371
+ * atlas writes one cell without re-sending the sheet. A mip chain
372
+ * regenerates after either form.
366
373
  */
367
- export function uploadTexture(id: TextureId, data: Uint8Array | Float32Array | Uint32Array, offset?: number): void
374
+ export function uploadTexture(id: TextureId, data: Uint8Array | Float32Array | Uint32Array, at?: number | TextureRect): void
368
375
  /**
369
376
  * Replace a texture's storage with a new size at the same id (an id-stable
370
377
  * resize): `<texture src>` references and shader sampler bindings keep
@@ -12,6 +12,10 @@ declare module "flux:rendertree" {
12
12
  fontSize?: number
13
13
  fontStyle?: "normal" | "italic"
14
14
  fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
15
+ /** Width as a percentage of normal (CSS font-stretch), on the font's width axis; default 100. */
16
+ fontStretch?: number
17
+ /** Extra advance after every character in pixels (CSS letter-spacing); default 0. */
18
+ letterSpacing?: number
15
19
  lineHeight?: number
16
20
  /** measureText only. */
17
21
  maxLines?: number
@@ -35,6 +39,8 @@ declare module "flux:rendertree" {
35
39
  fontSize?: number
36
40
  fontStyle?: "normal" | "italic"
37
41
  fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
42
+ fontStretch?: number
43
+ letterSpacing?: number
38
44
  lineHeight?: number
39
45
  }
40
46
 
@@ -66,12 +72,20 @@ declare module "flux:rendertree" {
66
72
  * cluster boundary from its start (`offset` = start, x 0) to the end of
67
73
  * its shaped text (before any break characters), in order. `offset` is
68
74
  * into the prepared text, `x` from the unit's pen position. These are
69
- * the per-glyph x positions of the shaping that is drawn, kerning
70
- * included: for placing or animating single glyphs, use them rather
75
+ * the runtime's own shaper's glyph positions for the unit, kerning
76
+ * included, within a texel of what is drawn and ending on the unit's
77
+ * drawn advance: for placing or animating single glyphs, use them rather
71
78
  * than measuring characters one at a time with measureText, which sees
72
79
  * no neighbors and drifts on every kerning pair.
73
80
  */
74
81
  carets?: { offset: number, x: number }[]
82
+ /**
83
+ * The unit's glyphs, from `flux:font`'s prepareText only (its ids name
84
+ * cells of that font's atlas): the font's glyph `id`, the glyph origin
85
+ * `x`/`y` from the unit's pen position (kerned, y down) and the pen
86
+ * `advance` it contributes.
87
+ */
88
+ glyphs?: { id: number, x: number, y: number, advance: number }[]
75
89
  }
76
90
 
77
91
  /** The wrap units of a text in one font, shaped once. Plain data; layout is arithmetic over `units`. */
@@ -200,10 +214,20 @@ declare module "flux:rendertree" {
200
214
  * the shared word cache, so a text already drawn or prepared costs no
201
215
  * shaping), for app-side line breaking - text into a shape, around an
202
216
  * obstacle, across columns, fitted by size, per glyph; see layoutNextLine
203
- * in @solidrt/core. `runs` restyle ranges, `carets` adds glyph positions;
217
+ * in @solidrt/core. `runs` restyle ranges, `carets` adds caret stops;
204
218
  * `maxLines` is ignored.
205
219
  */
206
220
  export function prepareText(text: string, options?: MeasureTextOptions): PreparedText
221
+ /**
222
+ * Make the glyph cells of printable ASCII for these font styles ahead of
223
+ * their first use, on the engine's worker thread: the type scale an app
224
+ * draws its screens in, called at startup under the splash, so a first
225
+ * paint in any of them never waits for cells. Each entry names a font
226
+ * (family, size, weight, style) as a `<text>` would; `lineHeight`,
227
+ * `maxLines`, `carets` and `runs` are ignored. Glyphs outside ASCII are
228
+ * made at first use.
229
+ */
230
+ export function warmText(styles: MeasureTextOptions[]): void
207
231
  /**
208
232
  * The node's bounding box from the most recent layout, relative to its
209
233
  * nearest positioning context (an ancestor with an explicit
package/index.d.ts CHANGED
@@ -38,6 +38,7 @@
38
38
  /// <reference path="./gui/audio.d.ts" />
39
39
  /// <reference path="./gui/gpu.d.ts" />
40
40
  /// <reference path="./gui/spatial.d.ts" />
41
+ /// <reference path="./gui/font.d.ts" />
41
42
  /// <reference path="./gui/video.d.ts" />
42
43
  /// <reference path="./gui/raf.d.ts" />
43
44
  /// <reference path="./gui/test.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/flux-types",
3
- "version": "0.0.67",
3
+ "version": "0.0.68",
4
4
  "license": "MIT",
5
5
  "funding": "https://github.com/sponsors/wellawaretech",
6
6
  "author": "Antoine van Wel",