@weasel-js/core 1.6.1 → 1.7.1

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 (1005) hide show
  1. package/CHANGELOG.md +1006 -0
  2. package/README.md +28 -9
  3. package/dist/WeaselProvider.js +15 -0
  4. package/dist/WeaselProvider.js.map +1 -0
  5. package/dist/affordances/composeAffordanceLayer.js +224 -0
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -0
  7. package/dist/affordances/cornerResize.js +69 -0
  8. package/dist/affordances/cornerResize.js.map +1 -0
  9. package/dist/affordances/hitAffordanceRegions.js +138 -0
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -0
  11. package/dist/affordances/pathAnchors.js +66 -0
  12. package/dist/affordances/pathAnchors.js.map +1 -0
  13. package/dist/affordances/rotationHandle.js +103 -0
  14. package/dist/affordances/rotationHandle.js.map +1 -0
  15. package/dist/animation/behaviors/momentum.js +118 -0
  16. package/dist/animation/behaviors/momentum.js.map +1 -0
  17. package/dist/animation/colorHelpers.js +135 -0
  18. package/dist/animation/colorHelpers.js.map +1 -0
  19. package/dist/animation/colorRegistry.js +37 -0
  20. package/dist/animation/colorRegistry.js.map +1 -0
  21. package/dist/animation/index.js +20 -0
  22. package/dist/animation/loop.js +62 -0
  23. package/dist/animation/loop.js.map +1 -0
  24. package/dist/animation/observe.js +23 -0
  25. package/dist/animation/observe.js.map +1 -0
  26. package/dist/animation/poseHelpers.js +50 -0
  27. package/dist/animation/poseHelpers.js.map +1 -0
  28. package/dist/animation/reflow.js +121 -0
  29. package/dist/animation/reflow.js.map +1 -0
  30. package/dist/animation/rig/bindRig.js +74 -0
  31. package/dist/animation/rig/bindRig.js.map +1 -0
  32. package/dist/animation/rig/blendPoses.js +43 -0
  33. package/dist/animation/rig/blendPoses.js.map +1 -0
  34. package/dist/animation/rig/mirrorPose.js +19 -0
  35. package/dist/animation/rig/mirrorPose.js.map +1 -0
  36. package/dist/animation/rig/resolveSkeleton.js +33 -0
  37. package/dist/animation/rig/resolveSkeleton.js.map +1 -0
  38. package/dist/animation/rig/solveIk.js +103 -0
  39. package/dist/animation/rig/solveIk.js.map +1 -0
  40. package/dist/animation/rig/types.js +12 -0
  41. package/dist/animation/rig/types.js.map +1 -0
  42. package/dist/animation/rig/useRig.js +23 -0
  43. package/dist/animation/rig/useRig.js.map +1 -0
  44. package/dist/animation/slew.js +27 -0
  45. package/dist/animation/slew.js.map +1 -0
  46. package/dist/animation/stagger.js +138 -0
  47. package/dist/animation/stagger.js.map +1 -0
  48. package/dist/animation/timeline/booking.js +106 -0
  49. package/dist/animation/timeline/booking.js.map +1 -0
  50. package/dist/animation/timeline/createTimeline.js +116 -0
  51. package/dist/animation/timeline/createTimeline.js.map +1 -0
  52. package/dist/animation/timeline/sampleTrack.js +29 -0
  53. package/dist/animation/timeline/sampleTrack.js.map +1 -0
  54. package/dist/animation/useAnimator.js +329 -0
  55. package/dist/animation/useAnimator.js.map +1 -0
  56. package/dist/animation/wrappers/animateLifecycle.js +40 -0
  57. package/dist/animation/wrappers/animateLifecycle.js.map +1 -0
  58. package/dist/animation/wrappers/animateOnSetPose.js +44 -0
  59. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -0
  60. package/dist/{autoPoseDescriptor-_XOyF7t4.d.ts → autoPoseDescriptor-BT_vp9FO.d.ts} +2 -2
  61. package/dist/{builtins-HWyuLzE-.d.ts → builtins-BSUfH8nU.d.ts} +1301 -508
  62. package/dist/canvas/Canvas.js +608 -0
  63. package/dist/canvas/Canvas.js.map +1 -0
  64. package/dist/canvas/CanvasView.js +255 -0
  65. package/dist/canvas/CanvasView.js.map +1 -0
  66. package/dist/canvas/CursorCoordsHud.js +75 -0
  67. package/dist/canvas/CursorCoordsHud.js.map +1 -0
  68. package/dist/canvas/DrawCanvas.js +67 -0
  69. package/dist/canvas/DrawCanvas.js.map +1 -0
  70. package/dist/canvas/MinimapCanvas.js +139 -0
  71. package/dist/canvas/MinimapCanvas.js.map +1 -0
  72. package/dist/canvas/ModalityHud.js +66 -0
  73. package/dist/canvas/ModalityHud.js.map +1 -0
  74. package/dist/canvas/NodeShape.js +391 -0
  75. package/dist/canvas/NodeShape.js.map +1 -0
  76. package/dist/canvas/PickHud.js +93 -0
  77. package/dist/canvas/PickHud.js.map +1 -0
  78. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +10 -0
  79. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +10 -0
  81. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js.map +1 -0
  82. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +51 -0
  83. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -0
  84. package/dist/canvas/SceneCanvas/contributionFrameHooks.js +42 -0
  85. package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -0
  86. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +549 -0
  87. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -0
  88. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +26 -0
  89. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -0
  90. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +69 -0
  91. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -0
  92. package/dist/canvas/SceneCanvas/features.js +97 -0
  93. package/dist/canvas/SceneCanvas/features.js.map +1 -0
  94. package/dist/canvas/SceneCanvas/poseGeometry.js +46 -0
  95. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -0
  96. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +48 -0
  97. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -0
  98. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +70 -0
  99. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -0
  100. package/dist/canvas/SceneCanvas/useContributionRoles.js +75 -0
  101. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -0
  102. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +172 -0
  103. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -0
  104. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +69 -0
  105. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -0
  106. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +127 -0
  107. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -0
  108. package/dist/canvas/SceneCanvas/useViewportActions.js +30 -0
  109. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -0
  110. package/dist/canvas/SceneCanvas.js +992 -0
  111. package/dist/canvas/SceneCanvas.js.map +1 -0
  112. package/dist/canvas/SceneViewCanvas.js +54 -0
  113. package/dist/canvas/SceneViewCanvas.js.map +1 -0
  114. package/dist/canvas/accentColor.js +9 -0
  115. package/dist/canvas/accentColor.js.map +1 -0
  116. package/dist/canvas/affordanceAt.js +63 -0
  117. package/dist/canvas/affordanceAt.js.map +1 -0
  118. package/dist/canvas/buildSceneTree.js +65 -0
  119. package/dist/canvas/buildSceneTree.js.map +1 -0
  120. package/dist/canvas/canvasRenderer.js +89 -0
  121. package/dist/canvas/canvasRenderer.js.map +1 -0
  122. package/dist/canvas/colorOverrides.js +16 -0
  123. package/dist/canvas/colorOverrides.js.map +1 -0
  124. package/dist/canvas/defaultDrawOne.js +43 -0
  125. package/dist/canvas/defaultDrawOne.js.map +1 -0
  126. package/dist/canvas/deps/areaSelect.js +19 -0
  127. package/dist/canvas/deps/areaSelect.js.map +1 -0
  128. package/dist/canvas/deps/debug.js +9 -0
  129. package/dist/canvas/deps/debug.js.map +1 -0
  130. package/dist/canvas/deps/dispatcher.js +11 -0
  131. package/dist/canvas/deps/dispatcher.js.map +1 -0
  132. package/dist/canvas/deps/editAnchors.js +101 -0
  133. package/dist/canvas/deps/editAnchors.js.map +1 -0
  134. package/dist/canvas/deps/geometryProjection.js +11 -0
  135. package/dist/canvas/deps/geometryProjection.js.map +1 -0
  136. package/dist/canvas/deps/hitTestArea.js +51 -0
  137. package/dist/canvas/deps/hitTestArea.js.map +1 -0
  138. package/dist/canvas/deps/ingestion.js +31 -0
  139. package/dist/canvas/deps/ingestion.js.map +1 -0
  140. package/dist/canvas/deps/insert.js +116 -0
  141. package/dist/canvas/deps/insert.js.map +1 -0
  142. package/dist/canvas/deps/lassoSelect.js +20 -0
  143. package/dist/canvas/deps/lassoSelect.js.map +1 -0
  144. package/dist/canvas/deps/layout.js +34 -0
  145. package/dist/canvas/deps/layout.js.map +1 -0
  146. package/dist/canvas/deps/nodeAtPoint.js +19 -0
  147. package/dist/canvas/deps/nodeAtPoint.js.map +1 -0
  148. package/dist/canvas/deps/poseComposition.js +11 -0
  149. package/dist/canvas/deps/poseComposition.js.map +1 -0
  150. package/dist/canvas/deps/poseDescriptor.js +12 -0
  151. package/dist/canvas/deps/poseDescriptor.js.map +1 -0
  152. package/dist/canvas/deps/resizePolicy.js +35 -0
  153. package/dist/canvas/deps/resizePolicy.js.map +1 -0
  154. package/dist/canvas/deps/slice.js +99 -0
  155. package/dist/canvas/deps/slice.js.map +1 -0
  156. package/dist/canvas/deps/snap.js +11 -0
  157. package/dist/canvas/deps/snap.js.map +1 -0
  158. package/dist/canvas/deps/textEdit.js +21 -0
  159. package/dist/canvas/deps/textEdit.js.map +1 -0
  160. package/dist/canvas/deps/view.js +43 -0
  161. package/dist/canvas/deps/view.js.map +1 -0
  162. package/dist/canvas/derivedPath.js +47 -0
  163. package/dist/canvas/derivedPath.js.map +1 -0
  164. package/dist/canvas/drawEnvelope.js +22 -0
  165. package/dist/canvas/drawEnvelope.js.map +1 -0
  166. package/dist/canvas/getNodeAtPoint.js +18 -0
  167. package/dist/canvas/getNodeAtPoint.js.map +1 -0
  168. package/dist/canvas/hostAnchor.js +29 -0
  169. package/dist/canvas/hostAnchor.js.map +1 -0
  170. package/dist/canvas/hud.module.js +18 -0
  171. package/dist/canvas/hud.module.js.map +1 -0
  172. package/dist/canvas/insertPreviewExtent.js +103 -0
  173. package/dist/canvas/insertPreviewExtent.js.map +1 -0
  174. package/dist/canvas/kitRequirements.js +177 -0
  175. package/dist/canvas/kitRequirements.js.map +1 -0
  176. package/dist/canvas/layerOrder.js +66 -0
  177. package/dist/canvas/layerOrder.js.map +1 -0
  178. package/dist/canvas/layerSlots.js +14 -0
  179. package/dist/canvas/layerSlots.js.map +1 -0
  180. package/dist/canvas/minimapMath.js +80 -0
  181. package/dist/canvas/minimapMath.js.map +1 -0
  182. package/dist/canvas/mountedCanvases.js +20 -0
  183. package/dist/canvas/mountedCanvases.js.map +1 -0
  184. package/dist/canvas/overlayRoleStrokes.js +17 -0
  185. package/dist/canvas/overlayRoleStrokes.js.map +1 -0
  186. package/dist/canvas/paintCull.js +20 -0
  187. package/dist/canvas/paintCull.js.map +1 -0
  188. package/dist/canvas/pickWalk.js +158 -0
  189. package/dist/canvas/pickWalk.js.map +1 -0
  190. package/dist/canvas/planeClips.js +30 -0
  191. package/dist/canvas/planeClips.js.map +1 -0
  192. package/dist/canvas/poseRotation.js +35 -0
  193. package/dist/canvas/poseRotation.js.map +1 -0
  194. package/dist/canvas/rasterToPng.js +21 -0
  195. package/dist/canvas/rasterToPng.js.map +1 -0
  196. package/dist/canvas/renderDebugSnapshot.js +32 -0
  197. package/dist/canvas/renderDebugSnapshot.js.map +1 -0
  198. package/dist/canvas/renderNeeds.js +25 -0
  199. package/dist/canvas/renderNeeds.js.map +1 -0
  200. package/dist/canvas/renderSceneToPixels.js +143 -0
  201. package/dist/canvas/renderSceneToPixels.js.map +1 -0
  202. package/dist/canvas/sceneAdapter.js +270 -0
  203. package/dist/canvas/sceneAdapter.js.map +1 -0
  204. package/dist/canvas/sceneLayerPaint.js +37 -0
  205. package/dist/canvas/sceneLayerPaint.js.map +1 -0
  206. package/dist/canvas/sceneSlotWiring.js +20 -0
  207. package/dist/canvas/sceneSlotWiring.js.map +1 -0
  208. package/dist/canvas/sceneViewRender.js +72 -0
  209. package/dist/canvas/sceneViewRender.js.map +1 -0
  210. package/dist/canvas/slopsDebugLayer.js +61 -0
  211. package/dist/canvas/slopsDebugLayer.js.map +1 -0
  212. package/dist/canvas/surfaceContribution.js +15 -0
  213. package/dist/canvas/surfaceContribution.js.map +1 -0
  214. package/dist/canvas/toolPreview.js +39 -0
  215. package/dist/canvas/toolPreview.js.map +1 -0
  216. package/dist/canvas/useCanvasRenderer.js +11 -0
  217. package/dist/canvas/useCanvasRenderer.js.map +1 -0
  218. package/dist/canvas/useFrameLoop.js +60 -0
  219. package/dist/canvas/useFrameLoop.js.map +1 -0
  220. package/dist/canvas/useHostAnchor.js +71 -0
  221. package/dist/canvas/useHostAnchor.js.map +1 -0
  222. package/dist/canvas/useLateContentRedraw.js +21 -0
  223. package/dist/canvas/useLateContentRedraw.js.map +1 -0
  224. package/dist/canvas/useRedrawOn.js +21 -0
  225. package/dist/canvas/useRedrawOn.js.map +1 -0
  226. package/dist/canvas/useViewHelpers.js +120 -0
  227. package/dist/canvas/useViewHelpers.js.map +1 -0
  228. package/dist/canvas/viewInputs.js +17 -0
  229. package/dist/canvas/viewInputs.js.map +1 -0
  230. package/dist/canvas/viewRegistry.js +61 -0
  231. package/dist/canvas/viewRegistry.js.map +1 -0
  232. package/dist/canvas/wrapNodeOutput.js +14 -0
  233. package/dist/canvas/wrapNodeOutput.js.map +1 -0
  234. package/dist/clipboard.d.ts +10 -5
  235. package/dist/clipboard.js +3 -5
  236. package/dist/clone.d.ts +3 -3
  237. package/dist/clone.js +2 -5
  238. package/dist/core/adapters/arrayAdapter.js +85 -0
  239. package/dist/core/adapters/arrayAdapter.js.map +1 -0
  240. package/dist/core/adapters/useArrayAdapter.js +13 -0
  241. package/dist/core/adapters/useArrayAdapter.js.map +1 -0
  242. package/dist/core/applyOps.js +12 -0
  243. package/dist/core/applyOps.js.map +1 -0
  244. package/dist/core/device/index.js +4 -0
  245. package/dist/core/device/targets.js +17 -0
  246. package/dist/core/device/targets.js.map +1 -0
  247. package/dist/core/device/useDeviceProfile.js +75 -0
  248. package/dist/core/device/useDeviceProfile.js.map +1 -0
  249. package/dist/core/fillInPoseFrame.js +102 -0
  250. package/dist/core/fillInPoseFrame.js.map +1 -0
  251. package/dist/core/geometry/poseDescriptor.js +98 -0
  252. package/dist/core/geometry/poseDescriptor.js.map +1 -0
  253. package/dist/core/geometry/poseRotation.js +58 -0
  254. package/dist/core/geometry/poseRotation.js.map +1 -0
  255. package/dist/core/geometry/regionHit.js +102 -0
  256. package/dist/core/geometry/regionHit.js.map +1 -0
  257. package/dist/core/geometry/unionBounds.js +60 -0
  258. package/dist/core/geometry/unionBounds.js.map +1 -0
  259. package/dist/core/gradient.js +136 -0
  260. package/dist/core/gradient.js.map +1 -0
  261. package/dist/core/isPlainObject.js +11 -0
  262. package/dist/core/isPlainObject.js.map +1 -0
  263. package/dist/core/layers/render.js +150 -0
  264. package/dist/core/layers/render.js.map +1 -0
  265. package/dist/core/markerInset.js +24 -0
  266. package/dist/core/markerInset.js.map +1 -0
  267. package/dist/core/mixed.js +6 -0
  268. package/dist/core/mixed.js.map +1 -0
  269. package/dist/core/ops/arrange.js +31 -0
  270. package/dist/core/ops/arrange.js.map +1 -0
  271. package/dist/core/ops/create.js +32 -0
  272. package/dist/core/ops/create.js.map +1 -0
  273. package/dist/core/ops/createHistory.js +20 -0
  274. package/dist/core/ops/createHistory.js.map +1 -0
  275. package/dist/core/ops/delete.js +89 -0
  276. package/dist/core/ops/delete.js.map +1 -0
  277. package/dist/core/ops/registry.js +17 -0
  278. package/dist/core/ops/registry.js.map +1 -0
  279. package/dist/core/ops/reorder/algorithms.js +55 -0
  280. package/dist/core/ops/reorder/algorithms.js.map +1 -0
  281. package/dist/core/ops/reorder/index.js +140 -0
  282. package/dist/core/ops/reorder/index.js.map +1 -0
  283. package/dist/core/ops/reparent.js +52 -0
  284. package/dist/core/ops/reparent.js.map +1 -0
  285. package/dist/core/ops/select.js +34 -0
  286. package/dist/core/ops/select.js.map +1 -0
  287. package/dist/core/ops/setData.js +34 -0
  288. package/dist/core/ops/setData.js.map +1 -0
  289. package/dist/core/ops/setLayer.js +34 -0
  290. package/dist/core/ops/setLayer.js.map +1 -0
  291. package/dist/core/ops/setLayout.js +31 -0
  292. package/dist/core/ops/setLayout.js.map +1 -0
  293. package/dist/core/ops/setPath.js +57 -0
  294. package/dist/core/ops/setPath.js.map +1 -0
  295. package/dist/core/ops/setText.js +34 -0
  296. package/dist/core/ops/setText.js.map +1 -0
  297. package/dist/core/ops/slot.js +37 -0
  298. package/dist/core/ops/slot.js.map +1 -0
  299. package/dist/core/ops/transform.js +42 -0
  300. package/dist/core/ops/transform.js.map +1 -0
  301. package/dist/core/paintKinds.js +156 -0
  302. package/dist/core/paintKinds.js.map +1 -0
  303. package/dist/core/scene/NodeProperties.js +20 -0
  304. package/dist/core/scene/NodeProperties.js.map +1 -0
  305. package/dist/core/scene/NodeRouting.js +24 -0
  306. package/dist/core/scene/NodeRouting.js.map +1 -0
  307. package/dist/core/scene/arrivals.js +12 -0
  308. package/dist/core/scene/arrivals.js.map +1 -0
  309. package/dist/core/scene/composeFrame.js +29 -0
  310. package/dist/core/scene/composeFrame.js.map +1 -0
  311. package/dist/core/scene/depMemo.js +18 -0
  312. package/dist/core/scene/depMemo.js.map +1 -0
  313. package/dist/core/scene/dependents.js +66 -0
  314. package/dist/core/scene/dependents.js.map +1 -0
  315. package/dist/core/scene/derivedPath.js +31 -0
  316. package/dist/core/scene/derivedPath.js.map +1 -0
  317. package/dist/core/scene/effectivePose.js +78 -0
  318. package/dist/core/scene/effectivePose.js.map +1 -0
  319. package/dist/core/scene/kitRegistry.js +33 -0
  320. package/dist/core/scene/kitRegistry.js.map +1 -0
  321. package/dist/core/scene/layoutPass.js +96 -0
  322. package/dist/core/scene/layoutPass.js.map +1 -0
  323. package/dist/core/scene/nodeFnFields.js +83 -0
  324. package/dist/core/scene/nodeFnFields.js.map +1 -0
  325. package/dist/core/scene/nodeMemo.js +28 -0
  326. package/dist/core/scene/nodeMemo.js.map +1 -0
  327. package/dist/core/scene/poseFeed.js +87 -0
  328. package/dist/core/scene/poseFeed.js.map +1 -0
  329. package/dist/core/scene/poseOverrides.js +52 -0
  330. package/dist/core/scene/poseOverrides.js.map +1 -0
  331. package/dist/core/scene/poseSnapshot.js +54 -0
  332. package/dist/core/scene/poseSnapshot.js.map +1 -0
  333. package/dist/core/scene/scene.js +1271 -0
  334. package/dist/core/scene/scene.js.map +1 -0
  335. package/dist/core/scene/types.js +6 -0
  336. package/dist/core/scene/types.js.map +1 -0
  337. package/dist/core/scene/useScene.js +32 -0
  338. package/dist/core/scene/useScene.js.map +1 -0
  339. package/dist/core/selection/chromeState.js +31 -0
  340. package/dist/core/selection/chromeState.js.map +1 -0
  341. package/dist/core/selection/selectionTarget.js +6 -0
  342. package/dist/core/selection/selectionTarget.js.map +1 -0
  343. package/dist/core/selection/useSelection.js +71 -0
  344. package/dist/core/selection/useSelection.js.map +1 -0
  345. package/dist/core/shapeKinds.js +54 -0
  346. package/dist/core/shapeKinds.js.map +1 -0
  347. package/dist/core/strokeMarkerShapes.js +139 -0
  348. package/dist/core/strokeMarkerShapes.js.map +1 -0
  349. package/dist/core/strokeMarkers.js +28 -0
  350. package/dist/core/strokeMarkers.js.map +1 -0
  351. package/dist/core/stylus/stylus.js +39 -0
  352. package/dist/core/stylus/stylus.js.map +1 -0
  353. package/dist/core/stylus/usePointerStylus.js +51 -0
  354. package/dist/core/stylus/usePointerStylus.js.map +1 -0
  355. package/dist/core/usePaintKinds.js +17 -0
  356. package/dist/core/usePaintKinds.js.map +1 -0
  357. package/dist/core/viewport/clampView.js +24 -0
  358. package/dist/core/viewport/clampView.js.map +1 -0
  359. package/dist/core/viewport/clientToWorld.js +8 -0
  360. package/dist/core/viewport/clientToWorld.js.map +1 -0
  361. package/dist/core/viewport/createVelocityTracker.js +39 -0
  362. package/dist/core/viewport/createVelocityTracker.js.map +1 -0
  363. package/dist/core/viewport/fitToBounds.js +18 -0
  364. package/dist/core/viewport/fitToBounds.js.map +1 -0
  365. package/dist/core/viewport/fitViewToBounds.js +36 -0
  366. package/dist/core/viewport/fitViewToBounds.js.map +1 -0
  367. package/dist/core/viewport/interpolateView.js +34 -0
  368. package/dist/core/viewport/interpolateView.js.map +1 -0
  369. package/dist/core/viewport/meanScale.js +8 -0
  370. package/dist/core/viewport/meanScale.js.map +1 -0
  371. package/dist/core/viewport/parallax.js +111 -0
  372. package/dist/core/viewport/parallax.js.map +1 -0
  373. package/dist/core/viewport/pxExtent.js +42 -0
  374. package/dist/core/viewport/pxExtent.js.map +1 -0
  375. package/dist/core/viewport/sceneNodeClientRect.js +18 -0
  376. package/dist/core/viewport/sceneNodeClientRect.js.map +1 -0
  377. package/dist/core/viewport/screenSlop.js +27 -0
  378. package/dist/core/viewport/screenSlop.js.map +1 -0
  379. package/dist/core/viewport/useAutoCenter.js +32 -0
  380. package/dist/core/viewport/useAutoCenter.js.map +1 -0
  381. package/dist/core/viewport/useCanvasSize.js +29 -0
  382. package/dist/core/viewport/useCanvasSize.js.map +1 -0
  383. package/dist/core/viewport/useDecayLoop.js +63 -0
  384. package/dist/core/viewport/useDecayLoop.js.map +1 -0
  385. package/dist/core/viewport/useVelocityTracker.js +10 -0
  386. package/dist/core/viewport/useVelocityTracker.js.map +1 -0
  387. package/dist/core/viewport/useViewAnimation.js +63 -0
  388. package/dist/core/viewport/useViewAnimation.js.map +1 -0
  389. package/dist/core/viewport/view.js +37 -0
  390. package/dist/core/viewport/view.js.map +1 -0
  391. package/dist/core/viewport/viewTransform.js +11 -0
  392. package/dist/core/viewport/viewTransform.js.map +1 -0
  393. package/dist/core/viewport/viewportWorldRect.js +13 -0
  394. package/dist/core/viewport/viewportWorldRect.js.map +1 -0
  395. package/dist/core/viewport/wheelHandler.js +30 -0
  396. package/dist/core/viewport/wheelHandler.js.map +1 -0
  397. package/dist/core/viewport/zoomAt.js +22 -0
  398. package/dist/core/viewport/zoomAt.js.map +1 -0
  399. package/dist/core/viewport/zoomBounds.js +20 -0
  400. package/dist/core/viewport/zoomBounds.js.map +1 -0
  401. package/dist/{pointSnapToGrid-7mCcm6qG.d.ts → cornerHandles-CDcZOV8h.d.ts} +54 -71
  402. package/dist/debug/createDebugOverlayLayer.js +358 -0
  403. package/dist/debug/createDebugOverlayLayer.js.map +1 -0
  404. package/dist/debug/createDebugSink.js +83 -0
  405. package/dist/debug/createDebugSink.js.map +1 -0
  406. package/dist/debug/defaultTheme.js +31 -0
  407. package/dist/debug/defaultTheme.js.map +1 -0
  408. package/dist/debug/flag.js +41 -0
  409. package/dist/debug/flag.js.map +1 -0
  410. package/dist/debug/frameStats.js +16 -0
  411. package/dist/debug/frameStats.js.map +1 -0
  412. package/dist/debug/parseDebugFlags.js +32 -0
  413. package/dist/debug/parseDebugFlags.js.map +1 -0
  414. package/dist/features/chrome-caps/buildChromeCtx.js +16 -0
  415. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -0
  416. package/dist/features/chrome-caps/conditions.js +36 -0
  417. package/dist/features/chrome-caps/conditions.js.map +1 -0
  418. package/dist/features/chrome-caps/defaults.js +26 -0
  419. package/dist/features/chrome-caps/defaults.js.map +1 -0
  420. package/dist/features/chrome-caps/index.js +7 -0
  421. package/dist/features/chrome-caps/resolve.js +23 -0
  422. package/dist/features/chrome-caps/resolve.js.map +1 -0
  423. package/dist/features/chrome-caps/useHoverTracking.js +27 -0
  424. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -0
  425. package/dist/features/cursor/paintedCursorLayer.js +60 -0
  426. package/dist/features/cursor/paintedCursorLayer.js.map +1 -0
  427. package/dist/features/focus/gateLayer.js +14 -0
  428. package/dist/features/focus/gateLayer.js.map +1 -0
  429. package/dist/features/focus/useCanvasFocus.js +29 -0
  430. package/dist/features/focus/useCanvasFocus.js.map +1 -0
  431. package/dist/features/groups/children.js +23 -0
  432. package/dist/features/groups/children.js.map +1 -0
  433. package/dist/features/groups/composePose.js +67 -0
  434. package/dist/features/groups/composePose.js.map +1 -0
  435. package/dist/features/groups/nestedHit.js +40 -0
  436. package/dist/features/groups/nestedHit.js.map +1 -0
  437. package/dist/features/groups/unionOfChildren.js +15 -0
  438. package/dist/features/groups/unionOfChildren.js.map +1 -0
  439. package/dist/features/images/imageCache.js +94 -0
  440. package/dist/features/images/imageCache.js.map +1 -0
  441. package/dist/features/ingestion/contentHandlers.js +37 -0
  442. package/dist/features/ingestion/contentHandlers.js.map +1 -0
  443. package/dist/features/ingestion/imageHandler.js +45 -0
  444. package/dist/features/ingestion/imageHandler.js.map +1 -0
  445. package/dist/features/ingestion/index.js +8 -0
  446. package/dist/features/ingestion/openFilePicker.js +15 -0
  447. package/dist/features/ingestion/openFilePicker.js.map +1 -0
  448. package/dist/features/ingestion/registerKitHandlers.js +26 -0
  449. package/dist/features/ingestion/registerKitHandlers.js.map +1 -0
  450. package/dist/features/ingestion/svgHandler.js +58 -0
  451. package/dist/features/ingestion/svgHandler.js.map +1 -0
  452. package/dist/features/ingestion/weaselJsonHandler.js +39 -0
  453. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -0
  454. package/dist/features/longPress/longPressFeedback.js +96 -0
  455. package/dist/features/longPress/longPressFeedback.js.map +1 -0
  456. package/dist/features/meshPaint/bake.js +79 -0
  457. package/dist/features/meshPaint/bake.js.map +1 -0
  458. package/dist/features/meshPaint/bakeCache.js +59 -0
  459. package/dist/features/meshPaint/bakeCache.js.map +1 -0
  460. package/dist/features/meshPaint/handles.js +86 -0
  461. package/dist/features/meshPaint/handles.js.map +1 -0
  462. package/dist/features/meshPaint/lazyKind.js +1298 -0
  463. package/dist/features/meshPaint/lazyKind.js.map +1 -0
  464. package/dist/features/meshPaint/meshPaint.js +236 -0
  465. package/dist/features/meshPaint/meshPaint.js.map +1 -0
  466. package/dist/features/meshPaint/meshShader.js +6 -0
  467. package/dist/features/meshPaint/meshShader.js.map +1 -0
  468. package/dist/features/meshPaint/register.js +7 -0
  469. package/dist/features/meshPaint/register.js.map +1 -0
  470. package/dist/features/meshPaint/surface.js +110 -0
  471. package/dist/features/meshPaint/surface.js.map +1 -0
  472. package/dist/features/minimap/actions.js +53 -0
  473. package/dist/features/minimap/actions.js.map +1 -0
  474. package/dist/features/minimap/createMinimapContribution.js +96 -0
  475. package/dist/features/minimap/createMinimapContribution.js.map +1 -0
  476. package/dist/features/minimap/layers.js +103 -0
  477. package/dist/features/minimap/layers.js.map +1 -0
  478. package/dist/features/modes/modeLayers.js +113 -0
  479. package/dist/features/modes/modeLayers.js.map +1 -0
  480. package/dist/features/overlays/useNodeOverlayFrame.js +103 -0
  481. package/dist/features/overlays/useNodeOverlayFrame.js.map +1 -0
  482. package/dist/features/parallax/createParallaxLayer.js +26 -0
  483. package/dist/features/parallax/createParallaxLayer.js.map +1 -0
  484. package/dist/features/parallax/createParallaxPlane.js +26 -0
  485. package/dist/features/parallax/createParallaxPlane.js.map +1 -0
  486. package/dist/features/paths/anchorEdits.js +156 -0
  487. package/dist/features/paths/anchorEdits.js.map +1 -0
  488. package/dist/features/paths/anchors.js +154 -0
  489. package/dist/features/paths/anchors.js.map +1 -0
  490. package/dist/features/paths/booleans.js +2 -0
  491. package/dist/features/paths/index.js +15 -0
  492. package/dist/features/paths/markerCommands.js +116 -0
  493. package/dist/features/paths/markerCommands.js.map +1 -0
  494. package/dist/features/paths/markerSites.js +59 -0
  495. package/dist/features/paths/markerSites.js.map +1 -0
  496. package/dist/features/paths/markers.js +95 -0
  497. package/dist/features/paths/markers.js.map +1 -0
  498. package/dist/features/paths/nearestAnchor.js +36 -0
  499. package/dist/features/paths/nearestAnchor.js.map +1 -0
  500. package/dist/features/paths/originProjection.js +16 -0
  501. package/dist/features/paths/originProjection.js.map +1 -0
  502. package/dist/features/paths/pathEditingOverlayLayer.js +137 -0
  503. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -0
  504. package/dist/features/paths/pathInWorld.js +41 -0
  505. package/dist/features/paths/pathInWorld.js.map +1 -0
  506. package/dist/features/paths/pathLayer.js +44 -0
  507. package/dist/features/paths/pathLayer.js.map +1 -0
  508. package/dist/features/paths/penPreviewLayer.js +220 -0
  509. package/dist/features/paths/penPreviewLayer.js.map +1 -0
  510. package/dist/features/paths/poseDescriptor.js +44 -0
  511. package/dist/features/paths/poseDescriptor.js.map +1 -0
  512. package/dist/features/paths/tessellate/stroke.js +230 -0
  513. package/dist/features/paths/tessellate/stroke.js.map +1 -0
  514. package/dist/features/patterns/index.js +23 -0
  515. package/dist/features/patterns/index.js.map +1 -0
  516. package/dist/features/patterns/patterns-builtin.js +38 -0
  517. package/dist/features/patterns/patterns-builtin.js.map +1 -0
  518. package/dist/features/patterns/resolveSpec.js +57 -0
  519. package/dist/features/patterns/resolveSpec.js.map +1 -0
  520. package/dist/features/patterns/tileGeometry.js +158 -0
  521. package/dist/features/patterns/tileGeometry.js.map +1 -0
  522. package/dist/features/pointer/PointerContext.js +45 -0
  523. package/dist/features/pointer/PointerContext.js.map +1 -0
  524. package/dist/features/poseRun/usePoseRun.js +70 -0
  525. package/dist/features/poseRun/usePoseRun.js.map +1 -0
  526. package/dist/features/selection/SelectionContext.js +46 -0
  527. package/dist/features/selection/SelectionContext.js.map +1 -0
  528. package/dist/features/selection/overlay.js +442 -0
  529. package/dist/features/selection/overlay.js.map +1 -0
  530. package/dist/features/simulation/createSimulation.js +61 -0
  531. package/dist/features/simulation/createSimulation.js.map +1 -0
  532. package/dist/features/simulation/types.js +6 -0
  533. package/dist/features/simulation/types.js.map +1 -0
  534. package/dist/features/simulation/useSimulation.js +74 -0
  535. package/dist/features/simulation/useSimulation.js.map +1 -0
  536. package/dist/features/text/domRuns.js +258 -0
  537. package/dist/features/text/domRuns.js.map +1 -0
  538. package/dist/features/text/fitTextPose.js +38 -0
  539. package/dist/features/text/fitTextPose.js.map +1 -0
  540. package/dist/features/text/hitTest.js +45 -0
  541. package/dist/features/text/hitTest.js.map +1 -0
  542. package/dist/features/text/renderLabel.js +14 -0
  543. package/dist/features/text/renderLabel.js.map +1 -0
  544. package/dist/features/text/runs/effectiveRangeStyle.js +66 -0
  545. package/dist/features/text/runs/effectiveRangeStyle.js.map +1 -0
  546. package/dist/features/text/runs/flagRange.js +53 -0
  547. package/dist/features/text/runs/flagRange.js.map +1 -0
  548. package/dist/features/text/runs/rangeStyle.js +135 -0
  549. package/dist/features/text/runs/rangeStyle.js.map +1 -0
  550. package/dist/features/text/textCommand.js +59 -0
  551. package/dist/features/text/textCommand.js.map +1 -0
  552. package/dist/features/text/textLayer.js +35 -0
  553. package/dist/features/text/textLayer.js.map +1 -0
  554. package/dist/features/text/textToPath.js +181 -0
  555. package/dist/features/text/textToPath.js.map +1 -0
  556. package/dist/features/text/useSceneTextEdit.js +138 -0
  557. package/dist/features/text/useSceneTextEdit.js.map +1 -0
  558. package/dist/features/text/useTextEdit.js +465 -0
  559. package/dist/features/text/useTextEdit.js.map +1 -0
  560. package/dist/features/tiling/createTiledLayer.js +63 -0
  561. package/dist/features/tiling/createTiledLayer.js.map +1 -0
  562. package/dist/features/tiling/tiledProject.js +14 -0
  563. package/dist/features/tiling/tiledProject.js.map +1 -0
  564. package/dist/features/viewports/viewResolver.js +59 -0
  565. package/dist/features/viewports/viewResolver.js.map +1 -0
  566. package/dist/features/viewports/viewportLayer.js +58 -0
  567. package/dist/features/viewports/viewportLayer.js.map +1 -0
  568. package/dist/icons/ArrowIcon.js +23 -0
  569. package/dist/icons/ArrowIcon.js.map +1 -0
  570. package/dist/icons/EllipseIcon.js +21 -0
  571. package/dist/icons/EllipseIcon.js.map +1 -0
  572. package/dist/icons/EyedropperIcon.js +49 -0
  573. package/dist/icons/EyedropperIcon.js.map +1 -0
  574. package/dist/icons/HandIcon.js +59 -0
  575. package/dist/icons/HandIcon.js.map +1 -0
  576. package/dist/icons/ImageIcon.js +34 -0
  577. package/dist/icons/ImageIcon.js.map +1 -0
  578. package/dist/icons/LassoIcon.js +22 -0
  579. package/dist/icons/LassoIcon.js.map +1 -0
  580. package/dist/icons/LineIcon.js +22 -0
  581. package/dist/icons/LineIcon.js.map +1 -0
  582. package/dist/icons/PenIcon.js +36 -0
  583. package/dist/icons/PenIcon.js.map +1 -0
  584. package/dist/icons/PencilIcon.js +25 -0
  585. package/dist/icons/PencilIcon.js.map +1 -0
  586. package/dist/icons/PolygonIcon.js +19 -0
  587. package/dist/icons/PolygonIcon.js.map +1 -0
  588. package/dist/icons/RectIcon.js +37 -0
  589. package/dist/icons/RectIcon.js.map +1 -0
  590. package/dist/icons/SelectIcon.js +20 -0
  591. package/dist/icons/SelectIcon.js.map +1 -0
  592. package/dist/icons/StarIcon.js +19 -0
  593. package/dist/icons/StarIcon.js.map +1 -0
  594. package/dist/icons/TextIcon.js +19 -0
  595. package/dist/icons/TextIcon.js.map +1 -0
  596. package/dist/icons/UnknownIcon.js +33 -0
  597. package/dist/icons/UnknownIcon.js.map +1 -0
  598. package/dist/icons/_base.js +12 -0
  599. package/dist/icons/_base.js.map +1 -0
  600. package/dist/index.css +2 -86
  601. package/dist/index.d.ts +2349 -2609
  602. package/dist/index.js +312 -13
  603. package/dist/input/keyState.js +76 -0
  604. package/dist/input/keyState.js.map +1 -0
  605. package/dist/input/useKeyState.js +22 -0
  606. package/dist/input/useKeyState.js.map +1 -0
  607. package/dist/interactions/actions/actionShortcuts.js +32 -0
  608. package/dist/interactions/actions/actionShortcuts.js.map +1 -0
  609. package/dist/interactions/actions/align/align.js +81 -0
  610. package/dist/interactions/actions/align/align.js.map +1 -0
  611. package/dist/interactions/actions/booleans/booleans.js +120 -0
  612. package/dist/interactions/actions/booleans/booleans.js.map +1 -0
  613. package/dist/interactions/actions/booleans/useBooleans.js +20 -0
  614. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -0
  615. package/dist/interactions/actions/booleans/useBooleansAdapter.js +9 -0
  616. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -0
  617. package/dist/interactions/actions/clipboard/clipboardOps.js +94 -0
  618. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -0
  619. package/dist/interactions/actions/clipboard/materializePaste.js +25 -0
  620. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -0
  621. package/dist/interactions/actions/clipboard/wireFormat.js +43 -0
  622. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -0
  623. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +26 -0
  624. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +1 -0
  625. package/dist/interactions/actions/defaultCommitAdapter.js +42 -0
  626. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -0
  627. package/dist/interactions/actions/defaults/align.js +71 -0
  628. package/dist/interactions/actions/defaults/align.js.map +1 -0
  629. package/dist/interactions/actions/defaults/anchorEditing.js +235 -0
  630. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -0
  631. package/dist/interactions/actions/defaults/areaSelect.js +75 -0
  632. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -0
  633. package/dist/interactions/actions/defaults/booleans.js +52 -0
  634. package/dist/interactions/actions/defaults/booleans.js.map +1 -0
  635. package/dist/interactions/actions/defaults/cancelGesture.js +24 -0
  636. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -0
  637. package/dist/interactions/actions/defaults/clearSelection.js +19 -0
  638. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -0
  639. package/dist/interactions/actions/defaults/clipboard.js +78 -0
  640. package/dist/interactions/actions/defaults/clipboard.js.map +1 -0
  641. package/dist/interactions/actions/defaults/clone.js +96 -0
  642. package/dist/interactions/actions/defaults/clone.js.map +1 -0
  643. package/dist/interactions/actions/defaults/createOutlines.js +47 -0
  644. package/dist/interactions/actions/defaults/createOutlines.js.map +1 -0
  645. package/dist/interactions/actions/defaults/createPaintAction.js +85 -0
  646. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -0
  647. package/dist/interactions/actions/defaults/delete.js +61 -0
  648. package/dist/interactions/actions/defaults/delete.js.map +1 -0
  649. package/dist/interactions/actions/defaults/distribute.js +66 -0
  650. package/dist/interactions/actions/defaults/distribute.js.map +1 -0
  651. package/dist/interactions/actions/defaults/duplicate.js +83 -0
  652. package/dist/interactions/actions/defaults/duplicate.js.map +1 -0
  653. package/dist/interactions/actions/defaults/editAnchors.js +100 -0
  654. package/dist/interactions/actions/defaults/editAnchors.js.map +1 -0
  655. package/dist/interactions/actions/defaults/enterPathEdit.js +29 -0
  656. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -0
  657. package/dist/interactions/actions/defaults/enterTextEdit.js +20 -0
  658. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -0
  659. package/dist/interactions/actions/defaults/escape.js +26 -0
  660. package/dist/interactions/actions/defaults/escape.js.map +1 -0
  661. package/dist/interactions/actions/defaults/exitPathEdit.js +22 -0
  662. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -0
  663. package/dist/interactions/actions/defaults/flip.js +119 -0
  664. package/dist/interactions/actions/defaults/flip.js.map +1 -0
  665. package/dist/interactions/actions/defaults/freshNodeId.js +10 -0
  666. package/dist/interactions/actions/defaults/freshNodeId.js.map +1 -0
  667. package/dist/interactions/actions/defaults/group.js +131 -0
  668. package/dist/interactions/actions/defaults/group.js.map +1 -0
  669. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +40 -0
  670. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +1 -0
  671. package/dist/interactions/actions/defaults/icons/actionGlyphs.js +10 -0
  672. package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +1 -0
  673. package/dist/interactions/actions/defaults/icons/alignIcons.js +173 -0
  674. package/dist/interactions/actions/defaults/icons/alignIcons.js.map +1 -0
  675. package/dist/interactions/actions/defaults/icons/booleanIcons.js +171 -0
  676. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -0
  677. package/dist/interactions/actions/defaults/icons/distributeIcons.js +63 -0
  678. package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +1 -0
  679. package/dist/interactions/actions/defaults/icons/editIcons.js +280 -0
  680. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -0
  681. package/dist/interactions/actions/defaults/icons/outlineIcons.js +53 -0
  682. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -0
  683. package/dist/interactions/actions/defaults/ingest.js +58 -0
  684. package/dist/interactions/actions/defaults/ingest.js.map +1 -0
  685. package/dist/interactions/actions/defaults/insert.js +288 -0
  686. package/dist/interactions/actions/defaults/insert.js.map +1 -0
  687. package/dist/interactions/actions/defaults/insertPathAnchor.js +50 -0
  688. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -0
  689. package/dist/interactions/actions/defaults/lassoSelect.js +156 -0
  690. package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -0
  691. package/dist/interactions/actions/defaults/move.js +656 -0
  692. package/dist/interactions/actions/defaults/move.js.map +1 -0
  693. package/dist/interactions/actions/defaults/nudge.js +110 -0
  694. package/dist/interactions/actions/defaults/nudge.js.map +1 -0
  695. package/dist/interactions/actions/defaults/pinchZoom.js +63 -0
  696. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -0
  697. package/dist/interactions/actions/defaults/reorder.js +143 -0
  698. package/dist/interactions/actions/defaults/reorder.js.map +1 -0
  699. package/dist/interactions/actions/defaults/requiresSelection.js +10 -0
  700. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -0
  701. package/dist/interactions/actions/defaults/resize.js +332 -0
  702. package/dist/interactions/actions/defaults/resize.js.map +1 -0
  703. package/dist/interactions/actions/defaults/rotate.js +181 -0
  704. package/dist/interactions/actions/defaults/rotate.js.map +1 -0
  705. package/dist/interactions/actions/defaults/selectAll.js +27 -0
  706. package/dist/interactions/actions/defaults/selectAll.js.map +1 -0
  707. package/dist/interactions/actions/defaults/setFill.js +27 -0
  708. package/dist/interactions/actions/defaults/setFill.js.map +1 -0
  709. package/dist/interactions/actions/defaults/setFillOpacity.js +15 -0
  710. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -0
  711. package/dist/interactions/actions/defaults/setStroke.js +36 -0
  712. package/dist/interactions/actions/defaults/setStroke.js.map +1 -0
  713. package/dist/interactions/actions/defaults/setStrokeOpacity.js +21 -0
  714. package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -0
  715. package/dist/interactions/actions/defaults/slice.js +39 -0
  716. package/dist/interactions/actions/defaults/slice.js.map +1 -0
  717. package/dist/interactions/actions/defaults/sliceOps.js +60 -0
  718. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -0
  719. package/dist/interactions/actions/defaults/toolActivate.js +35 -0
  720. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -0
  721. package/dist/interactions/actions/defaults/toolResetToDefault.js +26 -0
  722. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -0
  723. package/dist/interactions/actions/defaults/undoRedo.js +51 -0
  724. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -0
  725. package/dist/interactions/actions/defaults/viewportDragPan.js +88 -0
  726. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -0
  727. package/dist/interactions/actions/defaults/viewportWheelPan.js +57 -0
  728. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -0
  729. package/dist/interactions/actions/defaults/viewportZoom.js +143 -0
  730. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -0
  731. package/dist/interactions/actions/distribute/distribute.js +42 -0
  732. package/dist/interactions/actions/distribute/distribute.js.map +1 -0
  733. package/dist/interactions/actions/distribute/plan.js +29 -0
  734. package/dist/interactions/actions/distribute/plan.js.map +1 -0
  735. package/dist/interactions/actions/edit-anchors/geometry.js +61 -0
  736. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -0
  737. package/dist/interactions/actions/edit-anchors/handles.js +43 -0
  738. package/dist/interactions/actions/edit-anchors/handles.js.map +1 -0
  739. package/dist/interactions/actions/flip/helpers.js +35 -0
  740. package/dist/interactions/actions/flip/helpers.js.map +1 -0
  741. package/dist/interactions/actions/geometryProjection.js +18 -0
  742. package/dist/interactions/actions/geometryProjection.js.map +1 -0
  743. package/dist/interactions/actions/gestureLifecycle.js +44 -0
  744. package/dist/interactions/actions/gestureLifecycle.js.map +1 -0
  745. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +39 -0
  746. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -0
  747. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +36 -0
  748. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -0
  749. package/dist/interactions/actions/move/behaviors/snapToContainer.js +67 -0
  750. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -0
  751. package/dist/interactions/actions/move/gestureAdapter.js +37 -0
  752. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -0
  753. package/dist/interactions/actions/outlines/createOutlines.js +84 -0
  754. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -0
  755. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +9 -0
  756. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -0
  757. package/dist/interactions/actions/planeInput.js +168 -0
  758. package/dist/interactions/actions/planeInput.js.map +1 -0
  759. package/dist/interactions/actions/poseDescriptorDep.js +9 -0
  760. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -0
  761. package/dist/interactions/actions/poseFrame.js +38 -0
  762. package/dist/interactions/actions/poseFrame.js.map +1 -0
  763. package/dist/interactions/actions/previewOverrides.js +25 -0
  764. package/dist/interactions/actions/previewOverrides.js.map +1 -0
  765. package/dist/interactions/actions/resize/autoPoseDescriptor.js +32 -0
  766. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +1 -0
  767. package/dist/interactions/actions/resize/behaviors/clampMinSize.js +18 -0
  768. package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -0
  769. package/dist/interactions/actions/resize/behaviors/index.js +8 -0
  770. package/dist/interactions/actions/resize/behaviors/index.js.map +1 -0
  771. package/dist/interactions/actions/resize/behaviors/lockAspect.js +24 -0
  772. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -0
  773. package/dist/interactions/actions/resize/cornerHandles.js +72 -0
  774. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -0
  775. package/dist/interactions/actions/resolveOverlays.js +60 -0
  776. package/dist/interactions/actions/resolveOverlays.js.map +1 -0
  777. package/dist/interactions/actions/resolvePreviews.js +61 -0
  778. package/dist/interactions/actions/resolvePreviews.js.map +1 -0
  779. package/dist/interactions/actions/rotate/geometry.js +46 -0
  780. package/dist/interactions/actions/rotate/geometry.js.map +1 -0
  781. package/dist/interactions/actions/rotate/handle.js +27 -0
  782. package/dist/interactions/actions/rotate/handle.js.map +1 -0
  783. package/dist/interactions/actions/spatialReference.js +42 -0
  784. package/dist/interactions/actions/spatialReference.js.map +1 -0
  785. package/dist/interactions/actions/useStandardActions.js +142 -0
  786. package/dist/interactions/actions/useStandardActions.js.map +1 -0
  787. package/dist/interactions/gestures/dragGesture/dragGesture.js +111 -0
  788. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -0
  789. package/dist/interactions/gestures/dragRadial/dragRadial.js +117 -0
  790. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -0
  791. package/dist/interactions/gestures/dragRect/dragRect.js +164 -0
  792. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -0
  793. package/dist/interactions/gestures/handleDrag/handleDrag.js +46 -0
  794. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -0
  795. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +118 -0
  796. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -0
  797. package/dist/interactions/gestures/shared/originProjection.js +42 -0
  798. package/dist/interactions/gestures/shared/originProjection.js.map +1 -0
  799. package/dist/interactions/gestures/shared/screenTolerance.js +21 -0
  800. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -0
  801. package/dist/interactions/gestures/shared/snap.js +24 -0
  802. package/dist/interactions/gestures/shared/snap.js.map +1 -0
  803. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +30 -0
  804. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -0
  805. package/dist/layout/arrivals.js +36 -0
  806. package/dist/layout/arrivals.js.map +1 -0
  807. package/dist/{math-MCQcf_gc.d.ts → math-CUMxmZzn.d.ts} +8 -116
  808. package/dist/math.d.ts +4 -5
  809. package/dist/math.js +6 -4
  810. package/dist/mesh.d.ts +268 -0
  811. package/dist/mesh.js +7 -0
  812. package/dist/move.d.ts +7 -48
  813. package/dist/move.js +3 -142
  814. package/dist/originProjection-BSn4xiEy.d.ts +57 -0
  815. package/dist/patterns-builtin.js +3 -3
  816. package/dist/{poseDescriptor-rZa9W5hJ.d.ts → poseDescriptor-CjSXMf8X.d.ts} +3 -3
  817. package/dist/registerProgram-ateHDGjw.d.ts +193 -0
  818. package/dist/renderer/DrawCommand.js +6 -0
  819. package/dist/renderer/DrawCommand.js.map +1 -0
  820. package/dist/renderer/WeaselRenderer.js +328 -0
  821. package/dist/renderer/WeaselRenderer.js.map +1 -0
  822. package/dist/renderer/cache/GLImageCache.js +64 -0
  823. package/dist/renderer/cache/GLImageCache.js.map +1 -0
  824. package/dist/renderer/cache/GLMeshCache.js +102 -0
  825. package/dist/renderer/cache/GLMeshCache.js.map +1 -0
  826. package/dist/renderer/cache/GLTextureCache.js +51 -0
  827. package/dist/renderer/cache/GLTextureCache.js.map +1 -0
  828. package/dist/renderer/cache/GradientRampAtlas.js +82 -0
  829. package/dist/renderer/cache/GradientRampAtlas.js.map +1 -0
  830. package/dist/renderer/cache/cache.js +13 -0
  831. package/dist/renderer/cache/cache.js.map +1 -0
  832. package/dist/renderer/cache/markerCommandCache.js +59 -0
  833. package/dist/renderer/cache/markerCommandCache.js.map +1 -0
  834. package/dist/renderer/cache/outlineMeshCache.js +15 -0
  835. package/dist/renderer/cache/outlineMeshCache.js.map +1 -0
  836. package/dist/renderer/cache/outlineStrokeMeshCache.js +31 -0
  837. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +1 -0
  838. package/dist/renderer/cache/strokeMeshCache.js +44 -0
  839. package/dist/renderer/cache/strokeMeshCache.js.map +1 -0
  840. package/dist/renderer/cullDrawCommands.js +89 -0
  841. package/dist/renderer/cullDrawCommands.js.map +1 -0
  842. package/dist/renderer/draw.js +1109 -0
  843. package/dist/renderer/draw.js.map +1 -0
  844. package/dist/renderer/drawBatch.js +168 -0
  845. package/dist/renderer/drawBatch.js.map +1 -0
  846. package/dist/renderer/effects/EffectTargets.js +45 -0
  847. package/dist/renderer/effects/EffectTargets.js.map +1 -0
  848. package/dist/renderer/effects/builtins.js +31 -0
  849. package/dist/renderer/effects/builtins.js.map +1 -0
  850. package/dist/renderer/effects/composite.js +9 -0
  851. package/dist/renderer/effects/composite.js.map +1 -0
  852. package/dist/renderer/effects/effectPrelude.js +10 -0
  853. package/dist/renderer/effects/effectPrelude.js.map +1 -0
  854. package/dist/renderer/effects/types.js +10 -0
  855. package/dist/renderer/effects/types.js.map +1 -0
  856. package/dist/renderer/index.js +19 -0
  857. package/dist/renderer/math/color.js +341 -0
  858. package/dist/renderer/math/color.js.map +1 -0
  859. package/dist/renderer/math/mat3.js +71 -0
  860. package/dist/renderer/math/mat3.js.map +1 -0
  861. package/dist/renderer/math/patternSpace.js +22 -0
  862. package/dist/renderer/math/patternSpace.js.map +1 -0
  863. package/dist/renderer/math/viewToMat3.js +19 -0
  864. package/dist/renderer/math/viewToMat3.js.map +1 -0
  865. package/dist/renderer/paintResources.js +18 -0
  866. package/dist/renderer/paintResources.js.map +1 -0
  867. package/dist/renderer/paintScratch.js +37 -0
  868. package/dist/renderer/paintScratch.js.map +1 -0
  869. package/dist/renderer/shaders/ShaderProgram.js +74 -0
  870. package/dist/renderer/shaders/ShaderProgram.js.map +1 -0
  871. package/dist/renderer/shaders/batchFill.js +118 -0
  872. package/dist/renderer/shaders/batchFill.js.map +1 -0
  873. package/dist/renderer/shaders/customPrelude.js +34 -0
  874. package/dist/renderer/shaders/customPrelude.js.map +1 -0
  875. package/dist/renderer/shaders/extractUniformNames.js +184 -0
  876. package/dist/renderer/shaders/extractUniformNames.js.map +1 -0
  877. package/dist/renderer/shaders/glyphPaint.js +61 -0
  878. package/dist/renderer/shaders/glyphPaint.js.map +1 -0
  879. package/dist/renderer/shaders/gradFill.js +30 -0
  880. package/dist/renderer/shaders/gradFill.js.map +1 -0
  881. package/dist/renderer/shaders/imageFill.js +14 -0
  882. package/dist/renderer/shaders/imageFill.js.map +1 -0
  883. package/dist/renderer/shaders/pathFill.js +13 -0
  884. package/dist/renderer/shaders/pathFill.js.map +1 -0
  885. package/dist/renderer/shaders/patternFill.js +24 -0
  886. package/dist/renderer/shaders/patternFill.js.map +1 -0
  887. package/dist/renderer/shaders/registerProgram.js +18 -0
  888. package/dist/renderer/shaders/registerProgram.js.map +1 -0
  889. package/dist/renderer/spriteSheet.js +14 -0
  890. package/dist/renderer/spriteSheet.js.map +1 -0
  891. package/dist/renderer/state/GroupState.js +77 -0
  892. package/dist/renderer/state/GroupState.js.map +1 -0
  893. package/dist/renderer/syntheticItalic.js +6 -0
  894. package/dist/renderer/syntheticItalic.js.map +1 -0
  895. package/dist/renderer/textures/registerTexture.js +14 -0
  896. package/dist/renderer/textures/registerTexture.js.map +1 -0
  897. package/dist/renderer.d.ts +18 -20
  898. package/dist/renderer.js +18 -13
  899. package/dist/resize.d.ts +10 -46
  900. package/dist/resize.js +7 -5
  901. package/dist/routing.d.ts +1 -1
  902. package/dist/routing.js +2 -3
  903. package/dist/scheduling/useVisibleRaf.js +69 -0
  904. package/dist/scheduling/useVisibleRaf.js.map +1 -0
  905. package/dist/test-hook/createTestHook.js +39 -0
  906. package/dist/test-hook/createTestHook.js.map +1 -0
  907. package/dist/test-hook/install.js +12 -0
  908. package/dist/test-hook/install.js.map +1 -0
  909. package/dist/test-seams-fYf6m5pu.d.ts +356 -0
  910. package/dist/test-seams.d.ts +6 -0
  911. package/dist/test-seams.js +3 -0
  912. package/dist/tools/builtin/ellipse/useEllipseTool.js +33 -0
  913. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -0
  914. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +55 -0
  915. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -0
  916. package/dist/tools/builtin/hand/dragPanContribution.js +17 -0
  917. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -0
  918. package/dist/tools/builtin/hand/useHandTool.js +31 -0
  919. package/dist/tools/builtin/hand/useHandTool.js.map +1 -0
  920. package/dist/tools/builtin/image/useImageTool.js +41 -0
  921. package/dist/tools/builtin/image/useImageTool.js.map +1 -0
  922. package/dist/tools/builtin/lasso/useLassoTool.js +42 -0
  923. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -0
  924. package/dist/tools/builtin/line/useLineTool.js +33 -0
  925. package/dist/tools/builtin/line/useLineTool.js.map +1 -0
  926. package/dist/tools/builtin/pen/usePenTool.js +414 -0
  927. package/dist/tools/builtin/pen/usePenTool.js.map +1 -0
  928. package/dist/tools/builtin/pencil/usePencilTool.js +36 -0
  929. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -0
  930. package/dist/tools/builtin/pickTopMostHit.js +45 -0
  931. package/dist/tools/builtin/pickTopMostHit.js.map +1 -0
  932. package/dist/tools/builtin/polygon/usePolygonTool.js +81 -0
  933. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -0
  934. package/dist/tools/builtin/rect/useRectTool.js +32 -0
  935. package/dist/tools/builtin/rect/useRectTool.js.map +1 -0
  936. package/dist/tools/builtin/select/selectionContributions.js +109 -0
  937. package/dist/tools/builtin/select/selectionContributions.js.map +1 -0
  938. package/dist/tools/builtin/select/useSelectTool.js +162 -0
  939. package/dist/tools/builtin/select/useSelectTool.js.map +1 -0
  940. package/dist/tools/builtin/shared/insertToolOptions.js +8 -0
  941. package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -0
  942. package/dist/tools/builtin/slice/useSliceTool.js +263 -0
  943. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -0
  944. package/dist/tools/builtin/star/useStarTool.js +82 -0
  945. package/dist/tools/builtin/star/useStarTool.js.map +1 -0
  946. package/dist/tools/builtin/text/useTextTool.js +177 -0
  947. package/dist/tools/builtin/text/useTextTool.js.map +1 -0
  948. package/dist/tools/overlayBinding.js +8 -0
  949. package/dist/tools/overlayBinding.js.map +1 -0
  950. package/dist/tools/prefs.js +47 -0
  951. package/dist/tools/prefs.js.map +1 -0
  952. package/dist/tools/useKeybindings.js +66 -0
  953. package/dist/tools/useKeybindings.js.map +1 -0
  954. package/dist/{types-CxC8P6W0.d.ts → types-CA54-mAZ.d.ts} +188 -17
  955. package/dist/{types-D_74YlWs.d.ts → types-DSjd6W3n.d.ts} +35 -12
  956. package/dist/util/color.js +26 -0
  957. package/dist/util/color.js.map +1 -0
  958. package/dist/util/constrainTo45.js +17 -0
  959. package/dist/util/constrainTo45.js.map +1 -0
  960. package/dist/util/paint.js +72 -0
  961. package/dist/util/paint.js.map +1 -0
  962. package/dist/version.js +6 -0
  963. package/dist/version.js.map +1 -0
  964. package/package.json +31 -18
  965. package/dist/chunk-44EWMJV2.js +0 -128
  966. package/dist/chunk-44EWMJV2.js.map +0 -1
  967. package/dist/chunk-4RJP2N2L.js +0 -143
  968. package/dist/chunk-4RJP2N2L.js.map +0 -1
  969. package/dist/chunk-BJN5ZRIJ.js +0 -167
  970. package/dist/chunk-BJN5ZRIJ.js.map +0 -1
  971. package/dist/chunk-D4AAWR64.js +0 -28
  972. package/dist/chunk-D4AAWR64.js.map +0 -1
  973. package/dist/chunk-DOBSZOPR.js +0 -29
  974. package/dist/chunk-DOBSZOPR.js.map +0 -1
  975. package/dist/chunk-H6N2JSZ3.js +0 -248
  976. package/dist/chunk-H6N2JSZ3.js.map +0 -1
  977. package/dist/chunk-HPFJUUTF.js +0 -167
  978. package/dist/chunk-HPFJUUTF.js.map +0 -1
  979. package/dist/chunk-L5YNZYEG.js +0 -648
  980. package/dist/chunk-L5YNZYEG.js.map +0 -1
  981. package/dist/chunk-MZAIDI6D.js +0 -32492
  982. package/dist/chunk-MZAIDI6D.js.map +0 -1
  983. package/dist/chunk-PNNZSYRD.js +0 -318
  984. package/dist/chunk-PNNZSYRD.js.map +0 -1
  985. package/dist/chunk-RMR4QMM6.js +0 -250
  986. package/dist/chunk-RMR4QMM6.js.map +0 -1
  987. package/dist/clipboard.js.map +0 -1
  988. package/dist/clone.js.map +0 -1
  989. package/dist/grid-BXdz8GF2.d.ts +0 -158
  990. package/dist/index.css.map +0 -1
  991. package/dist/index.js.map +0 -1
  992. package/dist/insert.d.ts +0 -37
  993. package/dist/insert.js +0 -81
  994. package/dist/insert.js.map +0 -1
  995. package/dist/math.js.map +0 -1
  996. package/dist/move.js.map +0 -1
  997. package/dist/options-CzjxFoYZ.d.ts +0 -67
  998. package/dist/path-JEV2c5If.d.ts +0 -48
  999. package/dist/patterns-builtin.js.map +0 -1
  1000. package/dist/renderer.css +0 -86
  1001. package/dist/renderer.css.map +0 -1
  1002. package/dist/renderer.js.map +0 -1
  1003. package/dist/resize.js.map +0 -1
  1004. package/dist/routing.js.map +0 -1
  1005. package/dist/types-D2tTKEU0.d.ts +0 -18
@@ -0,0 +1,64 @@
1
+ //#region src/renderer/cache/GLImageCache.ts
2
+ var e = 4096, t = /* @__PURE__ */ new Set();
3
+ function n(e) {
4
+ for (let n of t) n.release(e);
5
+ }
6
+ function r() {
7
+ let n = Infinity;
8
+ for (let e of t) n = Math.min(n, e.maxTextureSide);
9
+ return Number.isFinite(n) ? n : e;
10
+ }
11
+ var i = class {
12
+ gl;
13
+ minification;
14
+ maxTextureSide;
15
+ map = /* @__PURE__ */ new WeakMap();
16
+ textures = /* @__PURE__ */ new Set();
17
+ magFilters = /* @__PURE__ */ new WeakMap();
18
+ constructor(n, r = "linear") {
19
+ this.gl = n, this.minification = r;
20
+ let i = n.getParameter(n.MAX_TEXTURE_SIZE);
21
+ this.maxTextureSide = typeof i == "number" && i > 0 ? i : e, t.add(this);
22
+ }
23
+ release(e) {
24
+ let t = this.map.get(e);
25
+ t && (this.gl.deleteTexture(t), this.textures.delete(t), this.map.delete(e), this.magFilters.delete(e));
26
+ }
27
+ dispose() {
28
+ for (let e of this.textures) this.gl.deleteTexture(e);
29
+ this.abandon();
30
+ }
31
+ abandon() {
32
+ this.textures.clear(), t.delete(this);
33
+ }
34
+ upload(e, t, n) {
35
+ let r = this.map.get(e);
36
+ if (r) return r;
37
+ let i = this.gl, o = i.createTexture();
38
+ if (!o) throw Error("GLImageCache: createTexture failed");
39
+ i.bindTexture(i.TEXTURE_2D, o), i.texImage2D(i.TEXTURE_2D, 0, i.RGBA, i.RGBA, i.UNSIGNED_BYTE, t), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MIN_FILTER, this.minification === "mipmap" ? i.LINEAR_MIPMAP_LINEAR : i.LINEAR), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MAG_FILTER, i.LINEAR), this.magFilters.set(e, i.LINEAR);
40
+ let [s, c] = a(i, n);
41
+ return i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_S, s), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_T, c), this.minification === "mipmap" && i.generateMipmap(i.TEXTURE_2D), i.bindTexture(i.TEXTURE_2D, null), this.map.set(e, o), this.textures.add(o), o;
42
+ }
43
+ bind(e, t) {
44
+ let n = this.map.get(e);
45
+ if (!n) throw Error("GLImageCache: image not uploaded; call upload() first");
46
+ let r = this.gl;
47
+ r.activeTexture(r.TEXTURE0 + t), r.bindTexture(r.TEXTURE_2D, n);
48
+ }
49
+ setMagFilter(e, t) {
50
+ this.magFilters.get(e) !== t && (this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, t), this.magFilters.set(e, t));
51
+ }
52
+ };
53
+ function a(e, t) {
54
+ switch (t) {
55
+ case "repeat": return [e.REPEAT, e.REPEAT];
56
+ case "repeat-x": return [e.REPEAT, e.CLAMP_TO_EDGE];
57
+ case "repeat-y": return [e.CLAMP_TO_EDGE, e.REPEAT];
58
+ default: return [e.CLAMP_TO_EDGE, e.CLAMP_TO_EDGE];
59
+ }
60
+ }
61
+ //#endregion
62
+ export { i as GLImageCache, r as maxImageTextureSide, n as releaseImageSource };
63
+
64
+ //# sourceMappingURL=GLImageCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GLImageCache.js","names":["DEFAULT_MAX_TEXTURE_SIDE","live","releaseImageSource","cache","key","maxImageTextureSide","side","GLImageCache","gl","minification","reported","tex","existing","source","wrapS","wrapT","wrapModes","repetition","unit","filter","rep"],"sources":["../../../src/renderer/cache/GLImageCache.ts"],"sourcesContent":["/**\n * GL texture upload cache for ImageBitmap objects.\n *\n * Key: ImageBitmap (or pattern source object) identity (WeakMap) — lets GC\n * reclaim unreferenced bitmaps. The GL textures are NOT freed when the source\n * is gc'd; a source's owner that knows it will never be drawn again frees them\n * with {@link releaseImageSource}, and `dispose` frees them all.\n *\n * Wrapping is set once at upload time per the `repetition` parameter:\n * - undefined / 'no-repeat' → CLAMP_TO_EDGE\n * - 'repeat' → REPEAT (both axes)\n * - 'repeat-x' → REPEAT on S, CLAMP on T\n * - 'repeat-y' → CLAMP on S, REPEAT on T\n *\n * Convention §2: texels stored straight; shader premultiplies.\n */\n\nexport type PatternRepetition = 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';\n\n/** MIN_FILTER strategy for uploaded textures. */\nexport type ImageMinification = 'linear' | 'mipmap';\n\ntype TexSource = ImageBitmap | ImageData | HTMLCanvasElement | HTMLImageElement;\n\n/** Assumed when no live context has reported its `MAX_TEXTURE_SIZE`. Above\n * WebGL2's guaranteed 2048, and at or below what every current GPU reports. */\nconst DEFAULT_MAX_TEXTURE_SIDE = 4096;\n\nconst live = new Set<GLImageCache>();\n\n/** Free `key`'s texture in every live renderer. For an owner that has replaced\n * a source and will never draw the old one again — a later draw of it simply\n * re-uploads. */\nexport function releaseImageSource(key: object): void {\n for (const cache of live) cache.release(key);\n}\n\n/** The largest texture side every live renderer can hold: the smallest\n * `MAX_TEXTURE_SIZE` among them, or a conservative default when none is live. */\nexport function maxImageTextureSide(): number {\n let side = Infinity;\n for (const cache of live) side = Math.min(side, cache.maxTextureSide);\n return Number.isFinite(side) ? side : DEFAULT_MAX_TEXTURE_SIDE;\n}\n\nexport class GLImageCache {\n /** This context's `MAX_TEXTURE_SIZE`. */\n readonly maxTextureSide: number;\n\n private readonly map = new WeakMap<object, WebGLTexture>();\n /** Every texture `map` holds, so `dispose` can reach them — a WeakMap\n * cannot be enumerated. */\n private readonly textures = new Set<WebGLTexture>();\n /**\n * MAG_FILTER each texture currently carries, so a redundant write can be\n * skipped.\n *\n * The batch sets this per flush — the same bitmap can be drawn at both\n * filters in one frame, and the value has to be right at the draw rather than\n * at upload. Filtering is state on the *texture object*, though, not on the\n * unit, so re-asserting a value it already has is a write to a live texture\n * for no reason. On a large sheet that is not free: a consumer's wall samples\n * a 5652px-square atlas, 122MB resident, and measured `sampling: 'nearest'`\n * costing up to 8x `'linear'` there — where the linear pass re-asserts the\n * upload default and the nearest pass changes state on every draw.\n *\n * Whether that is the cause is unproven (see `docs/TODO.md`), but the write\n * was redundant either way.\n */\n private readonly magFilters = new WeakMap<object, number>();\n\n /** `minification` selects the MIN_FILTER strategy for uploaded textures.\n * `'linear'` (default) is the screen path's existing behavior. `'mipmap'`\n * generates mipmaps and filters LINEAR_MIPMAP_LINEAR — required for\n * quality minification when a large source bitmap is drawn small (the\n * headless print/export path); bilinear-only minification undersamples\n * and produces moiré. */\n constructor(\n private readonly gl: WebGL2RenderingContext,\n private readonly minification: ImageMinification = 'linear',\n ) {\n const reported: unknown = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n this.maxTextureSide = typeof reported === 'number' && reported > 0\n ? reported\n : DEFAULT_MAX_TEXTURE_SIDE;\n live.add(this);\n }\n\n /** Delete `key`'s texture, if it has one. */\n release(key: object): void {\n const tex = this.map.get(key);\n if (!tex) return;\n this.gl.deleteTexture(tex);\n this.textures.delete(tex);\n this.map.delete(key);\n this.magFilters.delete(key);\n }\n\n /** Delete every texture this cache uploaded and stop answering\n * {@link releaseImageSource} and {@link maxImageTextureSide}. Idempotent. */\n dispose(): void {\n for (const tex of this.textures) this.gl.deleteTexture(tex);\n this.abandon();\n }\n\n /** {@link dispose} without the deletes, for a cache whose context was lost:\n * its textures died with it. */\n abandon(): void {\n this.textures.clear();\n live.delete(this);\n }\n\n upload(\n key: object,\n source: TexSource,\n repetition?: PatternRepetition,\n ): WebGLTexture {\n const existing = this.map.get(key);\n if (existing) return existing;\n\n const gl = this.gl;\n const tex = gl.createTexture();\n if (!tex) throw new Error('GLImageCache: createTexture failed');\n\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source as TexImageSource);\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MIN_FILTER,\n this.minification === 'mipmap' ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR,\n );\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n this.magFilters.set(key, gl.LINEAR);\n\n const [wrapS, wrapT] = wrapModes(gl, repetition);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n if (this.minification === 'mipmap') gl.generateMipmap(gl.TEXTURE_2D);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.map.set(key, tex);\n this.textures.add(tex);\n return tex;\n }\n\n bind(key: object, unit: number): void {\n const tex = this.map.get(key);\n if (!tex) throw new Error('GLImageCache: image not uploaded; call upload() first');\n const gl = this.gl;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n }\n\n /** Set `key`'s MAG_FILTER, skipping the call when it already holds that\n * value. Its texture must be bound to the active unit — callers pair this\n * with `bind`. */\n setMagFilter(key: object, filter: number): void {\n if (this.magFilters.get(key) === filter) return;\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, filter);\n this.magFilters.set(key, filter);\n }\n}\n\nfunction wrapModes(\n gl: WebGL2RenderingContext,\n rep?: PatternRepetition,\n): [number, number] {\n switch (rep) {\n case 'repeat': return [gl.REPEAT, gl.REPEAT];\n case 'repeat-x': return [gl.REPEAT, gl.CLAMP_TO_EDGE];\n case 'repeat-y': return [gl.CLAMP_TO_EDGE, gl.REPEAT];\n default: return [gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE];\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ //#region src/renderer/cache/GLMeshCache.ts
2
+ var e = class {
3
+ gl;
4
+ aPositionLoc;
5
+ map = /* @__PURE__ */ new WeakMap();
6
+ seen = /* @__PURE__ */ new WeakSet();
7
+ finalizer;
8
+ persistent = /* @__PURE__ */ new Set();
9
+ pendingDeletes = [];
10
+ disposed = !1;
11
+ transientThisFrame = [];
12
+ constructor(e, t) {
13
+ this.gl = e, this.aPositionLoc = t, this.finalizer = new FinalizationRegistry((e) => {
14
+ this.persistent.delete(e) && this.pendingDeletes.push(e);
15
+ });
16
+ }
17
+ handleFor(e) {
18
+ let t = this.map.get(e);
19
+ if (t) return t;
20
+ let { handle: n, vbo: r, ibo: i } = this.upload(e);
21
+ this.map.set(e, n);
22
+ let a = {
23
+ vao: n.vao,
24
+ vbo: r,
25
+ ibo: i
26
+ };
27
+ return this.persistent.add(a), this.finalizer.register(e, a, e), n;
28
+ }
29
+ uploadTransient(e) {
30
+ let { handle: t, vbo: n, ibo: r } = this.upload(e);
31
+ return this.transientThisFrame.push({
32
+ vao: t.vao,
33
+ vbo: n,
34
+ ibo: r
35
+ }), t;
36
+ }
37
+ uploadRecurring(e) {
38
+ return this.seen.has(e) ? this.handleFor(e) : (this.seen.add(e), this.uploadTransient(e));
39
+ }
40
+ freeTransient() {
41
+ if (this.transientThisFrame.length === 0) return;
42
+ let e = this.gl;
43
+ if (e.isContextLost()) {
44
+ this.transientThisFrame.length = 0;
45
+ return;
46
+ }
47
+ for (let t of this.transientThisFrame) e.deleteVertexArray(t.vao), e.deleteBuffer(t.vbo), e.deleteBuffer(t.ibo);
48
+ this.transientThisFrame.length = 0;
49
+ }
50
+ _transientCount() {
51
+ return this.transientThisFrame.length;
52
+ }
53
+ drainPendingDeletes() {
54
+ if (this.pendingDeletes.length === 0) return;
55
+ let e = this.gl;
56
+ if (e.isContextLost()) {
57
+ this.pendingDeletes.length = 0;
58
+ return;
59
+ }
60
+ for (let t of this.pendingDeletes) e.deleteVertexArray(t.vao), e.deleteBuffer(t.vbo), e.deleteBuffer(t.ibo);
61
+ this.pendingDeletes.length = 0;
62
+ }
63
+ dispose() {
64
+ if (!this.disposed) {
65
+ this.disposed = !0, this.freeTransient();
66
+ for (let e of this.persistent) this.pendingDeletes.push(e);
67
+ this.persistent.clear(), this.drainPendingDeletes();
68
+ }
69
+ }
70
+ _pendingDeleteCount() {
71
+ return this.pendingDeletes.length;
72
+ }
73
+ _enqueueDeleteForTest(e) {
74
+ this.pendingDeletes.push(e);
75
+ }
76
+ upload(e) {
77
+ let t = this.gl, n = t.createVertexArray();
78
+ if (!n) throw Error("createVertexArray returned null");
79
+ t.bindVertexArray(n);
80
+ let r = t.createBuffer();
81
+ if (!r) throw Error("createBuffer (VBO) returned null");
82
+ t.bindBuffer(t.ARRAY_BUFFER, r), t.bufferData(t.ARRAY_BUFFER, e.vertices, t.STATIC_DRAW), t.enableVertexAttribArray(this.aPositionLoc), t.vertexAttribPointer(this.aPositionLoc, 2, t.FLOAT, !1, 0, 0);
83
+ let i = t.createBuffer();
84
+ if (!i) throw Error("createBuffer (IBO) returned null");
85
+ return t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, i), t.bufferData(t.ELEMENT_ARRAY_BUFFER, e.indices, t.STATIC_DRAW), t.bindVertexArray(null), {
86
+ handle: {
87
+ vao: n,
88
+ indexCount: e.indices.length,
89
+ requiresStencil: e.requiresStencil ?? !1,
90
+ anchorA: e.anchorA,
91
+ anchorB: e.anchorB,
92
+ anchorT: e.anchorT
93
+ },
94
+ vbo: r,
95
+ ibo: i
96
+ };
97
+ }
98
+ };
99
+ //#endregion
100
+ export { e as GLMeshCache };
101
+
102
+ //# sourceMappingURL=GLMeshCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GLMeshCache.js","names":["GLMeshCache","gl","aPositionLoc","resources","cached","mesh","handle","r","vao","vbo","ibo"],"sources":["../../../src/renderer/cache/GLMeshCache.ts"],"sourcesContent":["import type { Mesh } from '@weasel-js/geom/tessellate';\n\nexport interface GLMeshHandle {\n readonly vao: WebGLVertexArrayObject;\n readonly indexCount: number;\n readonly requiresStencil: boolean;\n readonly anchorA?: Uint32Array;\n readonly anchorB?: Uint32Array;\n readonly anchorT?: Float32Array;\n}\n\n/** Resources to release when a Mesh is reclaimed by GC. */\ninterface MeshResources {\n vao: WebGLVertexArrayObject;\n vbo: WebGLBuffer;\n ibo: WebGLBuffer;\n}\n\n/**\n * Caches GL-side buffers + VAO per `Mesh` identity. Upload happens lazily\n * on first `handleFor(mesh)` call.\n *\n * **GC-aware cleanup (deferred-delete queue):** when a Mesh becomes\n * unreachable, the WeakMap entry is dropped automatically — but the\n * underlying GL resources (VAO, VBO, IBO) would leak forever without an\n * explicit `gl.delete*` call. We register each Mesh with a\n * `FinalizationRegistry`; when the Mesh is reclaimed, the finalizer pushes\n * the resources onto an internal queue. The renderer drains this queue at\n * the start of each `render()` call (via `drainPendingDeletes()`), when GL\n * is in a known state — no VAO bound, no draw mid-flight. Deleting from the\n * finalizer directly was racy (it could fire between two `gl.bindVertexArray`\n * calls inside `dispatch()`, sometimes corrupting the next draw); deferring\n * the actual delete to a known-safe point keeps the use-after-free risk to\n * zero.\n *\n * Caveats:\n * - Finalizer timing is non-deterministic; resources may live for a frame\n * or two beyond their Mesh, but they will be reclaimed.\n * - If the GL context is lost between finalizer and drain, the drain\n * no-ops safely (`gl.isContextLost()` makes deletes no-ops, and\n * `gl.deleteBuffer(null)` is allowed).\n *\n * The cache is GL-context-bound; if the context is lost and re-created, the\n * renderer should construct a new GLMeshCache. (Context loss handling lives\n * in `WeaselRenderer`.)\n */\nexport class GLMeshCache {\n private readonly map = new WeakMap<Mesh, GLMeshHandle>();\n /** Meshes this context has drawn at least once; see `uploadRecurring`. */\n private readonly seen = new WeakSet<Mesh>();\n private readonly finalizer: FinalizationRegistry<MeshResources>;\n /** Every persistent upload not yet freed, so `dispose` can reach them. */\n private readonly persistent = new Set<MeshResources>();\n private readonly pendingDeletes: MeshResources[] = [];\n private disposed = false;\n /** Transient resources allocated this frame; freed at end of render(). */\n private readonly transientThisFrame: MeshResources[] = [];\n\n constructor(\n private readonly gl: WebGL2RenderingContext,\n private readonly aPositionLoc: number,\n ) {\n this.finalizer = new FinalizationRegistry<MeshResources>((resources) => {\n // Defer the actual gl.delete* until the renderer's next render(),\n // when no VAO/buffer is bound mid-draw. Direct deletion from the\n // finalizer caused use-after-free crashes when GC fired between\n // bindVertexArray and drawElements inside dispatch().\n if (!this.persistent.delete(resources)) return;\n this.pendingDeletes.push(resources);\n });\n }\n\n handleFor(mesh: Mesh): GLMeshHandle {\n const cached = this.map.get(mesh);\n if (cached) return cached;\n const { handle, vbo, ibo } = this.upload(mesh);\n this.map.set(mesh, handle);\n const resources = { vao: handle.vao, vbo, ibo };\n this.persistent.add(resources);\n // Register so the GL resources get freed when `mesh` is GC'd. The\n // unregister token (mesh) lets us cancel if the Mesh is somehow\n // re-uploaded under a different cache, though that's not a normal flow.\n this.finalizer.register(mesh, resources, mesh);\n return handle;\n }\n\n /**\n * Upload a Mesh that the caller knows is single-use (e.g. the per-frame\n * stroke ribbon from `tessellateStroke`). Returns a handle backed by fresh\n * GL resources that the renderer will free deterministically at the end\n * of the current frame via `freeTransient()`. Bypasses the WeakMap cache\n * and the FinalizationRegistry, so transient meshes never wait on GC.\n */\n uploadTransient(mesh: Mesh): GLMeshHandle {\n const { handle, vbo, ibo } = this.upload(mesh);\n this.transientThisFrame.push({ vao: handle.vao, vbo, ibo });\n return handle;\n }\n\n /**\n * Upload a Mesh that may or may not recur across frames. Its first sight in\n * *this* context takes `uploadTransient`; every later one takes the\n * persistent handle. One transient upload to find out is cheaper than\n * stranding a persistent VAO on a mesh that never returns, whose release\n * would wait on GC. The transient upload does not populate the persistent\n * map, so steady-state reuse begins on the third frame.\n */\n uploadRecurring(mesh: Mesh): GLMeshHandle {\n if (this.seen.has(mesh)) return this.handleFor(mesh);\n this.seen.add(mesh);\n return this.uploadTransient(mesh);\n }\n\n /**\n * Free all transient resources allocated since the last call. Called by\n * the renderer at the end of each `render()`. Safe under context loss.\n */\n freeTransient(): void {\n if (this.transientThisFrame.length === 0) return;\n const gl = this.gl;\n if (gl.isContextLost()) {\n this.transientThisFrame.length = 0;\n return;\n }\n for (const r of this.transientThisFrame) {\n gl.deleteVertexArray(r.vao);\n gl.deleteBuffer(r.vbo);\n gl.deleteBuffer(r.ibo);\n }\n this.transientThisFrame.length = 0;\n }\n\n /** @internal — for tests asserting the transient-list size. */\n _transientCount(): number {\n return this.transientThisFrame.length;\n }\n\n /**\n * Free GL resources whose Mesh has been GC'd since the last drain.\n * Called by the renderer at the top of each `render()`, before any draws.\n */\n drainPendingDeletes(): void {\n if (this.pendingDeletes.length === 0) return;\n const gl = this.gl;\n if (gl.isContextLost()) {\n this.pendingDeletes.length = 0;\n return;\n }\n for (const r of this.pendingDeletes) {\n gl.deleteVertexArray(r.vao);\n gl.deleteBuffer(r.vbo);\n gl.deleteBuffer(r.ibo);\n }\n this.pendingDeletes.length = 0;\n }\n\n /**\n * Free every GL resource this cache holds — persistent, pending and\n * transient — and ignore finalizers from here on. Idempotent. Unlike the\n * other paths this does not wait on GC, which is what lets a renderer on a\n * context it does not own give back everything it uploaded.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.freeTransient();\n for (const r of this.persistent) this.pendingDeletes.push(r);\n this.persistent.clear();\n this.drainPendingDeletes();\n }\n\n /** @internal — for tests asserting the queue size. */\n _pendingDeleteCount(): number {\n return this.pendingDeletes.length;\n }\n\n /** @internal — for tests that need to simulate the finalizer firing. */\n _enqueueDeleteForTest(resources: MeshResources): void {\n this.pendingDeletes.push(resources);\n }\n\n private upload(mesh: Mesh): { handle: GLMeshHandle; vbo: WebGLBuffer; ibo: WebGLBuffer } {\n const gl = this.gl;\n const vao = gl.createVertexArray();\n if (!vao) throw new Error('createVertexArray returned null');\n gl.bindVertexArray(vao);\n\n const vbo = gl.createBuffer();\n if (!vbo) throw new Error('createBuffer (VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW);\n\n gl.enableVertexAttribArray(this.aPositionLoc);\n gl.vertexAttribPointer(this.aPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n const ibo = gl.createBuffer();\n if (!ibo) throw new Error('createBuffer (IBO) returned null');\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);\n\n gl.bindVertexArray(null);\n\n return {\n handle: {\n vao,\n indexCount: mesh.indices.length,\n requiresStencil: mesh.requiresStencil ?? false,\n anchorA: mesh.anchorA,\n anchorB: mesh.anchorB,\n anchorT: mesh.anchorT,\n },\n vbo,\n ibo,\n };\n }\n}\n"],"mappings":";AA8CA,IAAaA,IAAb,MAAyB;CAaJ;CACA;CAbnB,sBAAuB,IAAI,QAA4B;CAEvD,uBAAwB,IAAI,QAAc;CAC1C;CAEA,6BAA8B,IAAI,IAAmB;CACrD,iBAAmD,CAAC;CACpD,WAAmB;CAEnB,qBAAuD,CAAC;CAExD,YACE,GACA,GACA;EACA,AAHiB,KAAA,KAAAC,GACA,KAAA,eAAAC,GAEjB,KAAK,YAAY,IAAI,sBAAqC,MAAc;GAKtE,AAAK,KAAK,WAAW,OAAOC,CAAS,KACrC,KAAK,eAAe,KAAKA,CAAS;EACpC,CAAC;CACH;CAEA,UAAU,GAA0B;EAClC,IAAMC,IAAS,KAAK,IAAI,IAAIC,CAAI;EAChC,IAAID,GAAQ,OAAOA;EACnB,IAAM,EAAE,WAAQ,QAAK,WAAQ,KAAK,OAAOC,CAAI;EAC7C,KAAK,IAAI,IAAIA,GAAMC,CAAM;EACzB,IAAMH,IAAY;GAAE,KAAKG,EAAO;GAAK;GAAK;EAAI;EAM9C,OALA,KAAK,WAAW,IAAIH,CAAS,GAI7B,KAAK,UAAU,SAASE,GAAMF,GAAWE,CAAI,GACtCC;CACT;CASA,gBAAgB,GAA0B;EACxC,IAAM,EAAE,WAAQ,QAAK,WAAQ,KAAK,OAAOD,CAAI;EAE7C,OADA,KAAK,mBAAmB,KAAK;GAAE,KAAKC,EAAO;GAAK;GAAK;EAAI,CAAC,GACnDA;CACT;CAUA,gBAAgB,GAA0B;EAGxC,OAFI,KAAK,KAAK,IAAID,CAAI,IAAU,KAAK,UAAUA,CAAI,KACnD,KAAK,KAAK,IAAIA,CAAI,GACX,KAAK,gBAAgBA,CAAI;CAClC;CAMA,gBAAsB;EACpB,IAAI,KAAK,mBAAmB,WAAW,GAAG;EAC1C,IAAMJ,IAAK,KAAK;EAChB,IAAIA,EAAG,cAAc,GAAG;GACtB,KAAK,mBAAmB,SAAS;GACjC;EACF;EACA,KAAK,IAAMM,KAAK,KAAK,oBAGnB,AAFAN,EAAG,kBAAkBM,EAAE,GAAG,GAC1BN,EAAG,aAAaM,EAAE,GAAG,GACrBN,EAAG,aAAaM,EAAE,GAAG;EAEvB,KAAK,mBAAmB,SAAS;CACnC;CAGA,kBAA0B;EACxB,OAAO,KAAK,mBAAmB;CACjC;CAMA,sBAA4B;EAC1B,IAAI,KAAK,eAAe,WAAW,GAAG;EACtC,IAAMN,IAAK,KAAK;EAChB,IAAIA,EAAG,cAAc,GAAG;GACtB,KAAK,eAAe,SAAS;GAC7B;EACF;EACA,KAAK,IAAMM,KAAK,KAAK,gBAGnB,AAFAN,EAAG,kBAAkBM,EAAE,GAAG,GAC1BN,EAAG,aAAaM,EAAE,GAAG,GACrBN,EAAG,aAAaM,EAAE,GAAG;EAEvB,KAAK,eAAe,SAAS;CAC/B;CAQA,UAAgB;EACd,IAAI,MAAK,UAET;GADA,KAAK,WAAW,IAChB,KAAK,cAAc;GACnB,KAAK,IAAMA,KAAK,KAAK,YAAY,KAAK,eAAe,KAAKA,CAAC;GAE3D,AADA,KAAK,WAAW,MAAM,GACtB,KAAK,oBAAoB;EAHN;CAIrB;CAGA,sBAA8B;EAC5B,OAAO,KAAK,eAAe;CAC7B;CAGA,sBAAsB,GAAgC;EACpD,KAAK,eAAe,KAAKJ,CAAS;CACpC;CAEA,OAAe,GAA0E;EACvF,IAAMF,IAAK,KAAK,IACVO,IAAMP,EAAG,kBAAkB;EACjC,IAAI,CAACO,GAAK,MAAU,MAAM,iCAAiC;EAC3D,EAAG,gBAAgBA,CAAG;EAEtB,IAAMC,IAAMR,EAAG,aAAa;EAC5B,IAAI,CAACQ,GAAK,MAAU,MAAM,kCAAkC;EAK5D,AAJAR,EAAG,WAAWA,EAAG,cAAcQ,CAAG,GAClCR,EAAG,WAAWA,EAAG,cAAcI,EAAK,UAAUJ,EAAG,WAAW,GAE5DA,EAAG,wBAAwB,KAAK,YAAY,GAC5CA,EAAG,oBAAoB,KAAK,cAAc,GAAGA,EAAG,OAAO,IAAO,GAAG,CAAC;EAElE,IAAMS,IAAMT,EAAG,aAAa;EAC5B,IAAI,CAACS,GAAK,MAAU,MAAM,kCAAkC;EAM5D,OALAT,EAAG,WAAWA,EAAG,sBAAsBS,CAAG,GAC1CT,EAAG,WAAWA,EAAG,sBAAsBI,EAAK,SAASJ,EAAG,WAAW,GAEnEA,EAAG,gBAAgB,IAAI,GAEhB;GACL,QAAQ;IACN;IACA,YAAYI,EAAK,QAAQ;IACzB,iBAAiBA,EAAK,mBAAmB;IACzC,SAASA,EAAK;IACd,SAASA,EAAK;IACd,SAASA,EAAK;GAChB;GACA;GACA;EACF;CACF;AACF"}
@@ -0,0 +1,51 @@
1
+ //#region src/renderer/cache/GLTextureCache.ts
2
+ var e = class {
3
+ gl;
4
+ map = /* @__PURE__ */ new Map();
5
+ wraps = /* @__PURE__ */ new Map();
6
+ constructor(e) {
7
+ this.gl = e;
8
+ }
9
+ has(e) {
10
+ return this.map.has(e);
11
+ }
12
+ upload(e, t, n = "clamp") {
13
+ let r = this.map.get(e);
14
+ if (r) return this.wraps.get(e) !== n && this.applyWrap(e, r, n), e;
15
+ let i = this.gl, a = i.createTexture();
16
+ if (!a) throw Error(`GLTextureCache: createTexture failed for id="${e}"`);
17
+ let o = n === "repeat" ? i.REPEAT : i.CLAMP_TO_EDGE;
18
+ return i.bindTexture(i.TEXTURE_2D, a), i.texImage2D(i.TEXTURE_2D, 0, i.RGBA, i.RGBA, i.UNSIGNED_BYTE, t), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MIN_FILTER, i.LINEAR), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MAG_FILTER, i.LINEAR), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_S, o), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_T, o), i.bindTexture(i.TEXTURE_2D, null), this.map.set(e, a), this.wraps.set(e, n), e;
19
+ }
20
+ applyWrap(e, t, n) {
21
+ let r = this.gl, i = n === "repeat" ? r.REPEAT : r.CLAMP_TO_EDGE;
22
+ r.bindTexture(r.TEXTURE_2D, t), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, i), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, i), r.bindTexture(r.TEXTURE_2D, null), this.wraps.set(e, n);
23
+ }
24
+ uploadR8(e, t, n, r) {
25
+ if (this.map.has(e)) return;
26
+ let i = this.gl, a = i.createTexture();
27
+ if (!a) throw Error(`GLTextureCache: createTexture failed for id="${e}"`);
28
+ i.bindTexture(i.TEXTURE_2D, a), i.pixelStorei(i.UNPACK_ALIGNMENT, 1), i.texImage2D(i.TEXTURE_2D, 0, i.R8, t, n, 0, i.RED, i.UNSIGNED_BYTE, r), i.pixelStorei(i.UNPACK_ALIGNMENT, 4), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MIN_FILTER, i.LINEAR), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MAG_FILTER, i.LINEAR), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_S, i.CLAMP_TO_EDGE), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_T, i.CLAMP_TO_EDGE), i.bindTexture(i.TEXTURE_2D, null), this.map.set(e, a), this.wraps.set(e, "clamp");
29
+ }
30
+ subImageR8(e, t, n, r, i, a) {
31
+ let o = this.map.get(e);
32
+ if (!o) throw Error(`GLTextureCache: texture "${e}" not uploaded`);
33
+ let s = this.gl;
34
+ s.bindTexture(s.TEXTURE_2D, o), s.pixelStorei(s.UNPACK_ALIGNMENT, 1), s.texSubImage2D(s.TEXTURE_2D, 0, t, n, r, i, s.RED, s.UNSIGNED_BYTE, a), s.pixelStorei(s.UNPACK_ALIGNMENT, 4), s.bindTexture(s.TEXTURE_2D, null);
35
+ }
36
+ bind(e, t) {
37
+ let n = this.map.get(e);
38
+ if (!n) throw Error(`GLTextureCache: texture "${e}" not uploaded`);
39
+ let r = this.gl;
40
+ r.activeTexture(r.TEXTURE0 + t), r.bindTexture(r.TEXTURE_2D, n);
41
+ }
42
+ free() {
43
+ let e = this.gl;
44
+ for (let t of this.map.values()) e.deleteTexture(t);
45
+ this.map.clear(), this.wraps.clear();
46
+ }
47
+ };
48
+ //#endregion
49
+ export { e as GLTextureCache };
50
+
51
+ //# sourceMappingURL=GLTextureCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GLTextureCache.js","names":["GLTextureCache","gl","id","cached","wrap","tex","wrapMode","source","mode","width","height","data","x","y","w","h","unit"],"sources":["../../../src/renderer/cache/GLTextureCache.ts"],"sourcesContent":["/**\n * GL texture upload + cache for MSDF font atlases (and future images).\n *\n * Textures are keyed by a string id (the font family name or image id).\n * Pixels are uploaded once per id; a later upload of the same id reuses the\n * texture and only re-applies its wrap mode when that changed.\n * The cache is GL-context-bound; discard and create a new one on context loss.\n *\n * Atlas format: RGBA UNSIGNED_BYTE, linear filtering, no mipmaps.\n * Mipmap generation is deliberately skipped — MSDF works correctly with\n * linear filtering, and mipmap resampling corrupts the multi-channel SDF signal.\n */\n\ntype TexSource = HTMLImageElement | ImageBitmap | ImageData | HTMLCanvasElement;\n\n/** How a texture samples outside `0..1`. Pattern tiles need `'repeat'`;\n * everything else clamps. WebGL2 allows `REPEAT` on NPOT textures, so a\n * tile of any size tiles correctly. */\nexport type TextureWrap = 'clamp' | 'repeat';\n\nexport class GLTextureCache {\n private readonly map = new Map<string, WebGLTexture>();\n private readonly wraps = new Map<string, TextureWrap>();\n\n constructor(private readonly gl: WebGL2RenderingContext) {}\n\n has(id: string): boolean {\n return this.map.has(id);\n }\n\n /** Uploads the pixels once per id. `wrap` is re-applied whenever it differs\n * from what the id was last uploaded under: the same registered image can\n * be a clamped shader texture in one draw and a repeating pattern tile in\n * the next, and first-upload-wins gave the second one the first one's mode. */\n upload(id: string, source: TexSource, wrap: TextureWrap = 'clamp'): string {\n const cached = this.map.get(id);\n if (cached) {\n if (this.wraps.get(id) !== wrap) this.applyWrap(id, cached, wrap);\n return id;\n }\n\n const gl = this.gl;\n const tex = gl.createTexture();\n if (!tex) throw new Error(`GLTextureCache: createTexture failed for id=\"${id}\"`);\n\n const wrapMode = wrap === 'repeat' ? gl.REPEAT : gl.CLAMP_TO_EDGE;\n\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source as TexImageSource);\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapMode);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapMode);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.map.set(id, tex);\n this.wraps.set(id, wrap);\n return id;\n }\n\n private applyWrap(id: string, tex: WebGLTexture, wrap: TextureWrap): void {\n const gl = this.gl;\n const mode = wrap === 'repeat' ? gl.REPEAT : gl.CLAMP_TO_EDGE;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, mode);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, mode);\n gl.bindTexture(gl.TEXTURE_2D, null);\n this.wraps.set(id, wrap);\n }\n\n /** Create a single-channel R8 texture from raw bytes (full upload).\n * No-op if `id` already exists. Same LINEAR/CLAMP params as `upload`;\n * UNPACK_ALIGNMENT dropped to 1 for non-4-aligned row widths. */\n uploadR8(id: string, width: number, height: number, data: Uint8Array): void {\n if (this.map.has(id)) return;\n const gl = this.gl;\n const tex = gl.createTexture();\n if (!tex) throw new Error(`GLTextureCache: createTexture failed for id=\"${id}\"`);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, width, height, 0, gl.RED, gl.UNSIGNED_BYTE, data);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.bindTexture(gl.TEXTURE_2D, null);\n this.map.set(id, tex);\n this.wraps.set(id, 'clamp');\n }\n\n /** Patch a rect of an existing R8 texture with tightly-packed w×h bytes. */\n subImageR8(id: string, x: number, y: number, w: number, h: number, data: Uint8Array): void {\n const tex = this.map.get(id);\n if (!tex) throw new Error(`GLTextureCache: texture \"${id}\" not uploaded`);\n const gl = this.gl;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\n gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, w, h, gl.RED, gl.UNSIGNED_BYTE, data);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n\n bind(id: string, unit: number): void {\n const tex = this.map.get(id);\n if (!tex) throw new Error(`GLTextureCache: texture \"${id}\" not uploaded`);\n const gl = this.gl;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n }\n\n /**\n * Delete every uploaded GL texture and clear the map. Called by\n * `WeaselRenderer.dispose()`. The cache is unusable but refillable\n * afterward — a subsequent `upload()` for a previously-seen id re-creates\n * the texture rather than restoring the deleted one.\n */\n free(): void {\n const gl = this.gl;\n for (const tex of this.map.values()) {\n gl.deleteTexture(tex);\n }\n this.map.clear();\n this.wraps.clear();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { resolveGradientStops as e, sampleResolvedStops as t } from "../../core/gradient.js";
2
+ //#region src/renderer/cache/GradientRampAtlas.ts
3
+ var n = 256, r = 16, i = 1024;
4
+ function a(r, i = "rgb") {
5
+ let a = new Uint8ClampedArray(n * 4);
6
+ if (r.length === 0) return a;
7
+ let o = e(r);
8
+ for (let e = 0; e < n; e++) {
9
+ let [n, r, s, c] = t(o, e / 255, i);
10
+ a[e * 4] = n * 255, a[e * 4 + 1] = r * 255, a[e * 4 + 2] = s * 255, a[e * 4 + 3] = c * 255;
11
+ }
12
+ return a;
13
+ }
14
+ function o(e, t) {
15
+ return `${t}|${JSON.stringify(e)}`;
16
+ }
17
+ var s = class {
18
+ gl;
19
+ rowByKey = /* @__PURE__ */ new Map();
20
+ texture = null;
21
+ rows = 0;
22
+ pixels = /* @__PURE__ */ new Uint8ClampedArray();
23
+ totalQueries = 0;
24
+ cacheHits = 0;
25
+ constructor(e) {
26
+ this.gl = e;
27
+ }
28
+ get height() {
29
+ return this.rows;
30
+ }
31
+ upload(e, t = "rgb") {
32
+ let n = o(e, t);
33
+ this.totalQueries++;
34
+ let r = this.rowByKey.get(n);
35
+ if (r !== void 0) return this.cacheHits++, this.rowByKey.delete(n), this.rowByKey.set(n, r), r;
36
+ let i = this.claimRow();
37
+ return this.writeRow(i, a(e, t)), this.rowByKey.set(n, i), i;
38
+ }
39
+ wouldReshape(e, t = "rgb") {
40
+ return this.rowByKey.size !== 0 && !this.rowByKey.has(o(e, t)) && this.rowByKey.size >= this.rows;
41
+ }
42
+ rowV(e) {
43
+ return (e + .5) / (this.rows || 1);
44
+ }
45
+ bind(e) {
46
+ let t = this.gl;
47
+ t.activeTexture(t.TEXTURE0 + e), t.bindTexture(t.TEXTURE_2D, this.texture);
48
+ }
49
+ hitRate() {
50
+ return this.totalQueries === 0 ? 0 : this.cacheHits / this.totalQueries;
51
+ }
52
+ resetStats() {
53
+ this.totalQueries = 0, this.cacheHits = 0;
54
+ }
55
+ free() {
56
+ this.texture && this.gl.deleteTexture(this.texture), this.texture = null, this.rows = 0, this.pixels = /* @__PURE__ */ new Uint8ClampedArray(), this.rowByKey.clear();
57
+ }
58
+ claimRow() {
59
+ if (this.rowByKey.size < this.rows) return this.rowByKey.size;
60
+ if (this.rows < i) return this.resize(this.rows === 0 ? r : this.rows * 2), this.rowByKey.size;
61
+ let [e, t] = this.rowByKey.entries().next().value;
62
+ return this.rowByKey.delete(e), t;
63
+ }
64
+ resize(e) {
65
+ let t = this.gl, r = new Uint8ClampedArray(n * e * 4);
66
+ if (r.set(this.pixels), this.pixels = r, this.rows = e, this.texture) t.bindTexture(t.TEXTURE_2D, this.texture);
67
+ else {
68
+ let e = t.createTexture();
69
+ if (!e) throw Error("GradientRampAtlas: createTexture failed");
70
+ this.texture = e, t.bindTexture(t.TEXTURE_2D, e), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE);
71
+ }
72
+ t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, n, e, 0, t.RGBA, t.UNSIGNED_BYTE, this.pixels), t.bindTexture(t.TEXTURE_2D, null);
73
+ }
74
+ writeRow(e, t) {
75
+ let r = this.gl;
76
+ this.pixels.set(t, e * n * 4), r.bindTexture(r.TEXTURE_2D, this.texture), r.texSubImage2D(r.TEXTURE_2D, 0, 0, e, n, 1, r.RGBA, r.UNSIGNED_BYTE, t), r.bindTexture(r.TEXTURE_2D, null);
77
+ }
78
+ };
79
+ //#endregion
80
+ export { s as GradientRampAtlas, i as RAMP_ATLAS_MAX_ROWS, n as RAMP_WIDTH, a as buildGradientRamp };
81
+
82
+ //# sourceMappingURL=GradientRampAtlas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GradientRampAtlas.js","names":["RAMP_WIDTH","INITIAL_ROWS","RAMP_ATLAS_MAX_ROWS","buildGradientRamp","data","stops","resolved","resolveGradientStops","i","r","g","b","a","sampleResolvedStops","space","rampKey","GradientRampAtlas","gl","key","existing","row","unit","lruKey","lruRow","next","rows","tex","ramp"],"sources":["../../../src/renderer/cache/GradientRampAtlas.ts"],"sourcesContent":["/**\n * CPU gradient-ramp builder + the GL texture every baked ramp lives in.\n *\n * Each unique stop list is baked once into a 256-texel strip and written to its\n * own **row** of one RGBA texture, keyed by `JSON.stringify(stops)`. One\n * texture rather than one per ramp is what lets a gradient take a batch texture\n * slot the way a bitmap or a font atlas does: every gradient in a frame samples\n * the same unit, so a run does not break per gradient. The atlas is\n * GL-context-bound; discard and recreate on context loss.\n *\n * Output convention §2: texels are stored as straight RGBA. The fragment\n * shader applies premultiplication before writing outColor.\n */\n\nimport type { ColorSpace, GradStop } from '@weasel-js/paint';\nimport { resolveGradientStops, sampleResolvedStops } from '../../core/gradient';\n\n/** Texels across one ramp — the resolution a gradient is sampled at. */\nexport const RAMP_WIDTH = 256;\n\n/** Rows the atlas starts at, doubling from there. */\nconst INITIAL_ROWS = 16;\n\n/**\n * Rows the atlas stops growing at, past which the least recently used row is\n * recycled.\n *\n * WebGL2 guarantees `MAX_TEXTURE_SIZE` of at least 2048, so this is available\n * everywhere without a `getParameter` — which the GL recorder would answer with\n * a recording function rather than a number. A cap is also what bounds an\n * animating gradient, which mints a new stop list every frame and would\n * otherwise grow the atlas until it could not grow again.\n */\nexport const RAMP_ATLAS_MAX_ROWS = 1024;\n\n/** Bake gradient stops into a 256-entry RGBA lookup strip, which the shader\n * samples instead of evaluating stops per fragment. `space` is the gradient's\n * `interpolate` — the ramp is where a non-sRGB blend is paid for, once. */\nexport function buildGradientRamp(stops: GradStop[], space: ColorSpace = 'rgb'): Uint8ClampedArray {\n const data = new Uint8ClampedArray(RAMP_WIDTH * 4);\n if (stops.length === 0) return data;\n\n const resolved = resolveGradientStops(stops);\n for (let i = 0; i < RAMP_WIDTH; i++) {\n const [r, g, b, a] = sampleResolvedStops(resolved, i / (RAMP_WIDTH - 1), space);\n data[i * 4] = r * 255;\n data[i * 4 + 1] = g * 255;\n data[i * 4 + 2] = b * 255;\n data[i * 4 + 3] = a * 255;\n }\n\n return data;\n}\n\n/** The row identity. Two gradients with the same stops and different\n * `interpolate` bake to different texels, so the space is part of the key. */\nfunction rampKey(stops: GradStop[], space: ColorSpace): string {\n return `${space}|${JSON.stringify(stops)}`;\n}\n\nexport class GradientRampAtlas {\n /** Row per stop list, in least-recently-used order: a hit re-inserts, so the\n * first entry is the row a full atlas recycles. */\n private readonly rowByKey = new Map<string, number>();\n private texture: WebGLTexture | null = null;\n private rows = 0;\n /** Mirror of the texture, so growth can respecify it without re-baking every\n * ramp it already holds. */\n private pixels = new Uint8ClampedArray(0);\n private totalQueries = 0;\n private cacheHits = 0;\n\n constructor(private readonly gl: WebGL2RenderingContext) {}\n\n /** Rows the atlas currently holds — its texture height. */\n get height(): number {\n return this.rows;\n }\n\n /**\n * Bake `stops` into a row and return it, reusing the row an identical stop\n * list already holds.\n *\n * **A returned row outlives the frame only while the atlas has room.** Past\n * `RAMP_ATLAS_MAX_ROWS` an upload recycles the least recently used row, which\n * rewrites texels a row handed out earlier still names. Nothing that defers\n * its draw past this call may hold a row across another `upload` without\n * arranging to be flushed first.\n */\n upload(stops: GradStop[], space: ColorSpace = 'rgb'): number {\n const key = rampKey(stops, space);\n this.totalQueries++;\n const existing = this.rowByKey.get(key);\n if (existing !== undefined) {\n this.cacheHits++;\n this.rowByKey.delete(key);\n this.rowByKey.set(key, existing);\n return existing;\n }\n\n const row = this.claimRow();\n this.writeRow(row, buildGradientRamp(stops, space));\n this.rowByKey.set(key, row);\n return row;\n }\n\n /**\n * Whether uploading `stops` would move where existing rows sit — by growing\n * the atlas, which changes every row's `v`, or by recycling one, which\n * rewrites its texels.\n *\n * Anything holding a row past this call asks first and gets itself out of\n * the way, because neither can be undone once it has happened.\n */\n wouldReshape(stops: GradStop[], space: ColorSpace = 'rgb'): boolean {\n // An atlas holding nothing has no row to move, so its first growth is free.\n if (this.rowByKey.size === 0) return false;\n return !this.rowByKey.has(rampKey(stops, space))\n && this.rowByKey.size >= this.rows;\n }\n\n /**\n * The `v` a row is sampled at — its center.\n *\n * The center is load-bearing: the atlas filters LINEAR, so a `v` anywhere\n * else blends the ramp beside it into this one. At the center the neighbor's\n * weight is exactly zero.\n */\n rowV(row: number): number {\n return (row + 0.5) / (this.rows || 1);\n }\n\n bind(unit: number): void {\n const gl = this.gl;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n }\n\n hitRate(): number {\n if (this.totalQueries === 0) return 0;\n return this.cacheHits / this.totalQueries;\n }\n\n resetStats(): void {\n this.totalQueries = 0;\n this.cacheHits = 0;\n }\n\n /**\n * Delete the atlas texture and forget every row in it. Called by\n * `WeaselRenderer.dispose()`. The CPU mirror goes with it, so the atlas is\n * unusable but refillable afterward (stats are left as-is; call\n * `resetStats()` separately if desired).\n */\n free(): void {\n if (this.texture) this.gl.deleteTexture(this.texture);\n this.texture = null;\n this.rows = 0;\n this.pixels = new Uint8ClampedArray(0);\n this.rowByKey.clear();\n }\n\n /** The row the next ramp is written to: a free one, a taller atlas, or the\n * least recently used row of a full one. */\n private claimRow(): number {\n if (this.rowByKey.size < this.rows) return this.rowByKey.size;\n if (this.rows < RAMP_ATLAS_MAX_ROWS) {\n this.resize(this.rows === 0 ? INITIAL_ROWS : this.rows * 2);\n return this.rowByKey.size;\n }\n const [lruKey, lruRow] = this.rowByKey.entries().next().value as [string, number];\n this.rowByKey.delete(lruKey);\n return lruRow;\n }\n\n /** Grow to `rows`, keeping every row at the index it already had — a row\n * index is a stable name, and callers hold them. */\n private resize(rows: number): void {\n const gl = this.gl;\n const next = new Uint8ClampedArray(RAMP_WIDTH * rows * 4);\n next.set(this.pixels);\n this.pixels = next;\n this.rows = rows;\n\n if (!this.texture) {\n const tex = gl.createTexture();\n if (!tex) throw new Error('GradientRampAtlas: createTexture failed');\n this.texture = tex;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n } else {\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n }\n gl.texImage2D(\n gl.TEXTURE_2D, 0, gl.RGBA,\n RAMP_WIDTH, rows, 0,\n gl.RGBA, gl.UNSIGNED_BYTE, this.pixels,\n );\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n\n private writeRow(row: number, ramp: Uint8ClampedArray): void {\n const gl = this.gl;\n this.pixels.set(ramp, row * RAMP_WIDTH * 4);\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n gl.texSubImage2D(\n gl.TEXTURE_2D, 0, 0, row,\n RAMP_WIDTH, 1,\n gl.RGBA, gl.UNSIGNED_BYTE, ramp,\n );\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { tessellate as e } from "@weasel-js/geom/tessellate";
2
+ //#region src/renderer/cache/cache.ts
3
+ var t = /* @__PURE__ */ new WeakMap();
4
+ function n(n) {
5
+ let r = t.get(n);
6
+ if (r !== void 0) return r;
7
+ let i = e(n);
8
+ return t.set(n, i), i;
9
+ }
10
+ //#endregion
11
+ export { n as getMesh };
12
+
13
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","names":["cache","getMesh","cached","path","mesh","tessellate"],"sources":["../../../src/renderer/cache/cache.ts"],"sourcesContent":["import type { Path } from '@weasel-js/core';\nimport { type Mesh, tessellate } from '@weasel-js/geom/tessellate';\n\nlet cache = new WeakMap<Path, Mesh>();\n\n/**\n * Return the tessellated Mesh for `path`, computing and caching on first call.\n * Cached by Path identity (WeakMap) — different Path objects with the same\n * coords are distinct cache entries.\n *\n * Note: solid-fill rect paths bypass this cache entirely — they go into the\n * rect batch in `draw.ts`. The cache only serves polygon paths (where tessellation is\n * non-trivial and Path-object stability is the right contract).\n *\n * Also bypassed whenever `DrawContext.flattenTolerance` is set: `fillMeshHandle`\n * (see `../draw`) routes custom-tolerance fills through a fresh transient\n * tessellation instead of this cache.\n */\nexport function getMesh(path: Path): Mesh {\n const cached = cache.get(path);\n if (cached !== undefined) return cached;\n const mesh = tessellate(path);\n cache.set(path, mesh);\n return mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetCacheForTests(): void {\n cache = new WeakMap();\n}\n"],"mappings":";;AAGA,IAAIA,oBAAQ,IAAI,QAAoB;AAepC,SAAgBC,EAAQ,GAAkB;CACxC,IAAMC,IAASF,EAAM,IAAIG,CAAI;CAC7B,IAAID,MAAW,KAAA,GAAW,OAAOA;CACjC,IAAME,IAAOC,EAAWF,CAAI;CAE5B,OADAH,EAAM,IAAIG,GAAMC,CAAI,GACbA;AACT"}
@@ -0,0 +1,59 @@
1
+ import { getMarker as e, markerGeneration as t } from "../../core/strokeMarkers.js";
2
+ import { markerKeyOf as n } from "../../core/markerInset.js";
3
+ import { STROKE_CONFIGS_PER_PATH as r } from "./strokeMeshCache.js";
4
+ import { headCommands as i, markerHeads as a, markerReadsKey as o } from "../../features/paths/markerCommands.js";
5
+ //#region src/renderer/cache/markerCommandCache.ts
6
+ var s = /* @__PURE__ */ new WeakMap(), c = /* @__PURE__ */ new WeakMap(), l = (e) => e === void 0 ? "" : typeof e == "string" ? e : `${e.key}@${String(e.size ?? "")}`;
7
+ function u(t) {
8
+ let r = "";
9
+ for (let i of [
10
+ t.markerStart,
11
+ t.markerMid,
12
+ t.markerEnd
13
+ ]) {
14
+ let a = i === void 0 ? void 0 : e(n(i));
15
+ if (a === void 0) {
16
+ r += "/";
17
+ continue;
18
+ }
19
+ let s = o(a, t);
20
+ if (s === null) return null;
21
+ r += `${s}/`;
22
+ }
23
+ return r;
24
+ }
25
+ function d(e, t, n) {
26
+ if (n !== null) {
27
+ let t = s.get(e);
28
+ return t === void 0 && s.set(e, t = /* @__PURE__ */ new Map()), t;
29
+ }
30
+ let r = c.get(e);
31
+ r === void 0 && c.set(e, r = /* @__PURE__ */ new WeakMap());
32
+ let i = r.get(t);
33
+ return i === void 0 && r.set(t, i = /* @__PURE__ */ new Map()), i;
34
+ }
35
+ function f(e, n, o, s, c) {
36
+ if (o.markerStart === void 0 && o.markerMid === void 0 && o.markerEnd === void 0) return [];
37
+ let f = u(o), p = d(e, n, f), m = [
38
+ s,
39
+ c ?? "",
40
+ t(),
41
+ l(o.markerStart),
42
+ l(o.markerMid),
43
+ l(o.markerEnd),
44
+ f ?? ""
45
+ ].join("|"), h = p.get(m);
46
+ if (h === void 0) {
47
+ let t = a(e, o, s, c);
48
+ h = {
49
+ heads: t,
50
+ paint: o.paint,
51
+ cmds: i(t, o)
52
+ }, p.size >= r && p.clear(), p.set(m, h);
53
+ } else h.paint !== o.paint && (h.paint = o.paint, h.cmds = i(h.heads, o));
54
+ return h.cmds;
55
+ }
56
+ //#endregion
57
+ export { f as cachedMarkerCommands };
58
+
59
+ //# sourceMappingURL=markerCommandCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markerCommandCache.js","names":["byValue","byStroke","refKey","ref","readsKey","key","stroke","entry","getMarker","markerKeyOf","reads","markerReadsKey","mapFor","map","path","strokes","source","cachedMarkerCommands","strokeWidth","flattenTolerance","markerGeneration","heads","markerHeads","headCommands","STROKE_CONFIGS_PER_PATH"],"sources":["../../../src/renderer/cache/markerCommandCache.ts"],"sourcesContent":["/**\n * A stroke's marker commands, cached per path. The placed head is a fresh\n * `Path`, and the fill cache keys on path identity — so rebuilding it every\n * frame would re-tessellate and re-upload every head every frame.\n *\n * Keyed on value, so a painter that builds a new stroke object every frame\n * still hits: the resolved lengths, the flatten tolerance, the registry's\n * generation, the marker refs and whatever fields each head declares it reads.\n * A head that does not declare them may read any field, so for it the stroke\n * as the command carried it — before any `{ px }` length was resolved — joins\n * the key by identity. Paint is applied over the cached geometry, so a new\n * paint reuses the heads.\n */\n\nimport type { Path } from '@weasel-js/core';\nimport type { FillStyle, MarkerRef, Stroke } from '@weasel-js/paint';\nimport type { PathDrawCommand } from '../DrawCommand';\nimport {\n headCommands, markerHeads, markerReadsKey, type MarkerHead,\n} from 'features/paths/markerCommands';\nimport { getMarker, markerGeneration } from '../../core/strokeMarkers';\nimport { markerKeyOf } from '../../core/markerInset';\nimport { STROKE_CONFIGS_PER_PATH } from './strokeMeshCache';\n\ninterface Entry {\n readonly heads: MarkerHead[];\n paint: FillStyle | undefined;\n cmds: PathDrawCommand[];\n}\n\nlet byValue = new WeakMap<Path, Map<string, Entry>>();\nlet byStroke = new WeakMap<Path, WeakMap<Stroke, Map<string, Entry>>>();\n\nconst refKey = (ref: MarkerRef | undefined): string =>\n ref === undefined ? '' : typeof ref === 'string' ? ref : `${ref.key}@${String(ref.size ?? '')}`;\n\n/** What every head of `stroke` reads, or `null` if any head does not say. */\nfunction readsKey(stroke: Stroke): string | null {\n let key = '';\n for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {\n const entry = ref === undefined ? undefined : getMarker(markerKeyOf(ref));\n if (entry === undefined) {\n key += '/';\n continue;\n }\n const reads = markerReadsKey(entry, stroke);\n if (reads === null) return null;\n key += `${reads}/`;\n }\n return key;\n}\n\nfunction mapFor(path: Path, source: Stroke, reads: string | null): Map<string, Entry> {\n if (reads !== null) {\n let map = byValue.get(path);\n if (map === undefined) byValue.set(path, (map = new Map()));\n return map;\n }\n let strokes = byStroke.get(path);\n if (strokes === undefined) byStroke.set(path, (strokes = new WeakMap()));\n let map = strokes.get(source);\n if (map === undefined) strokes.set(source, (map = new Map()));\n return map;\n}\n\n/**\n * The marker commands for `path` under `stroke`, whose lengths are already\n * resolved to world units. `source` is the stroke before that resolution.\n */\nexport function cachedMarkerCommands(\n path: Path,\n source: Stroke,\n stroke: Stroke,\n strokeWidth: number,\n flattenTolerance: number | undefined,\n): PathDrawCommand[] {\n if (stroke.markerStart === undefined && stroke.markerMid === undefined && stroke.markerEnd === undefined) {\n return [];\n }\n const reads = readsKey(stroke);\n const map = mapFor(path, source, reads);\n const key = [\n strokeWidth,\n flattenTolerance ?? '',\n markerGeneration(),\n refKey(stroke.markerStart),\n refKey(stroke.markerMid),\n refKey(stroke.markerEnd),\n reads ?? '',\n ].join('|');\n let entry = map.get(key);\n if (entry === undefined) {\n const heads = markerHeads(path, stroke, strokeWidth, flattenTolerance);\n entry = { heads, paint: stroke.paint, cmds: headCommands(heads, stroke) };\n if (map.size >= STROKE_CONFIGS_PER_PATH) map.clear();\n map.set(key, entry);\n } else if (entry.paint !== stroke.paint) {\n entry.paint = stroke.paint;\n entry.cmds = headCommands(entry.heads, stroke);\n }\n return entry.cmds;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetMarkerCommandCacheForTests(): void {\n byValue = new WeakMap();\n byStroke = new WeakMap();\n}\n"],"mappings":";;;;;AA8BA,IAAIA,oBAAU,IAAI,QAAkC,GAChDC,oBAAW,IAAI,QAAmD,GAEhEC,KAAU,MACdC,MAAQ,KAAA,IAAY,KAAK,OAAOA,KAAQ,WAAWA,IAAM,GAAGA,EAAI,IAAI,GAAG,OAAOA,EAAI,QAAQ,EAAE;AAG9F,SAASC,EAAS,GAA+B;CAC/C,IAAIC,IAAM;CACV,KAAK,IAAMF,KAAO;EAACG,EAAO;EAAaA,EAAO;EAAWA,EAAO;CAAS,GAAG;EAC1E,IAAMC,IAAQJ,MAAQ,KAAA,IAAY,KAAA,IAAYK,EAAUC,EAAYN,CAAG,CAAC;EACxE,IAAII,MAAU,KAAA,GAAW;GACvB,KAAO;GACP;EACF;EACA,IAAMG,IAAQC,EAAeJ,GAAOD,CAAM;EAC1C,IAAII,MAAU,MAAM,OAAO;EAC3B,KAAO,GAAGA,EAAM;CAClB;CACA,OAAOL;AACT;AAEA,SAASO,EAAO,GAAY,GAAgB,GAA0C;CACpF,IAAIF,MAAU,MAAM;EAClB,IAAIG,IAAMb,EAAQ,IAAIc,CAAI;EAE1B,OADID,MAAQ,KAAA,KAAWb,EAAQ,IAAIc,GAAO,oBAAM,IAAI,IAAI,CAAE,GACnDD;CACT;CACA,IAAIE,IAAUd,EAAS,IAAIa,CAAI;CAC/B,AAAIC,MAAY,KAAA,KAAWd,EAAS,IAAIa,GAAO,oBAAU,IAAI,QAAQ,CAAE;CACvE,IAAID,IAAME,EAAQ,IAAIC,CAAM;CAE5B,OADIH,MAAQ,KAAA,KAAWE,EAAQ,IAAIC,GAAS,oBAAM,IAAI,IAAI,CAAE,GACrDH;AACT;AAMA,SAAgBI,EACd,GACA,GACA,GACA,GACA,GACmB;CACnB,IAAIX,EAAO,gBAAgB,KAAA,KAAaA,EAAO,cAAc,KAAA,KAAaA,EAAO,cAAc,KAAA,GAC7F,OAAO,CAAC;CAEV,IAAMI,IAAQN,EAASE,CAAM,GACvBO,IAAMD,EAAOE,GAAME,GAAQN,CAAK,GAChCL,IAAM;EACVa;EACAC,KAAoB;EACpBC,EAAiB;EACjBlB,EAAOI,EAAO,WAAW;EACzBJ,EAAOI,EAAO,SAAS;EACvBJ,EAAOI,EAAO,SAAS;EACvBI,KAAS;CACX,CAAC,CAAC,KAAK,GAAG,GACNH,IAAQM,EAAI,IAAIR,CAAG;CACvB,IAAIE,MAAU,KAAA,GAAW;EACvB,IAAMc,IAAQC,EAAYR,GAAMR,GAAQY,GAAaC,CAAgB;EAGrE,AAFA,IAAQ;GAAE;GAAO,OAAOb,EAAO;GAAO,MAAMiB,EAAaF,GAAOf,CAAM;EAAE,GACpEO,EAAI,QAAQW,KAAyBX,EAAI,MAAM,GACnDA,EAAI,IAAIR,GAAKE,CAAK;CACpB,OAAO,AAAIA,EAAM,UAAUD,EAAO,UAChC,EAAM,QAAQA,EAAO,OACrB,EAAM,OAAOiB,EAAahB,EAAM,OAAOD,CAAM;CAE/C,OAAOC,EAAM;AACf"}
@@ -0,0 +1,15 @@
1
+ import { pathFromD as e } from "@weasel-js/geom";
2
+ import { tessellate as t } from "@weasel-js/geom/tessellate";
3
+ //#region src/renderer/cache/outlineMeshCache.ts
4
+ var n = 1 / 4096, r = 2048, i = /* @__PURE__ */ new Map();
5
+ function a(a, o) {
6
+ let s = i.get(a);
7
+ if (s !== void 0) return s;
8
+ i.size >= r && (i = /* @__PURE__ */ new Map());
9
+ let c = t(e(o), { flattenTolerance: n });
10
+ return i.set(a, c), c;
11
+ }
12
+ //#endregion
13
+ export { n as OUTLINE_FLATTEN_TOLERANCE, r as OUTLINE_MESH_CACHE_LIMIT, a as outlineMesh };
14
+
15
+ //# sourceMappingURL=outlineMeshCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outlineMeshCache.js","names":["OUTLINE_FLATTEN_TOLERANCE","OUTLINE_MESH_CACHE_LIMIT","cache","outlineMesh","cached","key","mesh","tessellate","pathFromD","d"],"sources":["../../../src/renderer/cache/outlineMeshCache.ts"],"sourcesContent":["/**\n * Tessellated glyph outlines, in em space.\n *\n * This is the half of the outline text tier that is expensive: parsing `d`\n * into a path and running earcut over it costs far more than the per-instance\n * transform that follows. It is also the half that does not vary — em space\n * is unit-scale and baseline-relative, so the same glyph of the same face is\n * the same triangles at every size, position and zoom. Tessellate once, keep\n * it, and pay only a scale-and-translate per occurrence.\n *\n * That is why the renderer transforms cached vertices on the CPU and appends\n * them into one shared buffer rather than giving each glyph its own model\n * matrix: a per-glyph matrix would mean a draw call per glyph, throwing away\n * the batching the atlas tier already has, in exchange for saving an\n * arithmetic pass over a few hundred vertices.\n *\n * ### Flatten tolerance\n *\n * Tessellating once means committing to a curve tolerance once, and em space\n * makes that a clean tradeoff rather than a guess: an error of `T` em shows\n * up as `T × fontSize × viewScale` screen pixels. At 1/4096 em, a glyph would\n * have to reach ~4000 screen pixels tall before the flattening error covered\n * a single pixel — well past any size a document is read at, and far enough\n * past the tier's own threshold that the two never interact.\n *\n * ### Bound\n *\n * A plain `Map` with a cap and wholesale eviction. Glyph tessellations are\n * small (a few hundred vertices) and the working set is a charset, not a\n * document — the cap exists so a page that cycles through many faces cannot\n * grow without limit, not because pressure is expected. Wholesale rather than\n * LRU because the refill cost is bounded by what is actually on screen, and\n * an LRU's bookkeeping would cost more than the misses it avoids.\n */\n\nimport { pathFromD } from '@weasel-js/geom';\nimport { tessellate, type Mesh } from '@weasel-js/geom/tessellate';\n\n/** Curve flattening tolerance for glyph outlines, in em. See the header. */\nexport const OUTLINE_FLATTEN_TOLERANCE = 1 / 4096;\n\n/** Cached glyph tessellations before the cache is dropped wholesale. */\nexport const OUTLINE_MESH_CACHE_LIMIT = 2048;\n\nlet cache = new Map<string, Mesh>();\n\n/**\n * The em-space tessellation of one glyph.\n *\n * `key` identifies the glyph — face identity plus codepoint, assembled by\n * `layoutRuns`. `d` is only read on a miss, so passing the path data on every\n * call costs nothing; it is already in hand from the same source.\n */\nexport function outlineMesh(key: string, d: string): Mesh {\n const cached = cache.get(key);\n if (cached !== undefined) return cached;\n if (cache.size >= OUTLINE_MESH_CACHE_LIMIT) cache = new Map();\n const mesh = tessellate(pathFromD(d), { flattenTolerance: OUTLINE_FLATTEN_TOLERANCE });\n cache.set(key, mesh);\n return mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetOutlineMeshCacheForTests(): void {\n cache = new Map();\n}\n"],"mappings":";;;AAuCA,IAAaA,IAA4B,IAAI,MAGhCC,IAA2B,MAEpCC,oBAAQ,IAAI,IAAkB;AASlC,SAAgBC,EAAY,GAAa,GAAiB;CACxD,IAAMC,IAASF,EAAM,IAAIG,CAAG;CAC5B,IAAID,MAAW,KAAA,GAAW,OAAOA;CACjC,AAAIF,EAAM,QAAQD,MAA0B,oBAAQ,IAAI,IAAI;CAC5D,IAAMK,IAAOC,EAAWC,EAAUC,CAAC,GAAG,EAAE,kBAAkBT,EAA0B,CAAC;CAErF,OADAE,EAAM,IAAIG,GAAKC,CAAI,GACZA;AACT"}
@@ -0,0 +1,31 @@
1
+ import { tessellateStroke as e } from "../../features/paths/tessellate/stroke.js";
2
+ import { OUTLINE_FLATTEN_TOLERANCE as t } from "./outlineMeshCache.js";
3
+ import { pathFromD as n } from "@weasel-js/geom";
4
+ //#region src/renderer/cache/outlineStrokeMeshCache.ts
5
+ var r = 2048, i = 1 / 1024, a = /* @__PURE__ */ new Map();
6
+ function o(e) {
7
+ return Math.round(e / i) * i;
8
+ }
9
+ function s(i, o, s, c) {
10
+ if (!(s > 0)) return null;
11
+ let l = [
12
+ i,
13
+ s,
14
+ c.join ?? "miter",
15
+ c.cap ?? "butt",
16
+ c.miterLimit ?? "",
17
+ c.align ?? "center",
18
+ (c.dash ?? []).join(",")
19
+ ].join("|"), u = a.get(l);
20
+ if (u !== void 0) return u.indices.length === 0 ? null : u;
21
+ a.size >= r && (a = /* @__PURE__ */ new Map());
22
+ let d = e(n(o), {
23
+ ...c,
24
+ width: s
25
+ }, { flattenTolerance: t });
26
+ return a.set(l, d), d.indices.length === 0 ? null : d;
27
+ }
28
+ //#endregion
29
+ export { r as OUTLINE_STROKE_MESH_CACHE_LIMIT, s as outlineStrokeMesh, o as quantizeEmWidth };
30
+
31
+ //# sourceMappingURL=outlineStrokeMeshCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outlineStrokeMeshCache.js","names":["OUTLINE_STROKE_MESH_CACHE_LIMIT","WIDTH_QUANTUM","cache","quantizeEmWidth","emWidth","outlineStrokeMesh","key","glyphKey","stroke","cached","mesh","tessellateStroke","pathFromD","d","OUTLINE_FLATTEN_TOLERANCE"],"sources":["../../../src/renderer/cache/outlineStrokeMeshCache.ts"],"sourcesContent":["/**\n * Tessellated glyph *outlines' strokes*, in em space.\n *\n * The sibling of `outlineMeshCache`, and cached for the same reason: parsing\n * `d` and tessellating a ribbon costs far more than the per-instance\n * transform that follows, and em space is size- and position-independent, so\n * one tessellation serves every occurrence of that glyph.\n *\n * ### Why the width is in the key\n *\n * A fill mesh is the same triangles at every size. A stroke's is not — the\n * ribbon's width relative to the glyph decides the geometry, so the em-space\n * mesh depends on `strokeWidth / fontSize`. That ratio is a property of the\n * run's style, not of the frame, so it is stable across frames and makes a\n * perfectly good cache key; what it is *not* is free, so a document that\n * animates stroke width or font size will miss every frame. That is the same\n * bargain `tessellate` makes everywhere else, and it is the reason the width\n * is quantized before it reaches the key: neighbouring sub-quantum widths\n * would otherwise each get their own entry and evict each other.\n *\n * Joins, caps, miter limit, alignment and dash all change the ribbon too, so\n * they are in the key as well — assembled by the caller, which already has\n * the `Stroke` in hand.\n */\n\nimport { pathFromD } from '@weasel-js/geom';\nimport { tessellateStroke } from 'features/paths/tessellate/stroke';\nimport type { Stroke } from '@weasel-js/paint';\nimport type { Mesh } from '@weasel-js/geom/tessellate';\nimport { OUTLINE_FLATTEN_TOLERANCE } from './outlineMeshCache';\n\n/** Cached ribbons before the cache is dropped wholesale. Matches the fill\n * cache's cap: the working set is a charset times the handful of stroke\n * widths a document actually uses. */\nexport const OUTLINE_STROKE_MESH_CACHE_LIMIT = 2048;\n\n/**\n * Em-width quantum. 1/1024 em is finer than any width a reader can\n * distinguish at the sizes this tier serves — a 0.001 em difference is a\n * fifth of a screen pixel on 200px text — and coarse enough that a slider\n * dragged across a range lands on a bounded set of keys.\n */\nconst WIDTH_QUANTUM = 1 / 1024;\n\nlet cache = new Map<string, Mesh>();\n\n/** Quantized em width, exported so the key builder and the tessellator agree\n * on the number rather than each rounding for themselves. */\nexport function quantizeEmWidth(emWidth: number): number {\n return Math.round(emWidth / WIDTH_QUANTUM) * WIDTH_QUANTUM;\n}\n\n/**\n * The em-space stroke tessellation of one glyph.\n *\n * `glyphKey` identifies the glyph (face identity plus codepoint, assembled by\n * `layoutRuns`); `emWidth` is the stroke width divided by the run's font\n * size, already quantized. `d` is only read on a miss.\n *\n * Returns `null` when the ribbon has no area — a zero or negative width, or a\n * glyph whose path is empty (a space).\n */\nexport function outlineStrokeMesh(\n glyphKey: string,\n d: string,\n emWidth: number,\n stroke: Stroke,\n): Mesh | null {\n if (!(emWidth > 0)) return null;\n const key = [\n glyphKey, emWidth, stroke.join ?? 'miter', stroke.cap ?? 'butt',\n stroke.miterLimit ?? '', stroke.align ?? 'center', (stroke.dash ?? []).join(','),\n ].join('|');\n\n const cached = cache.get(key);\n if (cached !== undefined) return cached.indices.length === 0 ? null : cached;\n if (cache.size >= OUTLINE_STROKE_MESH_CACHE_LIMIT) cache = new Map();\n\n const mesh = tessellateStroke(\n pathFromD(d),\n { ...stroke, width: emWidth },\n { flattenTolerance: OUTLINE_FLATTEN_TOLERANCE },\n );\n cache.set(key, mesh);\n return mesh.indices.length === 0 ? null : mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetOutlineStrokeMeshCacheForTests(): void {\n cache = new Map();\n}\n"],"mappings":";;;;AAkCA,IAAaA,IAAkC,MAQzCC,IAAgB,IAAI,MAEtBC,oBAAQ,IAAI,IAAkB;AAIlC,SAAgBC,EAAgB,GAAyB;CACvD,OAAO,KAAK,MAAMC,IAAUH,CAAa,IAAIA;AAC/C;AAYA,SAAgBI,EACd,GACA,GACA,GACA,GACa;CACb,IAAI,EAAED,IAAU,IAAI,OAAO;CAC3B,IAAME,IAAM;EACVC;EAAUH;EAASI,EAAO,QAAQ;EAASA,EAAO,OAAO;EACzDA,EAAO,cAAc;EAAIA,EAAO,SAAS;GAAWA,EAAO,QAAQ,CAAC,EAAA,CAAG,KAAK,GAAG;CACjF,CAAC,CAAC,KAAK,GAAG,GAEJC,IAASP,EAAM,IAAII,CAAG;CAC5B,IAAIG,MAAW,KAAA,GAAW,OAAOA,EAAO,QAAQ,WAAW,IAAI,OAAOA;CACtE,AAAIP,EAAM,QAAQF,MAAiC,oBAAQ,IAAI,IAAI;CAEnE,IAAMU,IAAOC,EACXC,EAAUC,CAAC,GACX;EAAE,GAAGL;EAAQ,OAAOJ;CAAQ,GAC5B,EAAE,kBAAkBU,EAA0B,CAChD;CAEA,OADAZ,EAAM,IAAII,GAAKI,CAAI,GACZA,EAAK,QAAQ,WAAW,IAAI,OAAOA;AAC5C"}
@@ -0,0 +1,44 @@
1
+ import { resolveStrokeWidth as e, tessellateStroke as t } from "../../features/paths/tessellate/stroke.js";
2
+ import { strokeInsets as n } from "../../core/markerInset.js";
3
+ //#region src/renderer/cache/strokeMeshCache.ts
4
+ var r = 8, i = 1 / 8;
5
+ function a(e, t) {
6
+ if (!(e > 0) || !(t > 0) || !Number.isFinite(t)) return t;
7
+ let n = Math.ceil(Math.LN2 / (2 * Math.log1p(i / e)));
8
+ return 2 ** (Math.round(Math.log2(t) * n) / n);
9
+ }
10
+ var o = /* @__PURE__ */ new WeakMap();
11
+ function s(t, r) {
12
+ let i = e(t.width ?? 1, 1), a = n(t, i);
13
+ return [
14
+ i,
15
+ t.cap ?? "butt",
16
+ t.join ?? "miter",
17
+ t.miterLimit ?? "",
18
+ t.align ?? "center",
19
+ (t.dash ?? []).join(","),
20
+ t.varyingWidthJoinThreshold ?? "",
21
+ r ?? "",
22
+ a.start,
23
+ a.end
24
+ ].join("|");
25
+ }
26
+ function c(i, a, c) {
27
+ let l = o.get(i);
28
+ l === void 0 && (l = /* @__PURE__ */ new Map(), o.set(i, l));
29
+ let u = s(a, c), d = l.get(u);
30
+ if (d !== void 0 && d.vertexWidths === a.vertexWidths) return d.mesh;
31
+ let f = e(a.width ?? 1, 1), p = n(a, f), m = t(i, a, {
32
+ flattenTolerance: c,
33
+ startInset: p.start,
34
+ endInset: p.end
35
+ });
36
+ return d === void 0 && l.size >= r && l.clear(), l.set(u, {
37
+ mesh: m,
38
+ vertexWidths: a.vertexWidths
39
+ }), m;
40
+ }
41
+ //#endregion
42
+ export { r as STROKE_CONFIGS_PER_PATH, a as quantizeStrokeScale, c as strokeMesh };
43
+
44
+ //# sourceMappingURL=strokeMeshCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strokeMeshCache.js","names":["STROKE_CONFIGS_PER_PATH","PX_WIDTH_TOLERANCE","quantizeStrokeScale","px","scale","stepsPerOctave","cache","configKey","width","resolveStrokeWidth","stroke","insets","strokeInsets","flattenTolerance","strokeMesh","byConfig","path","key","entry","mesh","tessellateStroke"],"sources":["../../../src/renderer/cache/strokeMeshCache.ts"],"sourcesContent":["/**\n * Tessellated stroke ribbons for scene paths, keyed on `Path` identity.\n *\n * The sibling of `cache.ts` (fills) and `outlineStrokeMeshCache.ts` (glyph\n * ribbons in em space), and it inherits their contract: identity, not content.\n * A `Path` rebuilt with equal coords is a distinct entry.\n *\n * Design: `docs/superpowers/specs/2026-08-15-stroke-ribbon-cache-design.md`.\n */\n\nimport type { Path } from '@weasel-js/core';\nimport type { Stroke } from '@weasel-js/paint';\nimport { tessellateStroke, resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport { strokeInsets } from '../../core/markerInset';\nimport type { Mesh } from '@weasel-js/geom/tessellate';\n\n/**\n * Distinct stroke configurations kept per path before that path's map is\n * dropped wholesale. A document uses a handful; a width slider passes this on\n * its first drag and then degrades to tessellating every frame, which is what\n * it did before this cache existed.\n */\nexport const STROKE_CONFIGS_PER_PATH = 8;\n\n/** Screen-pixel bound on how far a quantized `{ px }` ribbon's width may\n * drift from the width asked for: each edge moves at most half of it. */\nconst PX_WIDTH_TOLERANCE = 1 / 8;\n\n/**\n * `scale` snapped to a log-spaced grid, for resolving a `{ px }` width against.\n * Resolving against the raw scale gives a continuous zoom a new cache key every\n * frame. The grid is fine enough that the resolved ribbon stays within\n * `PX_WIDTH_TOLERANCE` screen pixels of `px`, so it is coarser for thin\n * strokes, and powers of two land on it exactly.\n */\nexport function quantizeStrokeScale(px: number, scale: number): number {\n if (!(px > 0) || !(scale > 0) || !Number.isFinite(scale)) return scale;\n const stepsPerOctave = Math.ceil(Math.LN2 / (2 * Math.log1p(PX_WIDTH_TOLERANCE / px)));\n return 2 ** (Math.round(Math.log2(scale) * stepsPerOctave) / stepsPerOctave);\n}\n\ninterface StrokeEntry {\n readonly mesh: Mesh;\n /** Compared by reference — long enough that stringifying it per frame would\n * cost what the cache saves. */\n readonly vertexWidths: number[] | undefined;\n}\n\nlet cache = new WeakMap<Path, Map<string, StrokeEntry>>();\n\n/** The stroke parameters that change the ribbon's geometry. `paint` and\n * `vertexColors` are absent on purpose: both are applied over the same\n * triangles at draw time. Marker *identity* is absent too — only the\n * resolved trim distance affects these triangles, so two heads with the\n * same inset share one entry. */\nfunction configKey(stroke: Stroke, flattenTolerance: number | undefined): string {\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n const insets = strokeInsets(stroke, width);\n return [\n width,\n stroke.cap ?? 'butt',\n stroke.join ?? 'miter',\n stroke.miterLimit ?? '',\n stroke.align ?? 'center',\n (stroke.dash ?? []).join(','),\n stroke.varyingWidthJoinThreshold ?? '',\n flattenTolerance ?? '',\n insets.start,\n insets.end,\n ].join('|');\n}\n\n/** The tessellated ribbon for `path` under `stroke`. The same `Mesh` object\n * comes back for as long as the entry lives. */\nexport function strokeMesh(\n path: Path,\n stroke: Stroke,\n flattenTolerance: number | undefined,\n): Mesh {\n let byConfig = cache.get(path);\n if (byConfig === undefined) {\n byConfig = new Map<string, StrokeEntry>();\n cache.set(path, byConfig);\n }\n\n const key = configKey(stroke, flattenTolerance);\n const entry = byConfig.get(key);\n if (entry !== undefined && entry.vertexWidths === stroke.vertexWidths) {\n return entry.mesh;\n }\n\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n const insets = strokeInsets(stroke, width);\n const mesh = tessellateStroke(path, stroke, {\n flattenTolerance,\n startInset: insets.start,\n endInset: insets.end,\n });\n // Only a new key grows the map; replacing one under a churning\n // `vertexWidths` must not evict the other configurations alongside it.\n if (entry === undefined && byConfig.size >= STROKE_CONFIGS_PER_PATH) byConfig.clear();\n byConfig.set(key, { mesh, vertexWidths: stroke.vertexWidths });\n return mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetStrokeMeshCacheForTests(): void {\n cache = new WeakMap();\n}\n"],"mappings":";;;AAsBA,IAAaA,IAA0B,GAIjCC,IAAqB,IAAI;AAS/B,SAAgBC,EAAoB,GAAY,GAAuB;CACrE,IAAI,EAAEC,IAAK,MAAM,EAAEC,IAAQ,MAAM,CAAC,OAAO,SAASA,CAAK,GAAG,OAAOA;CACjE,IAAMC,IAAiB,KAAK,KAAK,KAAK,OAAO,IAAI,KAAK,MAAMJ,IAAqBE,CAAE,EAAE;CACrF,OAAO,MAAM,KAAK,MAAM,KAAK,KAAKC,CAAK,IAAIC,CAAc,IAAIA;AAC/D;AASA,IAAIC,oBAAQ,IAAI,QAAwC;AAOxD,SAASC,EAAU,GAAgB,GAA8C;CAC/E,IAAMC,IAAQC,EAAmBC,EAAO,SAAS,GAAG,CAAC,GAC/CC,IAASC,EAAaF,GAAQF,CAAK;CACzC,OAAO;EACLA;EACAE,EAAO,OAAO;EACdA,EAAO,QAAQ;EACfA,EAAO,cAAc;EACrBA,EAAO,SAAS;GACfA,EAAO,QAAQ,CAAC,EAAA,CAAG,KAAK,GAAG;EAC5BA,EAAO,6BAA6B;EACpCG,KAAoB;EACpBF,EAAO;EACPA,EAAO;CACT,CAAC,CAAC,KAAK,GAAG;AACZ;AAIA,SAAgBG,EACd,GACA,GACA,GACM;CACN,IAAIC,IAAWT,EAAM,IAAIU,CAAI;CAC7B,AAAID,MAAa,KAAA,MACf,oBAAW,IAAI,IAAyB,GACxCT,EAAM,IAAIU,GAAMD,CAAQ;CAG1B,IAAME,IAAMV,EAAUG,GAAQG,CAAgB,GACxCK,IAAQH,EAAS,IAAIE,CAAG;CAC9B,IAAIC,MAAU,KAAA,KAAaA,EAAM,iBAAiBR,EAAO,cACvD,OAAOQ,EAAM;CAGf,IAAMV,IAAQC,EAAmBC,EAAO,SAAS,GAAG,CAAC,GAC/CC,IAASC,EAAaF,GAAQF,CAAK,GACnCW,IAAOC,EAAiBJ,GAAMN,GAAQ;EAC1C;EACA,YAAYC,EAAO;EACnB,UAAUA,EAAO;CACnB,CAAC;CAKD,OAFIO,MAAU,KAAA,KAAaH,EAAS,QAAQf,KAAyBe,EAAS,MAAM,GACpFA,EAAS,IAAIE,GAAK;EAAE;EAAM,cAAcP,EAAO;CAAa,CAAC,GACtDS;AACT"}