@glissade/scene 0.10.0-pre.1 → 0.10.1-pre.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.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +25 -7
- package/dist/layoutEngine.d.ts +16 -8
- package/dist/layoutEngine.js +10 -9
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -440,6 +440,10 @@ declare class ShaderEffect extends Group {
|
|
|
440
440
|
}
|
|
441
441
|
//#endregion
|
|
442
442
|
//#region src/raster2d.d.ts
|
|
443
|
+
/** A backend gradient handle (DOM CanvasGradient and @napi-rs CanvasGradient both satisfy it). */
|
|
444
|
+
interface CanvasGradientLike {
|
|
445
|
+
addColorStop(offset: number, color: string): void;
|
|
446
|
+
}
|
|
443
447
|
/** The structural path surface buildPath drives — DOM Path2D and @napi-rs Path2D both satisfy it. */
|
|
444
448
|
interface PathLike {
|
|
445
449
|
moveTo(x: number, y: number): void;
|
|
@@ -468,6 +472,8 @@ interface Ctx2DLike<TPath, TDrawable> {
|
|
|
468
472
|
drawImage(image: TDrawable, x: number, y: number, w?: number, h?: number): void;
|
|
469
473
|
drawImage(image: TDrawable, sx: number, sy: number, sw: number, sh: number, x: number, y: number, w: number, h: number): void;
|
|
470
474
|
setLineDash(segments: number[]): void;
|
|
475
|
+
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradientLike;
|
|
476
|
+
createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradientLike;
|
|
471
477
|
lineDashOffset: number;
|
|
472
478
|
fillStyle: unknown;
|
|
473
479
|
strokeStyle: unknown;
|
package/dist/index.js
CHANGED
|
@@ -967,6 +967,24 @@ var ShaderEffect = class extends Group {
|
|
|
967
967
|
* four-line adapters, so the twin rasterizers structurally cannot drift —
|
|
968
968
|
* the golden + SSIM suites verify the refactor preserved every byte.
|
|
969
969
|
*/
|
|
970
|
+
function resolveFill(ctx, paint, bounds) {
|
|
971
|
+
if (paint.kind === "color") return paint.color;
|
|
972
|
+
let g;
|
|
973
|
+
if (paint.kind === "radial") {
|
|
974
|
+
const cx = paint.center ? paint.center[0] : bounds ? (bounds.minX + bounds.maxX) / 2 : 0;
|
|
975
|
+
const cy = paint.center ? paint.center[1] : bounds ? (bounds.minY + bounds.maxY) / 2 : 0;
|
|
976
|
+
const r = paint.radius !== void 0 ? paint.radius : bounds ? Math.hypot(bounds.maxX - bounds.minX, bounds.maxY - bounds.minY) / 2 : 0;
|
|
977
|
+
g = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);
|
|
978
|
+
} else {
|
|
979
|
+
const fx = paint.from ? paint.from[0] : bounds ? (bounds.minX + bounds.maxX) / 2 : 0;
|
|
980
|
+
const fy = paint.from ? paint.from[1] : bounds ? bounds.minY : 0;
|
|
981
|
+
const tx = paint.to ? paint.to[0] : bounds ? (bounds.minX + bounds.maxX) / 2 : 0;
|
|
982
|
+
const ty = paint.to ? paint.to[1] : bounds ? bounds.maxY : 0;
|
|
983
|
+
g = ctx.createLinearGradient(fx, fy, tx, ty);
|
|
984
|
+
}
|
|
985
|
+
for (const s of paint.stops) g.addColorStop(s.offset, s.color);
|
|
986
|
+
return g;
|
|
987
|
+
}
|
|
970
988
|
function fontString(font) {
|
|
971
989
|
return `${font.style === "italic" ? "italic " : ""}${font.weight !== void 0 && font.weight !== 400 ? `${font.weight} ` : ""}${font.size}px ${font.family}`;
|
|
972
990
|
}
|
|
@@ -1260,15 +1278,16 @@ var Raster2D = class {
|
|
|
1260
1278
|
break;
|
|
1261
1279
|
case "fillPath": {
|
|
1262
1280
|
const ctx = ctxOf();
|
|
1263
|
-
ctx.fillStyle = cmd.paint.color;
|
|
1264
|
-
ctx.fill(this.path(list.resources, cmd.path));
|
|
1265
1281
|
const b = this.pathBounds(list.resources, cmd.path);
|
|
1282
|
+
ctx.fillStyle = resolveFill(ctx, cmd.paint, b);
|
|
1283
|
+
ctx.fill(this.path(list.resources, cmd.path));
|
|
1266
1284
|
if (b) accumulateRect(top(), mat, b.minX, b.minY, b.maxX, b.maxY);
|
|
1267
1285
|
break;
|
|
1268
1286
|
}
|
|
1269
1287
|
case "strokePath": {
|
|
1270
1288
|
const ctx = ctxOf();
|
|
1271
|
-
|
|
1289
|
+
const sb = this.pathBounds(list.resources, cmd.path);
|
|
1290
|
+
ctx.strokeStyle = resolveFill(ctx, cmd.paint, sb);
|
|
1272
1291
|
ctx.lineWidth = cmd.stroke.width;
|
|
1273
1292
|
ctx.lineCap = cmd.stroke.cap ?? "butt";
|
|
1274
1293
|
ctx.lineJoin = cmd.stroke.join ?? "miter";
|
|
@@ -1281,17 +1300,16 @@ var Raster2D = class {
|
|
|
1281
1300
|
ctx.setLineDash([]);
|
|
1282
1301
|
ctx.lineDashOffset = 0;
|
|
1283
1302
|
}
|
|
1284
|
-
|
|
1285
|
-
if (b) {
|
|
1303
|
+
if (sb) {
|
|
1286
1304
|
const o = cmd.stroke.width * ((cmd.stroke.join ?? "miter") === "miter" ? 5 : 1);
|
|
1287
|
-
accumulateRect(top(), mat,
|
|
1305
|
+
accumulateRect(top(), mat, sb.minX - o, sb.minY - o, sb.maxX + o, sb.maxY + o);
|
|
1288
1306
|
}
|
|
1289
1307
|
break;
|
|
1290
1308
|
}
|
|
1291
1309
|
case "fillText": {
|
|
1292
1310
|
const ctx = ctxOf();
|
|
1293
1311
|
ctx.font = fontString(cmd.font);
|
|
1294
|
-
ctx.fillStyle = cmd.paint
|
|
1312
|
+
ctx.fillStyle = resolveFill(ctx, cmd.paint, null);
|
|
1295
1313
|
ctx.textBaseline = "alphabetic";
|
|
1296
1314
|
ctx.textAlign = cmd.align ?? "left";
|
|
1297
1315
|
ctx.fillText(cmd.text, cmd.x, cmd.y);
|
package/dist/layoutEngine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BindableSignal, PathValue, ReadonlySignal, Rng, Track, Vec2, Vec2Signal } from "@glissade/core";
|
|
1
|
+
import { BindableSignal, Paint, PathValue, ReadonlySignal, Rng, Track, Vec2, Vec2Signal } from "@glissade/core";
|
|
2
2
|
|
|
3
3
|
//#region src/matrix.d.ts
|
|
4
4
|
|
|
@@ -33,11 +33,6 @@ type Resource = {
|
|
|
33
33
|
mediaT: number;
|
|
34
34
|
};
|
|
35
35
|
type BlendMode = 'source-over' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten';
|
|
36
|
-
/** M1: solid colors. Gradients/patterns are additive later — backends switch on kind. */
|
|
37
|
-
type Paint = {
|
|
38
|
-
kind: 'color';
|
|
39
|
-
color: string;
|
|
40
|
-
};
|
|
41
36
|
interface StrokeStyle {
|
|
42
37
|
width: number;
|
|
43
38
|
cap?: 'butt' | 'round' | 'square';
|
|
@@ -287,6 +282,15 @@ interface NodeProps {
|
|
|
287
282
|
* (the cache key folds in the inherited device transform, so a stale CTM can
|
|
288
283
|
* never blit). OFF by default: a scene that never sets it emits ZERO extra
|
|
289
284
|
* groups and is byte-identical to before. Best for expensive STATIC subtrees.
|
|
285
|
+
*
|
|
286
|
+
* CAVEAT (when it does NOT help): the key folds in the inherited device
|
|
287
|
+
* transform, so a subtree that itself DRIFTS — e.g. animated on sub-pixel
|
|
288
|
+
* float positions — misses the cache every frame; cache a static subtree
|
|
289
|
+
* under a *moving parent*, not a subtree that moves itself. And a `filter`
|
|
290
|
+
* is a LIVE composite parameter applied on the blit, never baked into the
|
|
291
|
+
* cached bitmap, so `cache:true` on a filter-declaring (e.g. blurred) group
|
|
292
|
+
* does not cache the filter cost. For per-frame-cheap drift, prefer
|
|
293
|
+
* eliminating the work (a cheaper Paint/effect) over caching it.
|
|
290
294
|
*/
|
|
291
295
|
cache?: boolean;
|
|
292
296
|
}
|
|
@@ -489,8 +493,12 @@ declare class Group extends Node {
|
|
|
489
493
|
remove(child: Node): this;
|
|
490
494
|
protected draw(out: DisplayListBuilder, ctx: EvalContext): void;
|
|
491
495
|
}
|
|
496
|
+
/** A color string is sugar for a solid `color` Paint; a Paint passes through. */
|
|
497
|
+
|
|
492
498
|
interface ShapeProps extends NodeProps {
|
|
493
|
-
|
|
499
|
+
/** A CSS color string, or a `Paint` (e.g. a `radial` gradient — soft-light
|
|
500
|
+
* fills with no blur filter; center/radius default to the shape bounds). */
|
|
501
|
+
fill?: PropInit<string | Paint>;
|
|
494
502
|
stroke?: PropInit<string>;
|
|
495
503
|
strokeWidth?: PropInit<number>;
|
|
496
504
|
/** hand-drawn look: the outline is geometrically roughened (see sketch.ts) */
|
|
@@ -506,7 +514,7 @@ interface ShapeProps extends NodeProps {
|
|
|
506
514
|
sketchFill?: HachureSpec;
|
|
507
515
|
}
|
|
508
516
|
declare abstract class Shape extends Node {
|
|
509
|
-
readonly fill: BindableSignal<string>;
|
|
517
|
+
readonly fill: BindableSignal<string | Paint>;
|
|
510
518
|
readonly stroke: BindableSignal<string>;
|
|
511
519
|
readonly strokeWidth: BindableSignal<number>;
|
|
512
520
|
readonly sketch: SketchStyle | undefined;
|
package/dist/layoutEngine.js
CHANGED
|
@@ -948,6 +948,13 @@ var Group = class extends Node {
|
|
|
948
948
|
for (const child of sorted) child.emit(out, ctx);
|
|
949
949
|
}
|
|
950
950
|
};
|
|
951
|
+
/** A color string is sugar for a solid `color` Paint; a Paint passes through. */
|
|
952
|
+
function toPaint(fill) {
|
|
953
|
+
return typeof fill === "string" ? {
|
|
954
|
+
kind: "color",
|
|
955
|
+
color: fill
|
|
956
|
+
} : fill;
|
|
957
|
+
}
|
|
951
958
|
var Shape = class extends Node {
|
|
952
959
|
fill;
|
|
953
960
|
stroke;
|
|
@@ -984,10 +991,7 @@ var Shape = class extends Node {
|
|
|
984
991
|
if (fill) out.push({
|
|
985
992
|
op: "fillPath",
|
|
986
993
|
path,
|
|
987
|
-
paint:
|
|
988
|
-
kind: "color",
|
|
989
|
-
color: fill
|
|
990
|
-
}
|
|
994
|
+
paint: toPaint(fill)
|
|
991
995
|
});
|
|
992
996
|
const stroke = this.stroke();
|
|
993
997
|
const width = this.strokeWidth();
|
|
@@ -1021,14 +1025,11 @@ var Shape = class extends Node {
|
|
|
1021
1025
|
out.push({
|
|
1022
1026
|
op: "fillPath",
|
|
1023
1027
|
path,
|
|
1024
|
-
paint:
|
|
1025
|
-
kind: "color",
|
|
1026
|
-
color: fill
|
|
1027
|
-
}
|
|
1028
|
+
paint: toPaint(fill)
|
|
1028
1029
|
});
|
|
1029
1030
|
}
|
|
1030
1031
|
const { strokes, resolved } = roughen(segs, this.sketch, rng);
|
|
1031
|
-
const ink = this.stroke() || fill || "#000000";
|
|
1032
|
+
const ink = this.stroke() || (typeof fill === "string" ? fill : "") || "#000000";
|
|
1032
1033
|
if (this.sketchFill) {
|
|
1033
1034
|
const clipPath = out.resource({
|
|
1034
1035
|
kind: "path",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glissade/scene",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1-pre.0",
|
|
4
4
|
"description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"yoga-layout": "^3.2.1",
|
|
23
|
-
"@glissade/core": "0.10.
|
|
23
|
+
"@glissade/core": "0.10.1-pre.0"
|
|
24
24
|
},
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|