@flatkit/compiler 0.35.1 → 0.35.3

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.
@@ -465,15 +465,21 @@ and composes with `self.x`/`self.y` etc. (same `self`).
465
465
 
466
466
  ## `filter` performance
467
467
 
468
- - A `filter glow`/`shadow` = **one offscreen canvas recomposited** per group carrying the
469
- filter. The engine automatically **caches** *static* filtered subtrees (decor with no
470
- expression or animation): they are only re-rendered on zoom/pan or asset load. So a filter
471
- on **static decor** is nearly free in steady state.
472
- - A filter on an **animated** element (channel expression, `bind`, timeline) is recomposited
473
- every frame. Keep filters on animated elements **small**.
468
+ - A `filter glow`/`shadow` = **one offscreen canvas recomposited**, then blitted. The engine **caches**
469
+ that composite, keyed on the item's screen placement, so a filter that holds still is repaid once and
470
+ then costs a single blit — on a group **and on a bare shape** (`circle … filter glow`), which went
471
+ uncached until 0.35.0: 360 recompositions over 60 frames where the same thing, cached, does 0.
472
+ - The cache is **per instance**, not per item: eight lanterns from one filtered symbol keep eight bitmaps.
473
+ (They shared one entry before 0.35.0 and thrashed it — 480 recompositions over 60 frames.)
474
+ - **What defeats it: motion that never settles.** The key is the placement, so a *periodic* `clock`/`time`
475
+ motion (`dy = 3 * sin(clock)`) on the filtered item **or on any ancestor** never repeats a key: 270
476
+ recompositions over 60 frames, for as long as the scene is open. `--check` reports it, naming the
477
+ culprits. A motion that comes to REST (a `shake` at 0, a `clamp` decay) pays once and hits forever, and
478
+ animating **`opacity`** is free — it is applied at blit time, deliberately outside the key.
474
479
  - Cheap alternative for decor shadows: a **"baked" shadow** = the same path offset by a few
475
480
  px in `#00000028` UNDER the cutout (no offscreen canvas). Ideal for large planes.
476
- - Drop-shadow cost ∝ area × blur: a large blurred plane is expensive when not cached.
481
+ - Drop-shadow cost ∝ area × blur: a large blurred plane is expensive when not cached. A document keeps at
482
+ most 256 baked composites; past that, the extra ones simply draw the slow way.
477
483
 
478
484
  ## Audio
479
485
 
@@ -90,8 +90,11 @@ filter blur <radius>
90
90
  filter adjust <brightness> <contrast> <saturate> <hue>
91
91
  ```
92
92
 
93
- Filters on **static** decor are cached (nearly free); on **animated** elements they recomposite every
94
- frame — keep those small (see the [gotchas](dsl-gotchas.md) for the perf details).
93
+ A filter is composited off-screen and the result is **cached** on the item's screen placement — on a group
94
+ and on a bare shape alike — so decor that holds still is repaid once. What defeats the cache is placement
95
+ that never settles: a periodic `sin(clock)` motion on the item **or an ancestor** re-composites every
96
+ frame, and `--check` says so. Animating `opacity` instead is free. See the
97
+ [gotchas](dsl-gotchas.md#filter-performance) for the numbers.
95
98
 
96
99
  ## Clipping & masks
97
100
 
package/docs/tooling.md CHANGED
@@ -90,6 +90,15 @@ or a `tint`) that the symbol doesn't declare — a silent "dead recolor". The la
90
90
  groups** and measure in world coordinates, and they skip anything positioned at runtime (a bound or dragged
91
91
  item, and everything nested under one, has no meaningful static position).
92
92
 
93
+ It reports what a gesture or a shape does SILENTLY when its options do not add up: a `draw` on a shape
94
+ with no `stroke` (nothing to trim), a `reveal … cells` array whose length does not match the grid the
95
+ engine builds (writes past the end are dropped, so a restored session comes back untouched — the message
96
+ states the geometry and the exact `fill(N, 0)` to declare), a `step` of 0 or less on a `trace` (the
97
+ progress can never move, so the drill cannot be completed), `both ends` without `step`, a non-positive
98
+ `tolerance`/`brush`/`grain` (silently replaced by the default), and a `filter` under a transform that
99
+ never stops moving (the composite is re-baked every frame, forever — see the
100
+ [gotchas](dsl-gotchas.md#filter-performance)).
101
+
93
102
  It flags an instant **captured on `time` and read by `pulse`/`shake`** — both ride the monotone `clock`, so
94
103
  the two axes never meet and the ramp never fires, with nothing on screen to say so. The costliest kind of
95
104
  bug in a codebase migrated from 0.21; see the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flatkit/compiler",
3
- "version": "0.35.1",
3
+ "version": "0.35.3",
4
4
  "description": "The FlatInk language (parser + AST) and compiler (.flatink → .flatpack). Ships the flatc CLI.",
5
5
  "license": "MIT",
6
6
  "author": "Zwyk Studio",
@@ -57,9 +57,9 @@
57
57
  "docs"
58
58
  ],
59
59
  "dependencies": {
60
- "@flatkit/engine": "0.35.1",
61
- "@flatkit/player": "0.35.1",
62
- "@flatkit/types": "0.35.1"
60
+ "@flatkit/engine": "0.35.3",
61
+ "@flatkit/player": "0.35.3",
62
+ "@flatkit/types": "0.35.3"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "skia-canvas": "^3.0.8"