spryte 0.0.0-stage → 0.1.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -2
  3. package/dist/backend.d.ts +69 -0
  4. package/dist/backend.d.ts.map +1 -0
  5. package/dist/backend.js +2 -0
  6. package/dist/backend.js.map +1 -0
  7. package/dist/bitmap-font.d.ts +55 -0
  8. package/dist/bitmap-font.d.ts.map +1 -0
  9. package/dist/bitmap-font.js +103 -0
  10. package/dist/bitmap-font.js.map +1 -0
  11. package/dist/canvas2d.d.ts +45 -0
  12. package/dist/canvas2d.d.ts.map +1 -0
  13. package/dist/canvas2d.js +210 -0
  14. package/dist/canvas2d.js.map +1 -0
  15. package/dist/color.d.ts +7 -0
  16. package/dist/color.d.ts.map +1 -0
  17. package/dist/color.js +49 -0
  18. package/dist/color.js.map +1 -0
  19. package/dist/copies.d.ts +45 -0
  20. package/dist/copies.d.ts.map +1 -0
  21. package/dist/copies.js +43 -0
  22. package/dist/copies.js.map +1 -0
  23. package/dist/draw.d.ts +188 -0
  24. package/dist/draw.d.ts.map +1 -0
  25. package/dist/draw.js +603 -0
  26. package/dist/draw.js.map +1 -0
  27. package/dist/index.d.ts +9 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +7 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/renderer.d.ts +17 -0
  32. package/dist/renderer.d.ts.map +1 -0
  33. package/dist/renderer.js +61 -0
  34. package/dist/renderer.js.map +1 -0
  35. package/dist/shader.d.ts +34 -0
  36. package/dist/shader.d.ts.map +1 -0
  37. package/dist/shader.js +40 -0
  38. package/dist/shader.js.map +1 -0
  39. package/dist/target.d.ts +13 -0
  40. package/dist/target.d.ts.map +1 -0
  41. package/dist/target.js +18 -0
  42. package/dist/target.js.map +1 -0
  43. package/dist/webgl2.d.ts +90 -0
  44. package/dist/webgl2.d.ts.map +1 -0
  45. package/dist/webgl2.js +868 -0
  46. package/dist/webgl2.js.map +1 -0
  47. package/package.json +54 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 debuff contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,72 @@
1
- # Temporary Holding Version
1
+ # spryte
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A small, fast 2D renderer for the web. You draw in immediate mode (sprites, bulk sprites, rects, circles, lines, text, clips, blend modes, render targets and custom shaders), and spryte batches it onto WebGL2 with instancing, falling back to Canvas 2D automatically. No dependencies, no scene graph, no game framework.
4
+
5
+ > **Alpha.** spryte is the renderer inside [debuff](https://debuff.jp), where games already run on it. The API may still change before 1.0. So far it has been measured on desktop Chrome only; mobile and other browsers aren't verified yet.
6
+
7
+ ```bash
8
+ npm install spryte
9
+ ```
10
+
11
+ ```ts
12
+ import { createRenderer } from "spryte";
13
+
14
+ const draw = createRenderer(canvas, { smooth: false }); // smooth: false for pixel art
15
+ canvas.width = 640;
16
+ canvas.height = 360;
17
+ draw.resize(canvas.width, canvas.height);
18
+
19
+ function frame() {
20
+ draw.begin("#111", 320, 180, 2); // clear colour, logical size, backing pixels per logical unit
21
+ draw.rect(10, 10, 40, 20, "#cffb2d");
22
+ draw.sprite(image, 160, 90, { rotation: 0.3, tint: "#f0f" });
23
+ draw.text("hello", 8, 8);
24
+ draw.end();
25
+ requestAnimationFrame(frame);
26
+ }
27
+ requestAnimationFrame(frame);
28
+ ```
29
+
30
+ ## Why spryte
31
+
32
+ Measured against PixiJS 8 in the same session, with the same assets and the same simulation (desktop Chrome, RTX 5060 laptop). Full numbers and caveats are in [benchmarks](https://github.com/debuffjp/spryte/blob/main/docs/benchmarks.md).
33
+
34
+ | | spryte | PixiJS 8 |
35
+ | --- | --- | --- |
36
+ | JS at startup (brotli) | **8.4 kB** | 87.8 kB |
37
+ | 200k particles, position only | **3.8 ms** (`draw.sprites`) | 11.3 ms (`ParticleContainer`) |
38
+ | 200k particles, scale + rotation + tint + alpha per particle | **6.6 ms** | 26.8 ms |
39
+ | 50k sprites, one call each | **5.4 ms** (`draw.sprite`) | 21.2 ms (`Sprite`) |
40
+
41
+ - **Bulk sprites with no per-sprite JavaScript.** Pass a `Float32Array` of positions (plus optional per-copy scale, rotation and colour arrays) and spryte uploads it as is.
42
+ - **Immediate mode.** There are no display objects to create, pool or destroy. Draw what you want this frame.
43
+ - **Verified output.** Real-GPU pixel checks prove that the bulk paths, render targets and shaders draw exactly what the simple path draws.
44
+
45
+ ```ts
46
+ // Particles: one call, no objects.
47
+ draw.sprites(spark, positions, count, { tint: "#ffd36b" }, { scale, rotation, color });
48
+
49
+ // Post-processing: draw into a target, then draw the target through a shader.
50
+ draw.into(scene, () => drawWorld(draw));
51
+ draw.withShader(crt, () => draw.sprite(scene, 0, 0, { origin: [0, 0] }));
52
+ ```
53
+
54
+ ## Docs
55
+
56
+ - [API reference](https://github.com/debuffjp/spryte/blob/main/docs/api.md)
57
+ - [Architecture](https://github.com/debuffjp/spryte/blob/main/docs/architecture.md)
58
+ - [Benchmarks and method](https://github.com/debuffjp/spryte/blob/main/docs/benchmarks.md)
59
+ - [Minimal example](https://github.com/debuffjp/spryte/tree/main/examples/minimal): run `npm run example`, and add `?backend=2d` to the URL to see the fallback
60
+
61
+ ## Lifecycle
62
+
63
+ - `createRenderer(canvas, options)` makes a `Draw`. It uses WebGL2 when available, and otherwise Canvas 2D, loaded on demand. `await draw.ready` waits until the fallback can draw.
64
+ - You own the canvas size. After changing `canvas.width` or `canvas.height`, call `draw.resize(w, h)`.
65
+ - Each frame: `draw.begin(...)`, then your draw calls in order, then `draw.end()`. Call order is draw order.
66
+ - `draw.invalidate(source)` re-uploads an image whose pixels changed. `draw.disposeTarget(t)` frees a render target.
67
+ - `draw.dispose()` releases every GPU resource and listener.
68
+ - WebGL context loss is handled: drawing pauses while the context is lost (`draw.contextLost`), and textures re-upload after it's restored.
69
+
70
+ ## Licence
71
+
72
+ MIT
@@ -0,0 +1,69 @@
1
+ /** 2D affine matrix `[a, b, c, d, e, f]`: x' = a·x + c·y + e, y' = b·x + d·y + f (Canvas order). */
2
+ export type Matrix = [number, number, number, number, number, number];
3
+ export type BlendMode = "normal" | "add";
4
+ export interface ClipRect {
5
+ x: number;
6
+ y: number;
7
+ w: number;
8
+ h: number;
9
+ }
10
+ /** Raw access for advanced users. The backends are not interchangeable at this level. */
11
+ export type RawContext = {
12
+ kind: "webgl2";
13
+ gl: WebGL2RenderingContext;
14
+ } | {
15
+ kind: "2d";
16
+ ctx: CanvasRenderingContext2D;
17
+ };
18
+ import type { CopySpec } from "./copies.js";
19
+ import type { Shader } from "./shader.js";
20
+ import type { RenderTarget } from "./target.js";
21
+ /** Image sources the renderer can draw. Textures are cached per source object. */
22
+ export type TextureSource = HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | RenderTarget;
23
+ /**
24
+ * What a rendering backend implements. Everything is expressed as quads: a transform that maps the
25
+ * unit square onto logical space, an optional source rectangle, and an RGBA colour (tint).
26
+ * @internal
27
+ */
28
+ export interface Backend {
29
+ readonly kind: "webgl2" | "2d";
30
+ readonly raw: RawContext;
31
+ /** True while the GPU context is lost, where that can happen (WebGL2). */
32
+ readonly contextLost?: boolean;
33
+ /** GPU draw calls submitted so far this frame, where the backend batches (WebGL2). */
34
+ readonly drawCalls?: number;
35
+ /** Begin a frame: clear to `clear` (0xRRGGBBAA) at the given logical size and backing scale. */
36
+ begin(clear: number, width: number, height: number, scale: number): void;
37
+ /**
38
+ * Draw the unit square transformed by `m`. `src` null draws solid `color`.
39
+ * `sx, sy, sw, sh` is the source rect in source pixels (ignored when `src` is null). `flash` (0..1) mixes the texture toward white.
40
+ * `smooth` selects linear filtering for this source.
41
+ */
42
+ quad(m: Matrix, src: TextureSource | null, sx: number, sy: number, sw: number, sh: number, color: number, flash: number, smooth: boolean): void;
43
+ /**
44
+ * Many copies of one quad: `t` maps the unit square for a copy at (0, 0); copy i is moved by
45
+ * (positions[2i], positions[2i+1]) through `m`'s linear part. `snap` rounds each copy to whole pixels.
46
+ */
47
+ quads(t: Matrix, m: Matrix, positions: ArrayLike<number>, count: number, src: TextureSource, sx: number, sy: number, sw: number, sh: number, color: number, flash: number, smooth: boolean, snap: boolean): void;
48
+ /** Copies of one frame with per-copy scale, rotation or colour (`draw.sprites` with `each`). */
49
+ copies(spec: CopySpec): void;
50
+ setBlend(mode: BlendMode): void;
51
+ /**
52
+ * Send drawing to `target` (null: the canvas). `clear` (0xRRGGBBAA) clears it first; null keeps what's there.
53
+ * `width, height` are the logical size of the destination (the target's pixel size, or the canvas's logical size).
54
+ */
55
+ setTarget(target: RenderTarget | null, clear: number | null, width: number, height: number): void;
56
+ /** Draw subsequent quads with a custom fragment effect (null: the default). */
57
+ setShader(shader: Shader | null): void;
58
+ /** Free a target's GPU or canvas storage. */
59
+ disposeTarget(target: RenderTarget): void;
60
+ /** Restrict drawing to a rectangle in backing-store pixels (top-left origin), or remove the clip. */
61
+ setClip(rect: ClipRect | null): void;
62
+ /** Submit everything queued this frame. */
63
+ end(): void;
64
+ resize(backingWidth: number, backingHeight: number): void;
65
+ /** Drop cached GPU data for a source whose pixels changed. */
66
+ invalidate(src: TextureSource): void;
67
+ dispose(): void;
68
+ }
69
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEzC,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,yFAAyF;AACzF,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,sBAAsB,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,wBAAwB,CAAA;CAAE,CAAC;AAExH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,YAAY,CAAC;AAEhH;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,sFAAsF;IACtF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gGAAgG;IAChG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACzE;;;;OAIG;IACH,IAAI,CACF,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,aAAa,GAAG,IAAI,EACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,GACd,IAAI,CAAC;IACR;;;OAGG;IACH,KAAK,CACH,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ,IAAI,CAAC;IACR,gGAAgG;IAChG,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClG,+EAA+E;IAC/E,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACvC,6CAA6C;IAC7C,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1C,qGAAqG;IACrG,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;IACrC,2CAA2C;IAC3C,GAAG,IAAI,IAAI,CAAC;IACZ,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,8DAA8D;IAC9D,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import type { Frame } from "./draw.js";
2
+ export interface BitmapFontOptions {
3
+ /** One frame per glyph, in the order of `chars`: usually `assets.frames("font")` from a `font@WxH.png` grid. */
4
+ frames: readonly Frame[];
5
+ /** The characters the frames hold, in order. */
6
+ chars: string;
7
+ /**
8
+ * Advance per glyph in pixels. Default: measured from each glyph's rightmost opaque column, so a
9
+ * grid drawn in Aseprite becomes a proportional font. Pass a number for a monospaced font.
10
+ */
11
+ widths?: readonly number[] | number;
12
+ /** Pixels between glyphs. Default 1. */
13
+ spacing?: number;
14
+ /** Advance for a space (and any glyph that measures empty). Default a third of the cell height, rounded. */
15
+ spaceWidth?: number;
16
+ /** Pixels from one line's top to the next. Default the cell height + 1. */
17
+ lineHeight?: number;
18
+ /** Drawn for characters the font lacks. Default "?" if present, else nothing. */
19
+ fallback?: string;
20
+ }
21
+ export interface Glyph {
22
+ frame: Frame;
23
+ /** Pixels to advance after drawing, before spacing. */
24
+ advance: number;
25
+ }
26
+ /**
27
+ * A pixel font from a sprite sheet. Pass it as `font` to `draw.text` and `draw.measure`: glyphs land
28
+ * on whole pixels, so it stays crisp at any integer scale.
29
+ *
30
+ * ```ts
31
+ * // assets/font@6x9.png: glyphs on a 6×9 grid, exported from Aseprite
32
+ * const font = new BitmapFont({ frames: assets.frames("font"), chars: BitmapFont.ASCII });
33
+ * draw.text("coins 3", 4, 4, { font, color: "#fbbf24" });
34
+ * ```
35
+ */
36
+ export declare class BitmapFont {
37
+ /** Printable ASCII from space to "~", the order most font sheets use. */
38
+ static readonly ASCII: string;
39
+ /** Cell height in pixels. */
40
+ readonly height: number;
41
+ readonly lineHeight: number;
42
+ readonly spacing: number;
43
+ private readonly glyphs;
44
+ private readonly fallback;
45
+ constructor(o: BitmapFontOptions);
46
+ glyph(ch: string): Glyph | undefined;
47
+ /** Size of `text` in pixels. Lines split on "\n". */
48
+ measure(text: string): {
49
+ w: number;
50
+ h: number;
51
+ };
52
+ /** Width of one line, without trailing spacing. */
53
+ lineWidth(line: string): number;
54
+ }
55
+ //# sourceMappingURL=bitmap-font.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitmap-font.d.ts","sourceRoot":"","sources":["../src/bitmap-font.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC,gHAAgH;IAChH,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;IACpC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4GAA4G;IAC5G,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACrB,yEAAyE;IACzE,MAAM,CAAC,QAAQ,CAAC,KAAK,SAA8E;IAEnG,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,YAAY,CAAC,EAAE,iBAAiB,EAiB/B;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAEnC;IAED,qDAAqD;IACrD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAM9C;IAED,mDAAmD;IACnD,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAU9B;CACF"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * A pixel font from a sprite sheet. Pass it as `font` to `draw.text` and `draw.measure`: glyphs land
3
+ * on whole pixels, so it stays crisp at any integer scale.
4
+ *
5
+ * ```ts
6
+ * // assets/font@6x9.png: glyphs on a 6×9 grid, exported from Aseprite
7
+ * const font = new BitmapFont({ frames: assets.frames("font"), chars: BitmapFont.ASCII });
8
+ * draw.text("coins 3", 4, 4, { font, color: "#fbbf24" });
9
+ * ```
10
+ */
11
+ export class BitmapFont {
12
+ /** Printable ASCII from space to "~", the order most font sheets use. */
13
+ static ASCII = Array.from({ length: 95 }, (_, i) => String.fromCharCode(32 + i)).join("");
14
+ /** Cell height in pixels. */
15
+ height;
16
+ lineHeight;
17
+ spacing;
18
+ glyphs = new Map();
19
+ fallback;
20
+ constructor(o) {
21
+ const first = o.frames[0];
22
+ if (!first)
23
+ throw new Error("BitmapFont needs at least one frame");
24
+ const chars = [...o.chars];
25
+ if (chars.length > o.frames.length)
26
+ throw new Error(`BitmapFont has ${chars.length} chars but only ${o.frames.length} frames; check the grid size in the file name`);
27
+ this.height = first.h;
28
+ this.lineHeight = o.lineHeight ?? first.h + 1;
29
+ this.spacing = o.spacing ?? 1;
30
+ const space = o.spaceWidth ?? Math.max(1, Math.round(first.h / 3));
31
+ const measured = o.widths === undefined ? measureWidths(o.frames.slice(0, chars.length)) : undefined;
32
+ chars.forEach((ch, i) => {
33
+ const frame = o.frames[i];
34
+ const w = typeof o.widths === "number" ? o.widths : (o.widths?.[i] ?? measured?.[i] ?? frame.w);
35
+ this.glyphs.set(ch, { frame, advance: w > 0 ? w : space });
36
+ });
37
+ this.fallback = this.glyphs.get(o.fallback ?? "?");
38
+ }
39
+ glyph(ch) {
40
+ return this.glyphs.get(ch) ?? this.fallback;
41
+ }
42
+ /** Size of `text` in pixels. Lines split on "\n". */
43
+ measure(text) {
44
+ if (!text)
45
+ return { w: 0, h: 0 };
46
+ const lines = text.split("\n");
47
+ let w = 0;
48
+ for (const line of lines)
49
+ w = Math.max(w, this.lineWidth(line));
50
+ return { w, h: (lines.length - 1) * this.lineHeight + this.height };
51
+ }
52
+ /** Width of one line, without trailing spacing. */
53
+ lineWidth(line) {
54
+ let w = 0;
55
+ let n = 0;
56
+ for (const ch of line) {
57
+ const g = this.glyph(ch);
58
+ if (!g)
59
+ continue;
60
+ w += g.advance;
61
+ n++;
62
+ }
63
+ return n ? w + (n - 1) * this.spacing : 0;
64
+ }
65
+ }
66
+ /** Rightmost opaque column + 1 for each frame; 0 for empty ones. Falls back to the frame width without a 2D canvas. */
67
+ function measureWidths(frames) {
68
+ const cache = new Map();
69
+ return frames.map((f) => {
70
+ let img = cache.get(f.image);
71
+ if (img === undefined) {
72
+ img = readPixels(f.image);
73
+ cache.set(f.image, img);
74
+ }
75
+ if (!img)
76
+ return f.w;
77
+ for (let x = f.w - 1; x >= 0; x--)
78
+ for (let y = 0; y < f.h; y++)
79
+ if ((img.data[((f.y + y) * img.width + f.x + x) * 4 + 3] ?? 0) > 0)
80
+ return x + 1;
81
+ return 0;
82
+ });
83
+ }
84
+ function readPixels(src) {
85
+ const w = "naturalWidth" in src ? src.naturalWidth : src.width;
86
+ const h = "naturalHeight" in src ? src.naturalHeight : src.height;
87
+ if (!w || !h)
88
+ return null;
89
+ try {
90
+ const canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(w, h) : document.createElement("canvas");
91
+ canvas.width = w;
92
+ canvas.height = h;
93
+ const ctx = canvas.getContext("2d");
94
+ if (!ctx)
95
+ return null;
96
+ ctx.drawImage(src, 0, 0);
97
+ return { data: ctx.getImageData(0, 0, w, h).data, width: w };
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
103
+ //# sourceMappingURL=bitmap-font.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitmap-font.js","sourceRoot":"","sources":["../src/bitmap-font.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { Backend, BlendMode, ClipRect, Matrix, RawContext, TextureSource } from "./backend.js";
2
+ import { type CopySpec } from "./copies.js";
3
+ import type { Shader } from "./shader.js";
4
+ import { RenderTarget } from "./target.js";
5
+ /**
6
+ * Canvas 2D fallback for the `draw` API. Same output for solid shapes, sprites, text and alpha.
7
+ * Canvas 2D has no per-draw tint, so tinted textures (text, bitmap fonts, `tint`) go through a scratch
8
+ * canvas: slower than WebGL2, but only when a tint other than white is asked for.
9
+ */
10
+ export declare class Canvas2DBackend implements Backend {
11
+ readonly kind: "2d";
12
+ readonly raw: RawContext;
13
+ /** Where drawing goes: the canvas's context, or a render target's while inside `draw.into`. */
14
+ private ctx;
15
+ private readonly screen;
16
+ private screenScale;
17
+ private readonly surfaces;
18
+ private target;
19
+ private warnedShader;
20
+ private scale;
21
+ private smoothing;
22
+ private scratch;
23
+ private clipped;
24
+ private blendMode;
25
+ constructor(ctx: CanvasRenderingContext2D);
26
+ begin(clear: number, width: number, height: number, scale: number): void;
27
+ quad(m: Matrix, src: TextureSource | null, sx: number, sy: number, sw: number, sh: number, color: number, flash: number, smooth: boolean): void;
28
+ quads(t: Matrix, m: Matrix, positions: ArrayLike<number>, count: number, src: TextureSource, sx: number, sy: number, sw: number, sh: number, color: number, flash: number, smooth: boolean, snap: boolean): void;
29
+ copies(c: CopySpec): void;
30
+ setBlend(mode: BlendMode): void;
31
+ setClip(rect: ClipRect | null): void;
32
+ end(): void;
33
+ resize(): void;
34
+ invalidate(): void;
35
+ dispose(): void;
36
+ setTarget(target: RenderTarget | null, clear: number | null, _width: number, _height: number): void;
37
+ setShader(shader: Shader | null): void;
38
+ disposeTarget(target: RenderTarget): void;
39
+ private surface;
40
+ /** The source region multiplied by `color`'s RGB, keeping the source's alpha. */
41
+ private tinted;
42
+ private scratchCanvas;
43
+ private whiteSilhouette;
44
+ }
45
+ //# sourceMappingURL=canvas2d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas2d.d.ts","sourceRoot":"","sources":["../src/canvas2d.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEpG,OAAO,EAAE,KAAK,QAAQ,EAAU,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,QAAQ,CAAC,IAAI,EAAG,IAAI,CAAU;IAC9B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,+FAA+F;IAC/F,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,OAAO,CAAkD;IACjE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAuB;IAExC,YAAY,GAAG,EAAE,wBAAwB,EAIxC;IAED,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAWvE;IAED,IAAI,CACF,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,aAAa,GAAG,IAAI,EACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,GACd,IAAI,CAuBN;IAED,KAAK,CACH,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ,IAAI,CAaN;IAED,MAAM,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAMxB;IAED,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAG9B;IAED,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAenC;IAED,GAAG,IAAI,IAAI,CAIV;IAED,MAAM,IAAI,IAAI,CAGb;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,OAAO,IAAI,IAAI,CAAG;IAElB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAiBlG;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAKrC;IAED,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAQxC;IAED,OAAO,CAAC,OAAO;IAYf,iFAAiF;IACjF,OAAO,CAAC,MAAM;IAiBd,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;CAYxB"}
@@ -0,0 +1,210 @@
1
+ import { rgbaToCss } from "./color.js";
2
+ import { copyAt } from "./copies.js";
3
+ import { RenderTarget } from "./target.js";
4
+ /**
5
+ * Canvas 2D fallback for the `draw` API. Same output for solid shapes, sprites, text and alpha.
6
+ * Canvas 2D has no per-draw tint, so tinted textures (text, bitmap fonts, `tint`) go through a scratch
7
+ * canvas: slower than WebGL2, but only when a tint other than white is asked for.
8
+ */
9
+ export class Canvas2DBackend {
10
+ kind = "2d";
11
+ raw;
12
+ /** Where drawing goes: the canvas's context, or a render target's while inside `draw.into`. */
13
+ ctx;
14
+ screen;
15
+ screenScale = 1;
16
+ surfaces = new WeakMap();
17
+ target = null;
18
+ warnedShader = false;
19
+ scale = 1;
20
+ smoothing;
21
+ scratch;
22
+ clipped = false;
23
+ blendMode = "normal";
24
+ constructor(ctx) {
25
+ this.ctx = ctx;
26
+ this.screen = ctx;
27
+ this.raw = { kind: "2d", ctx };
28
+ }
29
+ begin(clear, width, height, scale) {
30
+ this.ctx = this.screen;
31
+ this.target = null;
32
+ this.scale = scale;
33
+ this.screenScale = scale;
34
+ const ctx = this.ctx;
35
+ ctx.setTransform(scale, 0, 0, scale, 0, 0);
36
+ ctx.globalAlpha = 1;
37
+ ctx.globalCompositeOperation = "source-over";
38
+ ctx.fillStyle = rgbaToCss(clear);
39
+ ctx.fillRect(0, 0, width, height);
40
+ }
41
+ quad(m, src, sx, sy, sw, sh, color, flash, smooth) {
42
+ if (src !== null && src === this.target)
43
+ throw new Error("spryte: can't draw a render target into itself");
44
+ const ctx = this.ctx;
45
+ const s = this.scale;
46
+ ctx.setTransform(m[0] * s, m[1] * s, m[2] * s, m[3] * s, m[4] * s, m[5] * s);
47
+ if (!src) {
48
+ ctx.globalAlpha = 1;
49
+ ctx.fillStyle = rgbaToCss(color);
50
+ ctx.fillRect(0, 0, 1, 1);
51
+ return;
52
+ }
53
+ if (this.smoothing !== smooth) {
54
+ ctx.imageSmoothingEnabled = smooth;
55
+ this.smoothing = smooth;
56
+ }
57
+ const image = src instanceof RenderTarget ? this.surface(src) : src;
58
+ ctx.globalAlpha = (color & 0xff) / 255;
59
+ if (color >>> 8 === 0xffffff)
60
+ ctx.drawImage(image, sx, sy, sw, sh, 0, 0, 1, 1);
61
+ else
62
+ ctx.drawImage(this.tinted(image, sx, sy, sw, sh, color), 0, 0, sw, sh, 0, 0, 1, 1);
63
+ if (flash > 0) {
64
+ ctx.globalAlpha *= Math.min(1, flash);
65
+ ctx.drawImage(this.whiteSilhouette(image, sx, sy, sw, sh), 0, 0, sw, sh, 0, 0, 1, 1);
66
+ }
67
+ }
68
+ quads(t, m, positions, count, src, sx, sy, sw, sh, color, flash, smooth, snap) {
69
+ const q = [t[0], t[1], t[2], t[3], 0, 0];
70
+ for (let i = 0; i < count; i++) {
71
+ const x = positions[i * 2];
72
+ const y = positions[i * 2 + 1];
73
+ q[4] = t[4] + m[0] * x + m[2] * y;
74
+ q[5] = t[5] + m[1] * x + m[3] * y;
75
+ if (snap) {
76
+ q[4] = Math.round(q[4]);
77
+ q[5] = Math.round(q[5]);
78
+ }
79
+ this.quad(q, src, sx, sy, sw, sh, color, flash, smooth);
80
+ }
81
+ }
82
+ copies(c) {
83
+ const q = [1, 0, 0, 1, 0, 0];
84
+ for (let i = 0; i < c.count; i++) {
85
+ const color = copyAt(c, i, q);
86
+ this.quad(q, c.src, c.sx, c.sy, c.sw, c.sh, color, c.flash, c.smooth);
87
+ }
88
+ }
89
+ setBlend(mode) {
90
+ this.blendMode = mode;
91
+ this.ctx.globalCompositeOperation = mode === "add" ? "lighter" : "source-over";
92
+ }
93
+ setClip(rect) {
94
+ const ctx = this.ctx;
95
+ // Canvas clips only shrink, so each change restores to the unclipped state first.
96
+ if (this.clipped) {
97
+ ctx.restore();
98
+ this.clipped = false;
99
+ this.setBlend(this.blendMode);
100
+ }
101
+ if (!rect)
102
+ return;
103
+ ctx.save();
104
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
105
+ ctx.beginPath();
106
+ ctx.rect(rect.x, rect.y, rect.w, rect.h);
107
+ ctx.clip();
108
+ this.clipped = true;
109
+ }
110
+ end() {
111
+ this.setClip(null);
112
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0);
113
+ this.ctx.globalAlpha = 1;
114
+ }
115
+ resize() {
116
+ // Canvas resize resets context state; it's reapplied in begin().
117
+ this.smoothing = undefined;
118
+ }
119
+ invalidate() {
120
+ // Canvas 2D reads sources directly; nothing is cached.
121
+ }
122
+ dispose() { }
123
+ setTarget(target, clear, _width, _height) {
124
+ this.ctx = target ? this.surface(target).getContext("2d") : this.screen;
125
+ this.target = target;
126
+ // Targets are sized in pixels; the canvas in logical units at its backing scale.
127
+ this.scale = target ? 1 : this.screenScale;
128
+ this.smoothing = undefined;
129
+ this.setBlend(this.blendMode);
130
+ if (target && clear !== null) {
131
+ const ctx = this.ctx;
132
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
133
+ ctx.globalAlpha = 1;
134
+ ctx.clearRect(0, 0, target.width, target.height);
135
+ if ((clear & 0xff) !== 0) {
136
+ ctx.fillStyle = rgbaToCss(clear);
137
+ ctx.fillRect(0, 0, target.width, target.height);
138
+ }
139
+ }
140
+ }
141
+ setShader(shader) {
142
+ if (shader && !this.warnedShader) {
143
+ this.warnedShader = true;
144
+ console.warn("spryte: custom shaders need WebGL2; the Canvas 2D fallback draws without them");
145
+ }
146
+ }
147
+ disposeTarget(target) {
148
+ if (target === this.target)
149
+ throw new Error("spryte: can't dispose a render target while drawing into it");
150
+ const surface = this.surfaces.get(target);
151
+ if (!surface)
152
+ return;
153
+ // Release the pixels now rather than whenever the canvas is collected.
154
+ surface.width = 0;
155
+ surface.height = 0;
156
+ this.surfaces.delete(target);
157
+ }
158
+ surface(target) {
159
+ let surface = this.surfaces.get(target);
160
+ if (!surface) {
161
+ surface =
162
+ typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(target.width, target.height) : document.createElement("canvas");
163
+ surface.width = target.width;
164
+ surface.height = target.height;
165
+ this.surfaces.set(target, surface);
166
+ }
167
+ return surface;
168
+ }
169
+ /** The source region multiplied by `color`'s RGB, keeping the source's alpha. */
170
+ tinted(src, x, y, w, h, color) {
171
+ const scratch = this.scratchCanvas(w, h);
172
+ const sctx = scratch.getContext("2d");
173
+ if (!sctx)
174
+ return scratch;
175
+ sctx.clearRect(0, 0, w, h);
176
+ sctx.globalCompositeOperation = "source-over";
177
+ sctx.drawImage(src, x, y, w, h, 0, 0, w, h);
178
+ sctx.globalCompositeOperation = "multiply";
179
+ sctx.fillStyle = rgbaToCss(color | 0xff);
180
+ sctx.fillRect(0, 0, w, h);
181
+ // multiply filled the transparent pixels too; cut back to the source's shape.
182
+ sctx.globalCompositeOperation = "destination-in";
183
+ sctx.drawImage(src, x, y, w, h, 0, 0, w, h);
184
+ sctx.globalCompositeOperation = "source-over";
185
+ return scratch;
186
+ }
187
+ scratchCanvas(w, h) {
188
+ if (!this.scratch)
189
+ this.scratch = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(w, h) : document.createElement("canvas");
190
+ if (this.scratch.width < w)
191
+ this.scratch.width = w;
192
+ if (this.scratch.height < h)
193
+ this.scratch.height = h;
194
+ return this.scratch;
195
+ }
196
+ whiteSilhouette(src, x, y, w, h) {
197
+ const scratch = this.scratchCanvas(w, h);
198
+ const sctx = scratch.getContext("2d");
199
+ if (!sctx)
200
+ return scratch;
201
+ sctx.clearRect(0, 0, w, h);
202
+ sctx.globalCompositeOperation = "source-over";
203
+ sctx.drawImage(src, x, y, w, h, 0, 0, w, h);
204
+ sctx.globalCompositeOperation = "source-in";
205
+ sctx.fillStyle = "#fff";
206
+ sctx.fillRect(0, 0, w, h);
207
+ return scratch;
208
+ }
209
+ }
210
+ //# sourceMappingURL=canvas2d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas2d.js","sourceRoot":"","sources":["../src/canvas2d.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAiB,MAAM,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;GAIG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,IAAa,CAAC;IACrB,GAAG,CAAa;IACzB,+FAA+F;IACvF,GAAG,CAA2B;IACrB,MAAM,CAA2B;IAC1C,WAAW,GAAG,CAAC,CAAC;IACP,QAAQ,GAAG,IAAI,OAAO,EAAyB,CAAC;IACzD,MAAM,GAAwB,IAAI,CAAC;IACnC,YAAY,GAAG,KAAK,CAAC;IACrB,KAAK,GAAG,CAAC,CAAC;IACV,SAAS,CAAsB;IAC/B,OAAO,CAAkD;IACzD,OAAO,GAAG,KAAK,CAAC;IAChB,SAAS,GAAc,QAAQ,CAAC;IAExC,YAAY,GAA6B;QACvC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QAClB,IAAI,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAa,EAAE,KAAa,EAAE,MAAc,EAAE,KAAa;QAC/D,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;QACpB,GAAG,CAAC,wBAAwB,GAAG,aAAa,CAAC;QAC7C,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CACF,CAAS,EACT,GAAyB,EACzB,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,KAAa,EACb,KAAa,EACb,MAAe;QAEf,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC3G,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YAC9B,GAAG,CAAC,qBAAqB,GAAG,MAAM,CAAC;YACnC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QAC1B,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,YAAY,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACpE,GAAG,CAAC,WAAW,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC;QACvC,IAAI,KAAK,KAAK,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;;YAC1E,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACtC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,KAAK,CACH,CAAS,EACT,CAAS,EACT,SAA4B,EAC5B,KAAa,EACb,GAAkB,EAClB,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,KAAa,EACb,KAAa,EACb,MAAe,EACf,IAAa;QAEb,MAAM,CAAC,GAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC;YACrC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAW,CAAC;YACzC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,IAAI,EAAE,CAAC;gBACT,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,CAAW;QAChB,MAAM,CAAC,GAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAe;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,wBAAwB,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;IACjF,CAAC;IAED,OAAO,CAAC,IAAqB;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,kFAAkF;QAClF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACzC,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,GAAG;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM;QACJ,iEAAiE;QACjE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,UAAU;QACR,uDAAuD;IACzD,CAAC;IAED,OAAO,KAAU,CAAC;IAElB,SAAS,CAAC,MAA2B,EAAE,KAAoB,EAAE,MAAc,EAAE,OAAe;QAC1F,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,IAAI,CAA8B,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACtG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,iFAAiF;QACjF,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9B,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;YACrB,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;gBACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAqB;QAC7B,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,aAAa,CAAC,MAAoB;QAChC,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAC3G,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,uEAAuE;QACvE,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;QAClB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEO,OAAO,CAAC,MAAoB;QAClC,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,eAAe,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC/H,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC7B,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,iFAAiF;IACzE,MAAM,CAAC,GAAsB,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa;QAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAoC,CAAC;QACzE,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,wBAAwB,GAAG,aAAa,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,UAAU,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,8EAA8E;QAC9E,IAAI,CAAC,wBAAwB,GAAG,gBAAgB,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,aAAa,CAAC;QAC9C,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,aAAa,CAAC,CAAS,EAAE,CAAS;QACxC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,eAAe,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxI,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,eAAe,CAAC,GAAsB,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS;QACxF,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAoC,CAAC;QACzE,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,wBAAwB,GAAG,aAAa,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,WAAW,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ /** A colour: CSS hex string (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`) or a number `0xRRGGBBAA`. */
2
+ export type Color = string | number;
3
+ /** Normalise a colour to `0xRRGGBBAA` (unsigned). Hex strings are cached; other CSS colours resolve through the browser. */
4
+ export declare function toRGBA(color: Color): number;
5
+ /** `0xRRGGBBAA` to a CSS colour string. */
6
+ export declare function rgbaToCss(rgba: number, alphaScale?: number): string;
7
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAIpC,4HAA4H;AAC5H,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAQ3C;AA8BD,2CAA2C;AAC3C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,MAAM,CAG9D"}