@solidrt/flux-types 0.0.69 → 0.0.70

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
@@ -51,7 +51,7 @@ rely on must be named.
51
51
  `flux:camera`, `flux:microphone`, `flux:audio`, `flux:gpu`, `flux:spatial`,
52
52
  `flux:font`.
53
53
  - Web-standard globals: `console`, `fetch` + `Headers`/`Request`/`Response`,
54
- `setTimeout`/`setInterval`/`queueMicrotask`, `performance`, `WebSocket`,
54
+ `setTimeout`/`setInterval`/`setImmediate`/`requestIdleCallback`/`queueMicrotask`, `performance`, `WebSocket`,
55
55
  `TextEncoder`/`TextDecoder`, `crypto.subtle.digest`. These are deliberate subsets matching exactly what
56
56
  the runtime implements.
57
57
  - GUI globals (gui-enabled runtime only): `requestAnimationFrame` /
package/gui/font.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  declare module "flux:font" {
16
16
  import type { TextureId } from "flux:gpu"
17
- import type { PreparedText } from "flux:rendertree"
17
+ import type { TextUnit } from "flux:rendertree"
18
18
 
19
19
  /** A created font, valid until {@link destroyFont}. */
20
20
  type FontId = number
@@ -34,6 +34,8 @@ declare module "flux:font" {
34
34
  fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
35
35
  /** Width as a percentage of normal (CSS font-stretch), on the font's width axis; default 100. */
36
36
  fontStretch?: number
37
+ /** Extra advance after every character in pixels (CSS letter-spacing), what {@link prepareText} shapes with by default; default 0. */
38
+ letterSpacing?: number
37
39
  /** Line height as a multiplier of the size, 0 for the font's own line. */
38
40
  lineHeight?: number
39
41
  }
@@ -54,6 +56,14 @@ declare module "flux:font" {
54
56
  range?: number
55
57
  /** Keep a mip chain on the atlas texture: default true for msdf (sampled at every zoom), false for mask. */
56
58
  mipmap?: boolean
59
+ /**
60
+ * mask only: how the cells are hinted. "light" snaps baseline, x-height
61
+ * and cap height to pixel rows (`true` means the same); "full" snaps
62
+ * stems to whole pixels as well, which a grid of cells drawn at whole
63
+ * pixels (a terminal) wants; false (default) keeps the outline as the
64
+ * font draws it. An msdf atlas is never hinted.
65
+ */
66
+ hint?: boolean | "light" | "full"
57
67
  /** Debug label of the atlas texture. */
58
68
  label?: string
59
69
  }
@@ -71,6 +81,8 @@ declare module "flux:font" {
71
81
  fontSize: number
72
82
  /** msdf: the distance range in texels; 0 for a mask atlas. */
73
83
  range: number
84
+ /** How the cells are hinted; "off" for an msdf atlas. */
85
+ hint: "off" | "light" | "full"
74
86
  }
75
87
 
76
88
  /**
@@ -97,10 +109,29 @@ declare module "flux:font" {
97
109
  fontSize?: number
98
110
  /** Line height multiplier; default the face's. */
99
111
  lineHeight?: number
112
+ /** Extra advance after every character in pixels, at `fontSize`; default the face's. */
113
+ letterSpacing?: number
100
114
  /** Also report each unit's caret stops (one pass over the cluster map). */
101
115
  carets?: boolean
102
116
  }
103
117
 
118
+ /**
119
+ * A wrap unit shaped on a font: `flux:rendertree`'s unit plus the unit's
120
+ * glyphs - the font's glyph `id` (a cell of this font's atlas), the glyph
121
+ * origin `x`/`y` from the unit's pen position (kerned, letter-spaced, y
122
+ * down) and the pen `advance` it contributes - all in pixels at the
123
+ * shaping size.
124
+ */
125
+ type FontTextUnit = TextUnit & {
126
+ glyphs: { id: number, x: number, y: number, advance: number }[]
127
+ }
128
+
129
+ /** A text shaped on a font: `flux:rendertree`'s `PreparedText` with every unit carrying its glyphs. */
130
+ type FontPreparedText = {
131
+ text: string
132
+ units: FontTextUnit[]
133
+ }
134
+
104
135
  /**
105
136
  * Create a font: one face with an empty atlas. Throws on an unknown cells
106
137
  * kind or a non-positive size. The atlas texture exists from here, so a
@@ -112,17 +143,16 @@ declare module "flux:font" {
112
143
  /** The font's atlas as it is now. */
113
144
  function fontAtlas(font: FontId): FontAtlas
114
145
  /**
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.
146
+ * Shape `text` on the font (the runtime's own shaper): the units of
147
+ * `flux:rendertree`'s prepareText, each also carrying its glyphs, for
148
+ * app-side line breaking with `layoutNextLine` and glyph placement.
119
149
  * The font is one face and its atlas holds that face's cells only, so a
120
150
  * character the face lacks shapes to its missing glyph (id 0) with no
121
151
  * fallback to another font, where a `<text>` would borrow the glyph;
122
152
  * whitespace and control characters the face lacks take the space's
123
153
  * advance.
124
154
  */
125
- function prepareText(font: FontId, text: string, options?: FontPrepareOptions): PreparedText
155
+ function prepareText(font: FontId, text: string, options?: FontPrepareOptions): FontPreparedText
126
156
  /**
127
157
  * Make the cells of `glyphs` (ids from prepared units) that the atlas
128
158
  * does not hold yet, on the worker thread. Resolves once every glyph is
@@ -79,13 +79,6 @@ declare module "flux:rendertree" {
79
79
  * no neighbors and drifts on every kerning pair.
80
80
  */
81
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 }[]
89
82
  }
90
83
 
91
84
  /** The wrap units of a text in one font, shaped once. Plain data; layout is arithmetic over `units`. */
@@ -228,6 +221,61 @@ declare module "flux:rendertree" {
228
221
  * made at first use.
229
222
  */
230
223
  export function warmText(styles: MeasureTextOptions[]): void
224
+ /** How every text is rendered, for {@link setTextRendering}. */
225
+ export interface TextRenderingOptions {
226
+ /**
227
+ * How a glyph's coverage becomes color: "naive" takes it as is;
228
+ * "linearLight", "polarityRemap" and "polarityLinear" remap it by
229
+ * `gamma` for light text on a dark ground; "directWrite" applies
230
+ * DirectWrite's contrast boost (`contrast`) and gamma alpha correction
231
+ * (`gamma`, 1.0 to 2.2).
232
+ */
233
+ coverage?: "naive" | "linearLight" | "polarityRemap" | "polarityLinear" | "directWrite"
234
+ /** The exponent of the remaps, or the DirectWrite gamma; positive. */
235
+ gamma?: number
236
+ /** The DirectWrite mode's enhanced contrast; positive, 1 is its default. */
237
+ contrast?: number
238
+ /**
239
+ * Stem darkening of every glyph in em per side, at any display scale;
240
+ * null restores the default (a low-DPI strength below 2x, none above).
241
+ */
242
+ darken?: number | null
243
+ /**
244
+ * How glyph cells are hinted, at any display scale: "light" (the
245
+ * autohinter's light mode: baseline, x-height and cap height snap to
246
+ * pixel rows, stems and advances untouched; `true` means the same),
247
+ * "full" (stems snap to whole pixels as well, letterforms rounded per
248
+ * size: a 1x screen read from a distance) or `false` (the outline as
249
+ * the font draws it). null restores the default: light below 2x,
250
+ * off above.
251
+ */
252
+ hint?: boolean | "light" | "full" | null
253
+ }
254
+ /**
255
+ * Change how every text is rendered. Each option given replaces its part
256
+ * of the current policy and the rest stays; every text redraws at the
257
+ * next frame. The defaults are what an app that says nothing gets; this
258
+ * is the knob for judging a policy by eye on a running app. Throws on an
259
+ * unknown mode or an invalid number.
260
+ */
261
+ export function setTextRendering(options: TextRenderingOptions): void
262
+ /** The text rendering policy as it stands, resolved for this display: what {@link textRendering} returns. */
263
+ export interface TextRenderingPolicy {
264
+ coverage: "naive" | "linearLight" | "polarityRemap" | "polarityLinear" | "directWrite"
265
+ gamma: number
266
+ contrast: number
267
+ /** The stem darkening in effect on this display, em per side. */
268
+ darken: number
269
+ /** The hinting in effect on this display. */
270
+ hint: false | "light" | "full"
271
+ }
272
+ /**
273
+ * The current text rendering policy, resolved for this display: a
274
+ * `darken` or `hint` left at its default reads as the value the display
275
+ * scale gives it, so a settings screen shows what is in effect, and
276
+ * setting the result back changes nothing on this display.
277
+ */
278
+ export function textRendering(): TextRenderingPolicy
231
279
  /**
232
280
  * The node's bounding box from the most recent layout, relative to its
233
281
  * nearest positioning context (an ancestor with an explicit
@@ -107,6 +107,13 @@ declare module "flux:isolate" {
107
107
  * already-aborted signal rejects without sending anything (or starting the
108
108
  * child).
109
109
  *
110
+ * A child that cannot start (an id no module resolves to or a malformed
111
+ * one, a module that does not decode, a runtime that cannot spawn
112
+ * isolates) never throws from the call expression: the first use rejects
113
+ * with the failure as an `Error`, a `for await` over it throws that error
114
+ * on its first step, and `exited` settles with the message. Nothing is
115
+ * remembered, so a later use tries again.
116
+ *
110
117
  * Reserved names: `terminate`, `exited`, `then`.
111
118
  */
112
119
  export function isolate<T = Record<string, (...args: any[]) => any>>(id: string, opts?: IsolateOptions): Isolated<T>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/flux-types",
3
- "version": "0.0.69",
3
+ "version": "0.0.70",
4
4
  "license": "MIT",
5
5
  "funding": "https://github.com/sponsors/wellawaretech",
6
6
  "author": "Antoine van Wel",
@@ -1,5 +1,13 @@
1
- // Timers, microtask scheduling, and the monotonic clock. flux's timers differ
2
- // from the browser in one way: no extra callback arguments are forwarded.
1
+ // Timers, task scheduling, idle callbacks, microtask scheduling, and the
2
+ // monotonic clock. flux's timers differ from the browser in one way: no
3
+ // extra callback arguments are forwarded.
4
+ //
5
+ // Two kinds of scheduling. What names a point in time (setTimeout,
6
+ // setInterval, requestAnimationFrame) runs on the app's frame clock, as
7
+ // described next. What names a turn (queueMicrotask, setImmediate) runs on
8
+ // the engine loop whenever it is ready: between frames in a GUI runtime,
9
+ // never waiting for one, and not held by a paused clock. requestIdleCallback
10
+ // sits on the frame side: its idle period is what is left of a frame.
3
11
  //
4
12
  // In a GUI runtime the timers are FRAME-QUANTIZED but WALL-ACCURATE: a
5
13
  // deadline is measured against the real clock from the moment of
@@ -31,6 +39,50 @@ declare function clearTimeout(id?: number): void
31
39
  declare function setInterval(callback: () => void, ms?: number): number
32
40
  /** Cancel a running interval. Unknown or missing ids are ignored. */
33
41
  declare function clearInterval(id?: number): void
42
+ /**
43
+ * Run `callback` on the next turn of the engine loop: after the current
44
+ * task and its microtasks, with no delay floor. Not a timer: in a GUI
45
+ * runtime it runs between frames (a chain of immediates makes progress at
46
+ * CPU speed while frames keep coming) and a paused clock does not hold it;
47
+ * it always runs before a `setTimeout(fn, 0)` registered with it there.
48
+ * Returns an id for {@link clearImmediate}.
49
+ */
50
+ declare function setImmediate(callback: () => void): number
51
+ /** Cancel a pending immediate. Unknown or missing ids are ignored. */
52
+ declare function clearImmediate(id?: number): void
53
+
54
+ /** What an idle callback is handed: how much of the idle period is left. */
55
+ interface IdleDeadline {
56
+ /** Milliseconds left in the idle period; 0 once it has passed. */
57
+ timeRemaining(): number
58
+ /** Whether the `timeout` ran the callback instead of an idle period. */
59
+ readonly didTimeout: boolean
60
+ }
61
+
62
+ interface IdleRequestOptions {
63
+ /**
64
+ * If no idle period has run the callback after this many ms, run it as
65
+ * a task anyway, with `didTimeout` true and no time remaining. That
66
+ * task is a timer, so in a GUI runtime it fires on a frame boundary,
67
+ * like `setTimeout`.
68
+ */
69
+ timeout?: number
70
+ }
71
+
72
+ /**
73
+ * Run `callback` in an idle period, oldest registration first, with an
74
+ * {@link IdleDeadline}. In a GUI runtime an idle period is what is left of a
75
+ * frame after its work: it begins once the frame's callbacks, flush and
76
+ * draw are done and its microtasks have run, and ends when the frame is
77
+ * due on screen, at most 50 ms later. Callbacks that do not fit wait for
78
+ * the next frame's period, and one registered during a period waits for
79
+ * the next. A paused clock holds the frames and with them the idle
80
+ * periods. Headless flux has no frames: the callback runs on the next
81
+ * turn with the full 50 ms. Returns an id for {@link cancelIdleCallback}.
82
+ */
83
+ declare function requestIdleCallback(callback: (deadline: IdleDeadline) => void, options?: IdleRequestOptions): number
84
+ /** Cancel a pending idle callback. Unknown or missing ids are ignored. */
85
+ declare function cancelIdleCallback(id?: number): void
34
86
  /**
35
87
  * Queue `callback` to run as a microtask: after the current job finishes, before
36
88
  * any timer fires.