openpencil/packages/core/package.json
Danila Poyarkov 379ef8b62d
perf(canvas): rebuild navigation rendering (#591)
* perf(canvas): add traced navigation benchmarks

- Record and replay timestamped pan and zoom gestures through DOM and CDP input paths\n- Correlate input, viewport, render, long-task, and retained-backing events in Chromium traces\n- Report frame pacing, latency, jump, anchor drift, and crisp-settlement metrics

* perf(canvas): stabilize navigation comparisons

- Separate low-overhead metric runs from optional CPU-profile traces\n- Warm scenarios before recording and use a consistent SwiftShader browser configuration\n- Add a canonical momentum-pan reversal gesture alongside pinch reversal

* fix(canvas): require hardware GPU navigation benchmarks

- Run macOS performance captures through Metal-backed ANGLE and reject accidental SwiftShader fallback\n- Record the GL renderer and reserve software GPU mode for portable correctness smoke runs

* perf(canvas): cache shadow rasters for crisp backing

- Rasterize local drop and inner shadows only while constructing retained scene backing\n- Bound native image memory and invalidate cached entries with node and renderer lifecycle changes\n- Quantize zoom-aware raster resolution and reuse nearby scales without lowering normal scene quality

* test(canvas): verify retained shadow raster fidelity

- Compare settled retained-backing shadow output with direct CanvasKit rendering\n- Keep backdrop blur on the picture fallback and exercise graph-driven cache invalidation\n- Cover updates, deletion, and reparenting through actual SceneGraph events

* perf(canvas): benchmark real FIG fixtures

- Serve exact local fixture bytes through an isolated Playwright route for production preview runs\n- Wait for document loading and page population before zooming to fit and recording navigation\n- Record the resolved fixture path in benchmark environment artifacts

* fix(canvas): preserve nested effect subtree pictures

- Keep deeply nested shadow documents on one retained subtree picture instead of exploding them into per-node image draws\n- Restrict shadow raster acceleration to effect-bearing page children\n- Cover nested shadow fallback and restore gold-preview FIG pinch performance to master levels

* refactor(canvas): share recorded wheel sample type

* perf(canvas): defer backing settlement across zoom reversals

- Track explicit navigation phases and gesture generations instead of inferring idle from viewport timing\n- Cancel or defer retained backing construction while pan, zoom, momentum, or tentative settlement is active\n- Add a repeated short-pause pinch reversal fixture based on the user trace

* perf(canvas): index bounded render chunks

- Split oversized painter subtrees into self-paint and bounded descendant chunks without dropping container visuals\n- Bulk-load chunk visual bounds into RBush for selective world-space queries\n- Cover bounded updates and gold-preview build/query complexity before tile rendering consumes the index

* refactor(canvas): namespace render chunk coverage

* perf(canvas): model chunk paint context

- Preserve ancestor transform and clip dependencies for independently renderable chunks\n- Keep opacity, blend, blur, and mask isolation subtrees atomic until command-level splitting exists\n- Report oversized atomic chunks and lock gold-preview to bounded painter units

* perf(canvas): record pixel-correct render chunks

- Record interruptible chunks in world coordinates with ancestor transforms, clips, and chunk-local culling bounds\n- Draw opacity, blend, blur, and mask isolation chunks directly into destination surfaces in painter order\n- Compare composited chunk output with direct CanvasKit rendering instead of relaxing visual thresholds

* perf(canvas): render selective world tiles

- Map world regions to fixed 256-device-pixel tile targets and quantized sharpness levels\n- Query only intersecting render chunks and preserve atomic destination compositing\n- Match multi-tile CanvasKit output against direct rendering and measure gold-preview tile cost

* perf(canvas): cache chunk pictures across tiles

- Reuse world-space chunk command pictures for every intersecting tile\n- Pool 256-pixel tile surfaces and expose allocation, draw, flush, and snapshot timings\n- Keep expensive atomic foreground blur visible as an over-budget scheduler constraint

* perf(canvas): schedule cached tile rendering

- Bound tile images with an LRU cache and reuse pooled CanvasKit surfaces\n- Plan mandatory holes, stale visible refreshes, and overscan by navigation and content generation\n- Stop jobs at a strict deadline while reporting fallbacks, stale work, overruns, and over-budget effects

* perf(canvas): integrate progressive tiled rendering

- Keep retained scene output as the interaction fallback while exact tiles refine only after navigation becomes idle
- Centralize runtime URL flags and pass renderer selection through the typed Vue canvas API
- Replace benchmark sleeps with explicit mode-aware renderer settlement and report exact tiled coverage
- Preserve bounded scheduler metrics, generation cancellation, native resource cleanup, and shared visual-bounds logic

* refactor(app): centralize runtime query configuration

- Parse collaboration, recent-files, benchmark, presentation, and renderer flags in one typed app module
- Remove ad hoc URL parsing from workspace and collaboration runtime consumers
- Cover supported values and production-safe defaults without adding a repository lint rule

* fix(canvas): replace fallback pixels with exact tiles

- Render opaque page-background tile cells and install them with source replacement instead of double-compositing translucent scene content
- Exercise the live progressive controller against direct rendering across masks, effects, blend isolation, images, fallback text, transforms, and clipping
- Preserve the bounded reversal path with zero Long Tasks and exact settlement near 128 ms on gold-preview.fig

* perf(canvas): invalidate tiled content selectively

- Index chunk dependencies across contained nodes and transform or clipping ancestors
- Re-record affected chunk pictures and invalidate tiles intersecting old or new visual bounds
- Advance unaffected cached tiles to the new scene generation instead of rebuilding the full chunk index and tile cache
- Keep structural graph mutations on the safe full-rebuild path and cover selective refresh end to end

* perf(canvas): bound atomic blur tile refresh

- Render atomic blur chunks with tile-local isolation bounds and blur halos instead of replaying full-subtree layers
- Keep content refresh behind the retained fallback, cap GPU submissions to four tile jobs per frame, and adapt estimates from measured work
- Preserve large-radius CPU over-budget visibility while preventing Metal-backed refresh bursts and deferred GPU overload
- Add deterministic node-mutation benchmarks and summarize scheduler throughput, job duration, overruns, and exact content settlement

* perf(canvas): cancel obsolete tile refresh generations

- Count and report queued jobs removed by content or navigation generation changes
- Add deterministic mutation-then-reversal benchmark support without sleeps
- Assert exact tile work remains suspended during navigation and resumes for the final viewport
- Summarize cancellation alongside scheduler throughput, overruns, and settlement metrics

* test(canvas): cover live tiled blur settlement

- Load gold-preview.fig through the real tiled canvas surface and wait on explicit renderer settlement
- Commit the settled radius-210 large-blur browser snapshot
- Replay the canonical zoom reversal during refresh and require byte-identical final canvas convergence

* fix(canvas): harden renderer resource lifecycle

- Release tiled surfaces, images, pictures, and queued work across surface, font, graph, page, structure, and renderer lifecycle boundaries
- Restore pooled canvas, viewport, and backing state through exception-safe native recording and raster paths
- Rebuild tiled chunk topology only when isolation requirements actually change, preserving selective blur mutation performance
- Document deterministic active-renderer settlement and add lifecycle, graph replacement, cache failure, and surface replacement regressions

* test(canvas): remove source-matching renderer claims

- Delete the autopsy suite that inferred runtime correctness from source text, regexes, line placement, and symbol counts
- Keep renderer ordering, cache cleanup, effect behavior, and pixel fidelity covered by executable behavioral and lifecycle tests

* perf(canvas): present retained backing during tiled navigation

- Profile production reversal traces and attribute tiled p95 cost to GPU command-buffer flushes from full-scene fallback replay and tile presentation
- Use the retained backing as the moving fallback while tile scheduling and cached lookup remain allocation-free
- Defer tile image presentation until idle and expose visible versus presented tile counts in navigation telemetry
- Reduce tiled reversal render p95 from about 8ms to 0.3ms while preserving exact idle replacement and visual parity

* perf(canvas): prioritize visible tile settlement

- Profile per-tile allocation, draw, flush, snapshot, and chunk costs through scheduler telemetry
- Defer overscan until all visible exact tiles are covered
- Replace the four-job idle cap with a higher safety ceiling while the measured five-millisecond deadline controls cheap work
- Reduce mutation-plus-reversal exact settlement from about 272ms to 160ms without Long Tasks, overruns, or over-budget jobs

* refactor(canvas): clarify renderer lifecycle boundaries

- Extract retained backing state types and navigation preview timing\n- Isolate tiled scheduler telemetry from frame orchestration\n- Document settlement and CanvasKit ownership invariants\n- Preserve hot drawing loops, budgets, cache limits, and rendering decisions

* fix(canvas): preserve current label rendering

Retain the merged paragraph-label cache lifecycle and substituted-font readiness while reconstructing the renderer stack on current master.

* test(canvas): keep tile benchmark assertions deterministic

Keep performance timing in benchmark telemetry while asserting structural tile selectivity and cache behavior in CI.

* feat(canvas): expose experimental tiled rendering

- Persist retained or tiled canvas mode in General settings\n- Keep retained rendering as the default and apply changes after reload\n- Preserve URL overrides for deterministic benchmarks and support reproduction

* refactor(app): centralize renderer preference state

Expose renderer override provenance from runtime configuration and keep the settings control's derived state separate from its explicit persistence action.

* refactor(app): share settings layout anatomy

Reuse slot-based section headers and bordered groups while keeping each settings control row explicit.

* fix(canvas): harden tiled renderer boundaries

- Bound low-zoom tile planning and handle failed tile surface allocation\n- Preserve effect raster dependencies, runtime-safe clocks, and navigation timing contracts\n- Keep benchmarks deterministic, backward compatible, and accurately localized

* fix(canvas): invalidate dependent node pictures

Track first-child shadow dependencies for retained node pictures so child geometry updates cannot leave stale parent shadows.
2026-08-31 13:39:40 +03:00

216 lines
6.1 KiB
JSON

{
"name": "@open-pencil/core",
"version": "0.14.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/open-pencil/open-pencil.git",
"directory": "packages/core"
},
"files": [
"dist",
"assets"
],
"type": "module",
"sideEffects": false,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"imports": {
"#core/*": "./src/*"
},
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./color": {
"types": "./dist/color/index.d.ts",
"import": "./dist/color/index.js",
"default": "./dist/color/index.js"
},
"./text": {
"types": "./dist/text/index.d.ts",
"import": "./dist/text/index.js",
"default": "./dist/text/index.js"
},
"./text/web-font/assets": {
"types": "./dist/text/web-font/assets.d.ts",
"import": "./dist/text/web-font/assets.js",
"default": "./dist/text/web-font/assets.js"
},
"./vector": {
"types": "./dist/vector/index.d.ts",
"import": "./dist/vector/index.js",
"default": "./dist/vector/index.js"
},
"./figma-api": {
"types": "./dist/figma-api/index.d.ts",
"import": "./dist/figma-api/index.js",
"default": "./dist/figma-api/index.js"
},
"./icons": {
"types": "./dist/icons/index.d.ts",
"import": "./dist/icons/index.js",
"default": "./dist/icons/index.js"
},
"./canvas": {
"types": "./dist/canvas/index.d.ts",
"import": "./dist/canvas/index.js",
"default": "./dist/canvas/index.js"
},
"./design-jsx": {
"types": "./dist/design-jsx/index.d.ts",
"import": "./dist/design-jsx/index.js",
"default": "./dist/design-jsx/index.js"
},
"./editor": {
"types": "./dist/editor/index.d.ts",
"import": "./dist/editor/index.js",
"default": "./dist/editor/index.js"
},
"./tools": {
"types": "./dist/tools/index.d.ts",
"import": "./dist/tools/index.js",
"default": "./dist/tools/index.js"
},
"./profiler": {
"types": "./dist/profiler/index.d.ts",
"import": "./dist/profiler/index.js",
"default": "./dist/profiler/index.js"
},
"./rpc": {
"types": "./dist/rpc/index.d.ts",
"import": "./dist/rpc/index.js",
"default": "./dist/rpc/index.js"
},
"./library": {
"bun": "./src/library/index.ts",
"types": "./dist/library/index.d.ts",
"import": "./dist/library/index.js",
"default": "./dist/library/index.js"
},
"./lint": {
"types": "./dist/lint/index.d.ts",
"import": "./dist/lint/index.js",
"default": "./dist/lint/index.js"
},
"./io": {
"types": "./dist/io/index.d.ts",
"import": "./dist/io/index.js",
"default": "./dist/io/index.js"
},
"./io/formats/fig": {
"types": "./dist/io/formats/fig/index.d.ts",
"import": "./dist/io/formats/fig/index.js",
"default": "./dist/io/formats/fig/index.js"
},
"./io/formats/jsx": {
"types": "./dist/io/formats/jsx/index.d.ts",
"import": "./dist/io/formats/jsx/index.js",
"default": "./dist/io/formats/jsx/index.js"
},
"./io/formats/raster": {
"types": "./dist/io/formats/raster/index.d.ts",
"import": "./dist/io/formats/raster/index.js",
"default": "./dist/io/formats/raster/index.js"
},
"./io/formats/svg": {
"types": "./dist/io/formats/svg/index.d.ts",
"import": "./dist/io/formats/svg/index.js",
"default": "./dist/io/formats/svg/index.js"
},
"./kiwi": {
"types": "./dist/kiwi/index.d.ts",
"import": "./dist/kiwi/index.js",
"default": "./dist/kiwi/index.js"
},
"./clipboard": {
"types": "./dist/clipboard.d.ts",
"import": "./dist/clipboard.js",
"default": "./dist/clipboard.js"
},
"./bytes": {
"bun": "./src/bytes/index.ts",
"types": "./dist/bytes/index.d.ts",
"import": "./dist/bytes/index.js",
"default": "./dist/bytes/index.js"
},
"./constants": {
"types": "./dist/constants.d.ts",
"import": "./dist/constants.js",
"default": "./dist/constants.js"
},
"./random": {
"types": "./dist/random.d.ts",
"import": "./dist/random.js",
"default": "./dist/random.js"
},
"./xpath": {
"types": "./dist/xpath.d.ts",
"import": "./dist/xpath.js",
"default": "./dist/xpath.js"
},
"./canvaskit": {
"types": "./dist/canvaskit.d.ts",
"import": "./dist/canvaskit.js",
"default": "./dist/canvaskit.js"
},
"./layout": {
"types": "./dist/layout.d.ts",
"import": "./dist/layout.js",
"default": "./dist/layout.js"
}
},
"publishConfig": {
"access": "public",
"provenance": true
},
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts",
"prepublishOnly": "bun run build"
},
"dependencies": {
"@chenglou/pretext": "^0.0.7",
"@iconify/utils": "^3.1.4",
"@open-pencil/fig": "workspace:*",
"@open-pencil/kiwi": "workspace:*",
"@open-pencil/pen": "workspace:*",
"@open-pencil/scene-graph": "workspace:*",
"@tauri-apps/api": "^2.11.1",
"@xmldom/xmldom": "^0.9.11",
"acorn": "^8.18.0",
"canvaskit-wasm": "^0.41.1",
"culori": "^4.0.2",
"destr": "^2.0.5",
"diff": "^8.0.4",
"es-toolkit": "^1.51.0",
"expr-eval": "^2.0.2",
"fflate": "^0.8.3",
"fontoxpath": "^3.34.0",
"fzstd": "^0.1.1",
"js-base64": "^3.9.3",
"jspdf": "^4.2.1",
"nanoevents": "^9.1.0",
"ofetch": "^1.5.1",
"opentype.js": "^2.0.0",
"pptxgenjs": "^4.0.1",
"rbush": "^4.0.1",
"sucrase": "^3.35.1",
"svg-path-properties": "^2.0.2",
"svg2pdf.js": "^2.7.0",
"svgpath": "^2.6.0",
"twirlwind": "^0.3.0",
"unifont": "0.7.4",
"yoga-layout": "npm:@open-pencil/yoga-layout@3.3.0-grid.3"
},
"devDependencies": {
"@types/culori": "^4.0.1",
"@types/diff": "^8.0.0",
"@types/opentype.js": "^1.3.10",
"@types/rbush": "^4.0.0",
"typescript": "~5.8.3"
}
}