@jbrowse/render-core 5.0.0-beta.1 → 5.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/RenderCanvas.d.ts +2 -2
- package/esm/RenderLifecycleMixin.d.ts +52 -20
- package/esm/RenderLifecycleMixin.js +89 -23
- package/esm/canvas2dUtils.d.ts +90 -23
- package/esm/canvas2dUtils.js +119 -36
- package/esm/colorRampLut.d.ts +5 -5
- package/esm/colorRampLut.js +6 -6
- package/esm/computePipeline.d.ts +14 -0
- package/esm/computePipeline.js +62 -0
- package/esm/contractReports.d.ts +54 -0
- package/esm/contractReports.js +112 -0
- package/esm/coverageBand.d.ts +13 -8
- package/esm/coverageBand.js +15 -5
- package/esm/coverageBandBuffers.d.ts +2 -9
- package/esm/coverageBandBuffers.js +1 -13
- package/esm/createRenderingBackend.d.ts +14 -18
- package/esm/createRenderingBackend.js +4 -2
- package/esm/displayPhase.d.ts +83 -104
- package/esm/displayPhase.js +42 -82
- package/esm/encodeMemo.d.ts +14 -0
- package/esm/encodeMemo.js +48 -0
- package/esm/gpuContextLostError.d.ts +30 -0
- package/esm/gpuContextLostError.js +40 -0
- package/esm/gpuDevice.d.ts +29 -10
- package/esm/gpuDevice.js +35 -16
- package/esm/graphicsCapabilities.d.ts +27 -19
- package/esm/graphicsCapabilities.js +40 -18
- package/esm/hal/createHal.d.ts +4 -5
- package/esm/hal/createHal.js +14 -4
- package/esm/hal/deviceGpuCache.d.ts +25 -30
- package/esm/hal/deviceGpuCache.js +88 -97
- package/esm/hal/gpuHalBase.d.ts +5 -4
- package/esm/hal/gpuHalBase.js +25 -14
- package/esm/hal/index.d.ts +2 -2
- package/esm/hal/index.js +1 -1
- package/esm/hal/mockHal.d.ts +15 -10
- package/esm/hal/mockHal.js +31 -18
- package/esm/hal/oomReporter.d.ts +7 -0
- package/esm/hal/oomReporter.js +10 -0
- package/esm/hal/passIds.d.ts +8 -7
- package/esm/hal/passIds.js +11 -10
- package/esm/hal/regionRegistry.d.ts +0 -1
- package/esm/hal/regionRegistry.js +3 -15
- package/esm/hal/types.d.ts +55 -18
- package/esm/hal/webgl2Hal.d.ts +23 -6
- package/esm/hal/webgl2Hal.js +161 -155
- package/esm/hal/webgpuHal.d.ts +29 -13
- package/esm/hal/webgpuHal.js +221 -153
- package/esm/installUpload.d.ts +16 -3
- package/esm/installUpload.js +13 -41
- package/esm/instanceCache.d.ts +10 -7
- package/esm/instanceCache.js +14 -15
- package/esm/instancePass.d.ts +2 -1
- package/esm/mapUploadSync.d.ts +2 -10
- package/esm/mapUploadSync.js +2 -3
- package/esm/marks/barMark.d.ts +30 -0
- package/esm/marks/barMark.js +149 -0
- package/esm/marks/colorFill.d.ts +17 -0
- package/esm/marks/colorFill.js +26 -0
- package/esm/marks/drawAgainstHit.d.ts +113 -0
- package/esm/marks/drawAgainstHit.js +407 -0
- package/esm/marks/ellipseDistance.d.ts +10 -0
- package/esm/marks/ellipseDistance.js +136 -0
- package/esm/marks/glyphPaint.d.ts +36 -0
- package/esm/marks/glyphPaint.js +77 -0
- package/esm/marks/index.d.ts +33 -0
- package/esm/marks/index.js +20 -0
- package/esm/marks/lineMark.d.ts +37 -0
- package/esm/marks/lineMark.js +416 -0
- package/esm/marks/linkMark.d.ts +76 -0
- package/esm/marks/linkMark.js +585 -0
- package/esm/marks/markBackend.d.ts +118 -0
- package/esm/marks/markBackend.js +196 -0
- package/esm/marks/markHit.d.ts +32 -0
- package/esm/marks/markHit.js +61 -0
- package/esm/marks/markInk.d.ts +18 -0
- package/esm/marks/markInk.js +71 -0
- package/esm/marks/markPaint.d.ts +14 -0
- package/esm/marks/markPaint.js +32 -0
- package/esm/marks/markPlan.d.ts +25 -0
- package/esm/marks/markPlan.js +20 -0
- package/esm/marks/markRamp.d.ts +72 -0
- package/esm/marks/markRamp.js +197 -0
- package/esm/marks/nearestMarkHit.d.ts +55 -0
- package/esm/marks/nearestMarkHit.js +158 -0
- package/esm/marks/pathRecorder.d.ts +14 -0
- package/esm/marks/pathRecorder.js +80 -0
- package/esm/marks/pointMark.d.ts +42 -0
- package/esm/marks/pointMark.js +125 -0
- package/esm/marks/rowLane.d.ts +39 -0
- package/esm/marks/rowLane.js +41 -0
- package/esm/marks/rowSpanIndex.d.ts +29 -0
- package/esm/marks/rowSpanIndex.js +141 -0
- package/esm/marks/rowTable.d.ts +41 -0
- package/esm/marks/rowTable.js +75 -0
- package/esm/marks/ruleMark.d.ts +21 -0
- package/esm/marks/ruleMark.js +91 -0
- package/esm/marks/spanMark.d.ts +42 -0
- package/esm/marks/spanMark.js +81 -0
- package/esm/marks/types.d.ts +261 -0
- package/esm/marks/types.js +175 -0
- package/esm/marks/valueScale.d.ts +23 -0
- package/esm/marks/valueScale.js +11 -0
- package/esm/namedReactions.d.ts +3 -4
- package/esm/namedReactions.js +3 -4
- package/esm/perRegionRenderingBackend.d.ts +21 -3
- package/esm/perRegionRenderingBackend.js +37 -3
- package/esm/regionDataMap.d.ts +2 -2
- package/esm/regionDataMap.js +25 -23
- package/esm/renderBlock.d.ts +14 -0
- package/esm/renderBlock.js +25 -0
- package/esm/renderingBackendBase.d.ts +20 -14
- package/esm/renderingBackendBase.js +12 -7
- package/esm/scoreScale.d.ts +27 -0
- package/esm/scoreScale.js +88 -0
- package/esm/shaders/barMark.generated.d.ts +3 -0
- package/esm/shaders/barMark.generated.js +7 -0
- package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/barMark.glsl.generated.js +4 -0
- package/esm/shaders/barMark.iface.generated.d.ts +90 -0
- package/esm/shaders/barMark.iface.generated.js +205 -0
- package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/barMark.wgsl.generated.js +3 -0
- package/esm/shaders/capsule.js.generated.d.ts +1 -0
- package/esm/shaders/capsule.js.generated.js +11 -0
- package/esm/shaders/clipStrip.generated.d.ts +2 -0
- package/esm/shaders/clipStrip.generated.js +4 -0
- package/esm/shaders/clipStrip.js.generated.d.ts +1 -0
- package/esm/shaders/clipStrip.js.generated.js +21 -0
- package/esm/shaders/colorRampLut.js.generated.d.ts +1 -0
- package/esm/shaders/colorRampLut.js.generated.js +17 -0
- package/esm/shaders/coverageBar.generated.d.ts +2 -3
- package/esm/shaders/coverageBar.generated.js +4 -3
- package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageBar.glsl.generated.js +4 -0
- package/esm/shaders/coverageBar.iface.generated.js +1 -1
- package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
- package/esm/shaders/coverageClip.generated.d.ts +3 -0
- package/esm/shaders/coverageClip.generated.js +7 -0
- package/esm/shaders/coverageClip.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageClip.glsl.generated.js +4 -0
- package/esm/shaders/coverageClip.iface.generated.d.ts +85 -0
- package/esm/shaders/coverageClip.iface.generated.js +114 -0
- package/esm/shaders/coverageClip.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageClip.wgsl.generated.js +3 -0
- package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
- package/esm/shaders/coverageIndicator.generated.js +4 -3
- package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
- package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
- package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
- package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
- package/esm/shaders/coverageInterbase.generated.js +4 -3
- package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
- package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
- package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
- package/esm/shaders/coverageMod.generated.d.ts +2 -3
- package/esm/shaders/coverageMod.generated.js +4 -3
- package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageMod.glsl.generated.js +4 -0
- package/esm/shaders/coverageMod.iface.generated.js +1 -1
- package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
- package/esm/shaders/coverageSnp.generated.d.ts +2 -3
- package/esm/shaders/coverageSnp.generated.js +4 -3
- package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
- package/esm/shaders/coverageSnp.iface.generated.js +1 -1
- package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
- package/esm/shaders/curveDistance.js.generated.d.ts +5 -0
- package/esm/shaders/curveDistance.js.generated.js +87 -0
- package/esm/shaders/hpmath.js.generated.d.ts +2 -1
- package/esm/shaders/hpmath.js.generated.js +5 -2
- package/esm/shaders/lineCenterMark.generated.d.ts +3 -0
- package/esm/shaders/lineCenterMark.generated.js +7 -0
- package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/lineCenterMark.glsl.generated.js +4 -0
- package/esm/shaders/lineCenterMark.iface.generated.d.ts +104 -0
- package/esm/shaders/lineCenterMark.iface.generated.js +237 -0
- package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/lineCenterMark.wgsl.generated.js +3 -0
- package/esm/shaders/lineCommon.generated.d.ts +2 -0
- package/esm/shaders/lineCommon.generated.js +4 -0
- package/esm/shaders/lineStepMark.generated.d.ts +3 -0
- package/esm/shaders/lineStepMark.generated.js +7 -0
- package/esm/shaders/lineStepMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/lineStepMark.glsl.generated.js +4 -0
- package/esm/shaders/lineStepMark.iface.generated.d.ts +98 -0
- package/esm/shaders/lineStepMark.iface.generated.js +225 -0
- package/esm/shaders/lineStepMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/lineStepMark.wgsl.generated.js +3 -0
- package/esm/shaders/linkMark.consts.generated.d.ts +14 -0
- package/esm/shaders/linkMark.consts.generated.js +16 -0
- package/esm/shaders/linkMark.generated.d.ts +4 -0
- package/esm/shaders/linkMark.generated.js +8 -0
- package/esm/shaders/linkMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/linkMark.glsl.generated.js +4 -0
- package/esm/shaders/linkMark.iface.generated.d.ts +142 -0
- package/esm/shaders/linkMark.iface.generated.js +1829 -0
- package/esm/shaders/linkMark.js.generated.d.ts +7 -0
- package/esm/shaders/linkMark.js.generated.js +159 -0
- package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/linkMark.wgsl.generated.js +3 -0
- package/esm/shaders/markColor.generated.d.ts +9 -0
- package/esm/shaders/markColor.generated.js +11 -0
- package/esm/shaders/pointGlyph.js.generated.d.ts +2 -0
- package/esm/shaders/pointGlyph.js.generated.js +15 -0
- package/esm/shaders/pointMark.consts.generated.d.ts +7 -0
- package/esm/shaders/pointMark.consts.generated.js +9 -0
- package/esm/shaders/pointMark.generated.d.ts +4 -0
- package/esm/shaders/pointMark.generated.js +8 -0
- package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/pointMark.glsl.generated.js +4 -0
- package/esm/shaders/pointMark.iface.generated.d.ts +98 -0
- package/esm/shaders/pointMark.iface.generated.js +219 -0
- package/esm/shaders/pointMark.js.generated.d.ts +3 -0
- package/esm/shaders/pointMark.js.generated.js +93 -0
- package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/pointMark.wgsl.generated.js +3 -0
- package/esm/shaders/rowRect.generated.d.ts +0 -1
- package/esm/shaders/rowRect.generated.js +0 -1
- package/esm/shaders/rowTable.generated.d.ts +1 -0
- package/esm/shaders/rowTable.generated.js +3 -0
- package/esm/shaders/rowTable.js.generated.d.ts +5 -0
- package/esm/shaders/rowTable.js.generated.js +29 -0
- package/esm/shaders/scoreScale.generated.d.ts +2 -0
- package/esm/shaders/scoreScale.generated.js +4 -0
- package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
- package/esm/shaders/scoreScale.js.generated.js +50 -23
- package/esm/shaders/spanMark.generated.d.ts +3 -0
- package/esm/shaders/spanMark.generated.js +7 -0
- package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/spanMark.glsl.generated.js +4 -0
- package/esm/shaders/spanMark.iface.generated.d.ts +81 -0
- package/esm/shaders/spanMark.iface.generated.js +215 -0
- package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/spanMark.wgsl.generated.js +3 -0
- package/esm/sharedBackendKey.d.ts +18 -0
- package/esm/{keyedRenderingBackend.js → sharedBackendKey.js} +5 -0
- package/esm/slangPass.d.ts +18 -11
- package/esm/slangPass.js +12 -4
- package/esm/useGraphicsCapabilities.d.ts +1 -1
- package/esm/useGraphicsCapabilities.js +1 -1
- package/esm/useRenderingBackend.d.ts +13 -13
- package/esm/useRenderingBackend.js +58 -20
- package/esm/webgpuUtils.d.ts +3 -11
- package/esm/webgpuUtils.js +12 -33
- package/package.json +32 -7
- package/src/shaders/antialias.slang +46 -0
- package/src/shaders/arcHull.test.ts +267 -0
- package/src/shaders/barMark.generated.ts +11 -0
- package/src/shaders/barMark.glsl.generated.ts +6 -0
- package/src/shaders/barMark.iface.generated.ts +285 -0
- package/src/shaders/barMark.slang +167 -0
- package/src/shaders/barMark.wgsl.generated.ts +4 -0
- package/src/shaders/capsule.js.generated.ts +14 -0
- package/src/shaders/capsule.slang +12 -4
- package/src/shaders/clipStrip.generated.ts +6 -0
- package/src/shaders/clipStrip.js.generated.ts +22 -0
- package/src/shaders/clipStrip.slang +34 -0
- package/src/shaders/clipStrip.test.ts +39 -0
- package/src/shaders/colorPack.slang +5 -1
- package/src/shaders/colorRampLut.js.generated.ts +22 -0
- package/src/shaders/colorRampLut.slang +15 -1
- package/src/shaders/coverageBand.slang +64 -32
- package/src/shaders/coverageBar.generated.ts +6 -5
- package/src/shaders/coverageBar.glsl.generated.ts +6 -0
- package/src/shaders/coverageBar.iface.generated.ts +1 -1
- package/src/shaders/coverageBar.slang +10 -10
- package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
- package/src/shaders/coverageClip.generated.ts +11 -0
- package/src/shaders/coverageClip.glsl.generated.ts +6 -0
- package/src/shaders/coverageClip.iface.generated.ts +172 -0
- package/src/shaders/coverageClip.slang +38 -0
- package/src/shaders/coverageClip.wgsl.generated.ts +4 -0
- package/src/shaders/coverageIndicator.generated.ts +6 -5
- package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
- package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
- package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
- package/src/shaders/coverageInterbase.generated.ts +6 -5
- package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
- package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
- package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
- package/src/shaders/coverageMod.generated.ts +6 -5
- package/src/shaders/coverageMod.glsl.generated.ts +6 -0
- package/src/shaders/coverageMod.iface.generated.ts +1 -1
- package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
- package/src/shaders/coverageSnp.generated.ts +6 -5
- package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
- package/src/shaders/coverageSnp.iface.generated.ts +1 -1
- package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
- package/src/shaders/curveDistance.js.generated.ts +91 -0
- package/src/shaders/curveDistance.slang +265 -0
- package/src/shaders/hpClampFloor.test.ts +87 -0
- package/src/shaders/hpmath.js.generated.ts +6 -2
- package/src/shaders/hpmath.slang +100 -48
- package/src/shaders/insetValueScale.test.ts +67 -0
- package/src/shaders/lineCenterMark.generated.ts +11 -0
- package/src/shaders/lineCenterMark.glsl.generated.ts +6 -0
- package/src/shaders/lineCenterMark.iface.generated.ts +328 -0
- package/src/shaders/lineCenterMark.slang +127 -0
- package/src/shaders/lineCenterMark.wgsl.generated.ts +4 -0
- package/src/shaders/lineCommon.generated.ts +6 -0
- package/src/shaders/lineCommon.slang +102 -0
- package/src/shaders/lineStepMark.generated.ts +11 -0
- package/src/shaders/lineStepMark.glsl.generated.ts +6 -0
- package/src/shaders/lineStepMark.iface.generated.ts +311 -0
- package/src/shaders/lineStepMark.slang +125 -0
- package/src/shaders/lineStepMark.wgsl.generated.ts +4 -0
- package/src/shaders/linkMark.consts.generated.ts +30 -0
- package/src/shaders/linkMark.generated.ts +12 -0
- package/src/shaders/linkMark.glsl.generated.ts +6 -0
- package/src/shaders/linkMark.iface.generated.ts +1954 -0
- package/src/shaders/linkMark.js.generated.ts +167 -0
- package/src/shaders/linkMark.slang +439 -0
- package/src/shaders/linkMark.wgsl.generated.ts +4 -0
- package/src/shaders/markColor.generated.ts +20 -0
- package/src/shaders/markColor.slang +128 -0
- package/src/shaders/pointGlyph.js.generated.ts +20 -0
- package/src/shaders/pointGlyph.slang +23 -7
- package/src/shaders/pointGlyphPad.test.ts +242 -0
- package/src/shaders/pointMark.consts.generated.ts +16 -0
- package/src/shaders/pointMark.generated.ts +12 -0
- package/src/shaders/pointMark.glsl.generated.ts +6 -0
- package/src/shaders/pointMark.iface.generated.ts +304 -0
- package/src/shaders/pointMark.js.generated.ts +99 -0
- package/src/shaders/pointMark.slang +227 -0
- package/src/shaders/pointMark.wgsl.generated.ts +4 -0
- package/src/shaders/rowRect.generated.ts +0 -2
- package/src/shaders/rowRect.slang +39 -58
- package/src/shaders/rowTable.generated.ts +4 -0
- package/src/shaders/rowTable.js.generated.ts +37 -0
- package/src/shaders/rowTable.slang +98 -0
- package/src/shaders/scoreScale.generated.ts +6 -0
- package/src/shaders/scoreScale.js.generated.ts +48 -23
- package/src/shaders/scoreScale.slang +49 -55
- package/src/shaders/sdEllipse.test.ts +211 -0
- package/src/shaders/spanMark.generated.ts +11 -0
- package/src/shaders/spanMark.glsl.generated.ts +6 -0
- package/src/shaders/spanMark.iface.generated.ts +289 -0
- package/src/shaders/spanMark.slang +77 -0
- package/src/shaders/spanMark.wgsl.generated.ts +4 -0
- package/src/shaders/valueScale.slang +26 -0
- package/src/shaders/wideCircleLeg.test.ts +85 -0
- package/esm/globalRenderingBackend.d.ts +0 -90
- package/esm/globalRenderingBackend.js +0 -53
- package/esm/keyedRenderingBackend.d.ts +0 -41
package/esm/installUpload.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getType } from '@jbrowse/mobx-state-tree';
|
|
2
|
-
import {
|
|
2
|
+
import { contractReportsOn, reportContractViolation, } from './contractReports.js';
|
|
3
|
+
import { createEncodeMemo } from './encodeMemo.js';
|
|
3
4
|
import { createMapUploadSync } from './mapUploadSync.js';
|
|
4
5
|
import { isCheckedAtTheStore } from './regionDataMap.js';
|
|
5
6
|
/**
|
|
@@ -29,7 +30,7 @@ function checkPayloads(self, cells) {
|
|
|
29
30
|
}
|
|
30
31
|
if (!named.has(key)) {
|
|
31
32
|
named.add(key);
|
|
32
|
-
|
|
33
|
+
reportContractViolation('display', `${getType(self).name}: cell ${String(key)} ` +
|
|
33
34
|
`handed to installUpload is \`${String(value)}\`. A fetch answers ` +
|
|
34
35
|
'a payload or nothing; leave the key out until it has one.');
|
|
35
36
|
}
|
|
@@ -46,49 +47,20 @@ export function installUpload(self, backend, { cells, inputs, encode, render })
|
|
|
46
47
|
b.release(key);
|
|
47
48
|
},
|
|
48
49
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
upload: b => {
|
|
53
|
-
const current = own();
|
|
54
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
55
|
-
checkPayloads(self, current);
|
|
56
|
-
}
|
|
57
|
-
return sync(b, current);
|
|
58
|
-
},
|
|
59
|
-
render: b => render(b, own()),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const encoded = new Map();
|
|
63
|
-
const encodedFrom = new Map();
|
|
64
|
-
const props = inputs && computed(inputs);
|
|
65
|
-
let lastProps;
|
|
50
|
+
const own = encode
|
|
51
|
+
? createEncodeMemo(cells, inputs, encode)
|
|
52
|
+
: cells;
|
|
66
53
|
return {
|
|
67
54
|
upload: b => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
checkPayloads(self, current);
|
|
71
|
-
}
|
|
72
|
-
const p = props ? props.get() : undefined;
|
|
73
|
-
if (p !== lastProps) {
|
|
74
|
-
lastProps = p;
|
|
75
|
-
encodedFrom.clear();
|
|
76
|
-
}
|
|
77
|
-
for (const [key, data] of current) {
|
|
78
|
-
if (encodedFrom.get(key) !== data) {
|
|
79
|
-
encoded.set(key, encode(data, p, key));
|
|
80
|
-
encodedFrom.set(key, data);
|
|
81
|
-
}
|
|
55
|
+
if (contractReportsOn()) {
|
|
56
|
+
checkPayloads(self, cells());
|
|
82
57
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
return sync(b, encoded);
|
|
58
|
+
return sync(b, own());
|
|
59
|
+
},
|
|
60
|
+
render: b => render(b, own()),
|
|
61
|
+
releaseTargets: b => {
|
|
62
|
+
b.releaseOffscreenTargets();
|
|
90
63
|
},
|
|
91
|
-
render: b => render(b, encoded),
|
|
92
64
|
};
|
|
93
65
|
});
|
|
94
66
|
}
|
package/esm/instanceCache.d.ts
CHANGED
|
@@ -14,9 +14,8 @@ export interface InstanceCacheOpts<TData> {
|
|
|
14
14
|
colorOffsetWords: number;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* A
|
|
18
|
-
*
|
|
19
|
-
* other one.
|
|
17
|
+
* A cache of packed instance bytes with a geometry/color split: a recolor
|
|
18
|
+
* patches the one color lane in place instead of re-packing every other one.
|
|
20
19
|
*
|
|
21
20
|
* The split is worth having because the two inputs move on completely
|
|
22
21
|
* different schedules — geometry on an RPC refetch, colors on a `colorBy`
|
|
@@ -32,12 +31,16 @@ export interface InstanceCacheOpts<TData> {
|
|
|
32
31
|
* problem. `installUpload` exists for the same reason one
|
|
33
32
|
* layer up — an upload memo is not a hand-rolled `let`.
|
|
34
33
|
*
|
|
34
|
+
* **The geometry token is the key**, so nothing has to evict: a payload whose
|
|
35
|
+
* coordinates were replaced takes its bytes with it, and a cache shared by
|
|
36
|
+
* several displays cannot hand one display another's buffer — two displays
|
|
37
|
+
* never hold one coordinate array. That is also what lets a mark's `pack`
|
|
38
|
+
* hold one of these, a mark list being module-level and shared.
|
|
39
|
+
*
|
|
35
40
|
* The GPU re-upload still happens on a recolor (no HAL does partial buffer
|
|
36
41
|
* updates); what is skipped is the dominant CPU interleave.
|
|
37
42
|
*/
|
|
38
43
|
export declare function createInstanceCache<TData>(opts: InstanceCacheOpts<TData>): {
|
|
39
|
-
/** Packed bytes for `
|
|
40
|
-
get(
|
|
41
|
-
delete(key: number): void;
|
|
42
|
-
clear(): void;
|
|
44
|
+
/** Packed bytes for `data`, re-packing or re-coloring only as needed. */
|
|
45
|
+
get(data: TData): ArrayBuffer;
|
|
43
46
|
};
|
package/esm/instanceCache.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
3
|
-
*
|
|
4
|
-
* other one.
|
|
2
|
+
* A cache of packed instance bytes with a geometry/color split: a recolor
|
|
3
|
+
* patches the one color lane in place instead of re-packing every other one.
|
|
5
4
|
*
|
|
6
5
|
* The split is worth having because the two inputs move on completely
|
|
7
6
|
* different schedules — geometry on an RPC refetch, colors on a `colorBy`
|
|
@@ -17,19 +16,25 @@
|
|
|
17
16
|
* problem. `installUpload` exists for the same reason one
|
|
18
17
|
* layer up — an upload memo is not a hand-rolled `let`.
|
|
19
18
|
*
|
|
19
|
+
* **The geometry token is the key**, so nothing has to evict: a payload whose
|
|
20
|
+
* coordinates were replaced takes its bytes with it, and a cache shared by
|
|
21
|
+
* several displays cannot hand one display another's buffer — two displays
|
|
22
|
+
* never hold one coordinate array. That is also what lets a mark's `pack`
|
|
23
|
+
* hold one of these, a mark list being module-level and shared.
|
|
24
|
+
*
|
|
20
25
|
* The GPU re-upload still happens on a recolor (no HAL does partial buffer
|
|
21
26
|
* updates); what is skipped is the dominant CPU interleave.
|
|
22
27
|
*/
|
|
23
28
|
export function createInstanceCache(opts) {
|
|
24
29
|
const { geomToken, colors, interleave, strideWords, colorOffsetWords } = opts;
|
|
25
|
-
const cache = new
|
|
30
|
+
const cache = new WeakMap();
|
|
26
31
|
return {
|
|
27
|
-
/** Packed bytes for `
|
|
28
|
-
get(
|
|
32
|
+
/** Packed bytes for `data`, re-packing or re-coloring only as needed. */
|
|
33
|
+
get(data) {
|
|
29
34
|
const geom = geomToken(data);
|
|
30
35
|
const cols = colors(data);
|
|
31
|
-
const hit = cache.get(
|
|
32
|
-
if (hit
|
|
36
|
+
const hit = cache.get(geom);
|
|
37
|
+
if (hit) {
|
|
33
38
|
if (hit.colors !== cols) {
|
|
34
39
|
const u32 = new Uint32Array(hit.buf);
|
|
35
40
|
for (let i = 0, n = cols.length; i < n; i++) {
|
|
@@ -40,14 +45,8 @@ export function createInstanceCache(opts) {
|
|
|
40
45
|
return hit.buf;
|
|
41
46
|
}
|
|
42
47
|
const buf = interleave(data);
|
|
43
|
-
cache.set(
|
|
48
|
+
cache.set(geom, { colors: cols, buf });
|
|
44
49
|
return buf;
|
|
45
50
|
},
|
|
46
|
-
delete(key) {
|
|
47
|
-
cache.delete(key);
|
|
48
|
-
},
|
|
49
|
-
clear() {
|
|
50
|
-
cache.clear();
|
|
51
|
-
},
|
|
52
51
|
};
|
|
53
52
|
}
|
package/esm/instancePass.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ import type { GpuHal, PipelineDescriptor } from './hal';
|
|
|
5
5
|
* A pass id, the packer that fills its buffer, and the upload that joins them
|
|
6
6
|
* are three statements of one fact, and renderers kept them in three places —
|
|
7
7
|
* so a pass could be registered and drawn while nothing uploaded to it, which
|
|
8
|
-
* paints nothing,
|
|
8
|
+
* paints nothing, on the GPU backend only. `InstancePass`
|
|
9
|
+
* makes them one object:
|
|
9
10
|
*
|
|
10
11
|
* ```ts
|
|
11
12
|
* export const GAP_PASS = {
|
package/esm/mapUploadSync.d.ts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
export interface MapUploadTarget<K, T, B> {
|
|
2
2
|
upload: (backend: B, key: K, data: T) => void;
|
|
3
|
-
/**
|
|
4
|
-
* How a key that left the map is released. `remove` deletes it by itself;
|
|
5
|
-
* `prune` is handed the keys still present and releases everything else.
|
|
6
|
-
* `installUpload` takes the first, which is the only correct shape on a
|
|
7
|
-
* canvas several displays share and does the same job on a display's own
|
|
8
|
-
* map.
|
|
9
|
-
*/
|
|
10
3
|
remove?: (backend: B, key: K) => void;
|
|
11
|
-
prune?: (backend: B, active: ReadonlySet<K>) => void;
|
|
12
4
|
}
|
|
13
5
|
/**
|
|
14
6
|
* The one reference diff every keyed GPU upload in the tree runs on. Uploads
|
|
@@ -17,8 +9,8 @@ export interface MapUploadTarget<K, T, B> {
|
|
|
17
9
|
* re-uploads), and re-uploads everything when the backend identity changes —
|
|
18
10
|
* a context-loss recovery hands a fresh backend with empty GPU buffers.
|
|
19
11
|
*
|
|
20
|
-
* Returns whether anything reached the backend,
|
|
21
|
-
*
|
|
12
|
+
* Returns whether anything reached the backend, so the upload autorun can skip
|
|
13
|
+
* the redraw it would otherwise force after every run.
|
|
22
14
|
*
|
|
23
15
|
* For the skip to fire, the map must keep **stable references** for unchanged
|
|
24
16
|
* entries across recomputes. With an always-fresh map every entry re-uploads,
|
package/esm/mapUploadSync.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* re-uploads), and re-uploads everything when the backend identity changes —
|
|
6
6
|
* a context-loss recovery hands a fresh backend with empty GPU buffers.
|
|
7
7
|
*
|
|
8
|
-
* Returns whether anything reached the backend,
|
|
9
|
-
*
|
|
8
|
+
* Returns whether anything reached the backend, so the upload autorun can skip
|
|
9
|
+
* the redraw it would otherwise force after every run.
|
|
10
10
|
*
|
|
11
11
|
* For the skip to fire, the map must keep **stable references** for unchanged
|
|
12
12
|
* entries across recomputes. With an always-fresh map every entry re-uploads,
|
|
@@ -39,7 +39,6 @@ export function createMapUploadSync(target) {
|
|
|
39
39
|
changed = true;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
target.prune?.(backend, new Set(entries.keys()));
|
|
43
42
|
return changed;
|
|
44
43
|
};
|
|
45
44
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ColorChannel } from './markRamp.ts';
|
|
2
|
+
import type { RowChannel, RowParams } from './rowLane.ts';
|
|
3
|
+
import type { MarkColorScale, MarkShape } from './types.ts';
|
|
4
|
+
import type { MarkValueScale } from './valueScale.ts';
|
|
5
|
+
/**
|
|
6
|
+
* The `bar` shape's channels: a rectangle from `x` to `x2` standing between
|
|
7
|
+
* the baseline and `y` on the value scale, in the band of its `row`.
|
|
8
|
+
*/
|
|
9
|
+
export interface BarChannels extends ColorChannel, RowChannel {
|
|
10
|
+
x: Uint32Array;
|
|
11
|
+
x2: Uint32Array;
|
|
12
|
+
y: Float32Array;
|
|
13
|
+
count: number;
|
|
14
|
+
}
|
|
15
|
+
export interface BarParams extends RowParams, MarkValueScale {
|
|
16
|
+
/** The quantitative colour scale, for a bar whose colour is a ramp or a threshold. */
|
|
17
|
+
colorScale?: MarkColorScale;
|
|
18
|
+
/** The value bars grow from; a bar below it hangs down. */
|
|
19
|
+
origin: number;
|
|
20
|
+
/**
|
|
21
|
+
* Narrowest a bar is painted, in CSS px, grown off the start edge. Zero is
|
|
22
|
+
* a no-op for a caller whose bars tile.
|
|
23
|
+
*/
|
|
24
|
+
minWidthPx: number;
|
|
25
|
+
/** CSS px the painter alone adds to the drawn width; see `SpanParams.seamPx`. */
|
|
26
|
+
seamPx: number;
|
|
27
|
+
/** CSS px each row's value scale runs over; the row's own height when absent. */
|
|
28
|
+
rowBandPx?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const barMark: MarkShape<BarChannels, BarParams>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { bpRangeXTuple } from '../blockClipUtils.js';
|
|
2
|
+
import { getDpr, makeBpMapper, spanLeft } from '../canvas2dUtils.js';
|
|
3
|
+
import * as shader from '../shaders/barMark.generated.js';
|
|
4
|
+
import { CLIP_STRIP_COLOR, CLIP_STRIP_PX, } from '../shaders/clipStrip.generated.js';
|
|
5
|
+
import { clipSide } from '../shaders/clipStrip.js.generated.js';
|
|
6
|
+
import { valueToYPxScaled } from '../shaders/pointMark.js.generated.js';
|
|
7
|
+
import { rowBandTopPx } from '../shaders/rowTable.js.generated.js';
|
|
8
|
+
import { slangPass } from '../slangPass.js';
|
|
9
|
+
import { makeAbgrFill } from './colorFill.js';
|
|
10
|
+
import { colorBits, paintColors, rampUniforms } from './markRamp.js';
|
|
11
|
+
import { valueWindow } from './nearestMarkHit.js';
|
|
12
|
+
import { bandHeightPx, rowColor, rowLane, rowSlot, rowTableKeys, rowTableTextures, } from './rowLane.js';
|
|
13
|
+
import { valueScaleUniforms } from './valueScale.js';
|
|
14
|
+
// Where a slot's value scale sits: its top and height, in the frame's CSS px.
|
|
15
|
+
function barBand(params, canvasHeight, slot) {
|
|
16
|
+
const pitch = bandHeightPx(params, canvasHeight);
|
|
17
|
+
return {
|
|
18
|
+
top: rowBandTopPx(params.rowOffsetPx ?? 0, pitch, slot),
|
|
19
|
+
band: params.rowBandPx ?? pitch,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Where the baseline sits inside a band, in CSS px below its top.
|
|
23
|
+
function originYPx(params, band, { valueScaleType: st, valueSymlogConstant: c }) {
|
|
24
|
+
const [domainMin, domainMax] = params.domain;
|
|
25
|
+
return valueToYPxScaled(params.origin, domainMin, domainMax, band, st, c);
|
|
26
|
+
}
|
|
27
|
+
// The x span one instance paints, floored at `minWidthPx` off its start edge.
|
|
28
|
+
function barSpan(bpToPx, x, x2, params) {
|
|
29
|
+
const xa = bpToPx(x);
|
|
30
|
+
const xb = bpToPx(x2);
|
|
31
|
+
const width = Math.max(params.minWidthPx, Math.abs(xb - xa));
|
|
32
|
+
return { left: spanLeft(xa, xb, width), width };
|
|
33
|
+
}
|
|
34
|
+
// The rect one instance paints, in the frame's CSS px, or undefined for a bar
|
|
35
|
+
// with no height — which draws nothing and so cannot be hovered.
|
|
36
|
+
function barRect(bpToPx, x, x2, y, bandTop, band, params, yScale) {
|
|
37
|
+
const { valueScaleType: st, valueSymlogConstant: c } = yScale;
|
|
38
|
+
const { left, width } = barSpan(bpToPx, x, x2, params);
|
|
39
|
+
const [domainMin, domainMax] = params.domain;
|
|
40
|
+
const valueY = bandTop + valueToYPxScaled(y, domainMin, domainMax, band, st, c);
|
|
41
|
+
const originY = bandTop + originYPx(params, band, yScale);
|
|
42
|
+
const top = Math.min(valueY, originY);
|
|
43
|
+
const height = Math.abs(valueY - originY);
|
|
44
|
+
return height === 0 ? undefined : { left, top, width, height };
|
|
45
|
+
}
|
|
46
|
+
// The clip strip's rect, or undefined for a bar the domain holds (ADR-183).
|
|
47
|
+
function stripRect(bpToPx, x, x2, y, bandTop, band, params, yScale) {
|
|
48
|
+
const [domainMin, domainMax] = params.domain;
|
|
49
|
+
const side = clipSide(y, domainMin, domainMax, yScale.valueScaleType);
|
|
50
|
+
if (side === 0) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const { left, width } = barSpan(bpToPx, x, x2, params);
|
|
54
|
+
return {
|
|
55
|
+
left,
|
|
56
|
+
top: side > 0 ? bandTop : bandTop + band - CLIP_STRIP_PX,
|
|
57
|
+
width,
|
|
58
|
+
height: CLIP_STRIP_PX,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export const barMark = {
|
|
62
|
+
id: 'bar',
|
|
63
|
+
pass: {
|
|
64
|
+
...slangPass({ id: 'bar', mod: shader }),
|
|
65
|
+
pack: c => shader.packInstances({ ...c, color: colorBits(c, c.count), row: rowLane(c.row, c.count) }, c.count),
|
|
66
|
+
},
|
|
67
|
+
writeUniforms(scratch, clip, block, frame, params) {
|
|
68
|
+
const yScale = valueScaleUniforms(params);
|
|
69
|
+
const band = params.rowBandPx ?? bandHeightPx(params, frame.canvasHeight);
|
|
70
|
+
shader.writeUniforms(scratch, {
|
|
71
|
+
bpRangeX: bpRangeXTuple(clip, block.reversed),
|
|
72
|
+
canvasHeight: frame.canvasHeight,
|
|
73
|
+
domainMin: params.domain[0],
|
|
74
|
+
domainMax: params.domain[1],
|
|
75
|
+
...yScale,
|
|
76
|
+
...rampUniforms(params.colorScale),
|
|
77
|
+
originYPx: originYPx(params, band, yScale),
|
|
78
|
+
rowHeight: bandHeightPx(params, frame.canvasHeight),
|
|
79
|
+
rowBandPx: band,
|
|
80
|
+
rowOffsetPx: params.rowOffsetPx ?? 0,
|
|
81
|
+
zero: 0,
|
|
82
|
+
minCellDenomPx: clip.scissorW,
|
|
83
|
+
minWidthPx: params.minWidthPx,
|
|
84
|
+
devicePixelRatio: getDpr(),
|
|
85
|
+
rowTableKeys: rowTableKeys(params),
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
textures: rowTableTextures,
|
|
89
|
+
paintBlock(ctx, channels, block, frame, params) {
|
|
90
|
+
const { x, x2, y, row, count } = channels;
|
|
91
|
+
const color = paintColors(channels, count, params.colorScale);
|
|
92
|
+
const bpToPx = makeBpMapper(block);
|
|
93
|
+
const setFill = makeAbgrFill(ctx);
|
|
94
|
+
const yScale = valueScaleUniforms(params);
|
|
95
|
+
const table = params.rowTable;
|
|
96
|
+
const [domainMin, domainMax] = params.domain;
|
|
97
|
+
let clipped = false;
|
|
98
|
+
for (let i = 0; i < count; i++) {
|
|
99
|
+
const slot = rowSlot(row, i, table);
|
|
100
|
+
if (slot === undefined) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const { top, band } = barBand(params, frame.canvasHeight, slot);
|
|
104
|
+
const r = barRect(bpToPx, x[i], x2[i], y[i], top, band, params, yScale);
|
|
105
|
+
if (r) {
|
|
106
|
+
setFill(rowColor(color[i], row, i, table));
|
|
107
|
+
ctx.fillRect(r.left, r.top, r.width + params.seamPx, r.height);
|
|
108
|
+
}
|
|
109
|
+
clipped ||=
|
|
110
|
+
clipSide(y[i], domainMin, domainMax, yScale.valueScaleType) !== 0;
|
|
111
|
+
}
|
|
112
|
+
if (!clipped) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// The strips go on after every bar, as the shader's second quad does, so
|
|
116
|
+
// a neighbour widened to the min-width floor cannot paint over one.
|
|
117
|
+
setFill(CLIP_STRIP_COLOR);
|
|
118
|
+
for (let i = 0; i < count; i++) {
|
|
119
|
+
const slot = rowSlot(row, i, table);
|
|
120
|
+
if (slot === undefined) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const { top, band } = barBand(params, frame.canvasHeight, slot);
|
|
124
|
+
const s = stripRect(bpToPx, x[i], x2[i], y[i], top, band, params, yScale);
|
|
125
|
+
if (s) {
|
|
126
|
+
ctx.fillRect(s.left, s.top, s.width + params.seamPx, s.height);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
ink(channels, block, frame, params, i) {
|
|
131
|
+
const { x, x2, y, row } = channels;
|
|
132
|
+
const slot = rowSlot(row, i, params.rowTable);
|
|
133
|
+
if (slot === undefined) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
// A bar cut to no height, its origin on the edge that cut it, paints only
|
|
137
|
+
// its strip, which is then what answers a hover.
|
|
138
|
+
const { top, band } = barBand(params, frame.canvasHeight, slot);
|
|
139
|
+
const bpToPx = makeBpMapper(block);
|
|
140
|
+
const yScale = valueScaleUniforms(params);
|
|
141
|
+
return (barRect(bpToPx, x[i], x2[i], y[i], top, band, params, yScale) ??
|
|
142
|
+
stripRect(bpToPx, x[i], x2[i], y[i], top, band, params, yScale));
|
|
143
|
+
},
|
|
144
|
+
valueWindow(yPx, radiusPx, frame, params) {
|
|
145
|
+
return params.rowBandPx === undefined
|
|
146
|
+
? valueWindow(yPx, radiusPx, frame, { ...params, edgePx: CLIP_STRIP_PX })
|
|
147
|
+
: [-Infinity, Infinity];
|
|
148
|
+
},
|
|
149
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Packed ABGR → `rgba(...)`, and the run-tracking fill a painter wraps it in.
|
|
3
|
+
*
|
|
4
|
+
* `@jbrowse/core/util/colorBits` re-exports `abgrToCssRgba` from here: core
|
|
5
|
+
* depends on render-core, never the reverse. The direction that genuinely
|
|
6
|
+
* needs core is resolving a CSS colour to a packed number, which is why a
|
|
7
|
+
* shape takes packed colours and the display resolves them.
|
|
8
|
+
*/
|
|
9
|
+
export declare function abgrToCssRgba(c: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* A fill-style setter that only touches `ctx.fillStyle` when the colour
|
|
12
|
+
* changes. Most of a painting is runs of one colour, and both the string
|
|
13
|
+
* allocation and the context write cost more than the comparison.
|
|
14
|
+
*/
|
|
15
|
+
export declare function makeAbgrFill(ctx: {
|
|
16
|
+
fillStyle: string | CanvasGradient | CanvasPattern;
|
|
17
|
+
}): (abgr: number) => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Packed ABGR → `rgba(...)`, and the run-tracking fill a painter wraps it in.
|
|
3
|
+
*
|
|
4
|
+
* `@jbrowse/core/util/colorBits` re-exports `abgrToCssRgba` from here: core
|
|
5
|
+
* depends on render-core, never the reverse. The direction that genuinely
|
|
6
|
+
* needs core is resolving a CSS colour to a packed number, which is why a
|
|
7
|
+
* shape takes packed colours and the display resolves them.
|
|
8
|
+
*/
|
|
9
|
+
export function abgrToCssRgba(c) {
|
|
10
|
+
const a = ((c >>> 24) & 255) / 255;
|
|
11
|
+
return `rgba(${c & 255},${(c >>> 8) & 255},${(c >>> 16) & 255},${a})`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A fill-style setter that only touches `ctx.fillStyle` when the colour
|
|
15
|
+
* changes. Most of a painting is runs of one colour, and both the string
|
|
16
|
+
* allocation and the context write cost more than the comparison.
|
|
17
|
+
*/
|
|
18
|
+
export function makeAbgrFill(ctx) {
|
|
19
|
+
let last;
|
|
20
|
+
return (abgr) => {
|
|
21
|
+
if (abgr !== last) {
|
|
22
|
+
last = abgr;
|
|
23
|
+
ctx.fillStyle = abgrToCssRgba(abgr);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { RenderBlock } from '../renderBlock.ts';
|
|
2
|
+
import type { Mark, MarkContext2D, MarkFrame } from './types.ts';
|
|
3
|
+
export interface RecordedRect {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
fillStyle: MarkContext2D['fillStyle'];
|
|
9
|
+
}
|
|
10
|
+
export declare function recordingContext(): {
|
|
11
|
+
ctx: {
|
|
12
|
+
fillStyle: string;
|
|
13
|
+
strokeStyle: string;
|
|
14
|
+
lineWidth: number;
|
|
15
|
+
lineCap: "butt";
|
|
16
|
+
lineJoin: "miter";
|
|
17
|
+
save(): void;
|
|
18
|
+
restore(): void;
|
|
19
|
+
translate(x: number, y: number): void;
|
|
20
|
+
scale(x: number, y: number): void;
|
|
21
|
+
rotate(angle: number): void;
|
|
22
|
+
beginPath(): void;
|
|
23
|
+
clip(): void;
|
|
24
|
+
setLineDash(_segments: number[]): void;
|
|
25
|
+
moveTo(x: number, y: number): void;
|
|
26
|
+
lineTo(x: number, y: number): void;
|
|
27
|
+
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
|
|
28
|
+
arc(x: number, y: number, radius: number, start?: number, end?: number): void;
|
|
29
|
+
ellipse(x: number, y: number, radiusX: number, radiusY: number, _rotation?: number, start?: number, end?: number): void;
|
|
30
|
+
closePath(): void;
|
|
31
|
+
fill(): void;
|
|
32
|
+
stroke(): void;
|
|
33
|
+
rect(x: number, y: number, w: number, h: number): void;
|
|
34
|
+
fillRect(x: number, y: number, w: number, h: number): void;
|
|
35
|
+
strokeRect(x: number, y: number, w: number, h: number): void;
|
|
36
|
+
};
|
|
37
|
+
calls: RecordedRect[];
|
|
38
|
+
};
|
|
39
|
+
/** The extent of a painting, in canvas px. */
|
|
40
|
+
export interface Box {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
w: number;
|
|
44
|
+
h: number;
|
|
45
|
+
}
|
|
46
|
+
interface Counted {
|
|
47
|
+
count: number;
|
|
48
|
+
}
|
|
49
|
+
export interface SweepOptions<C> {
|
|
50
|
+
maxDistSq?: number;
|
|
51
|
+
step?: number;
|
|
52
|
+
sliceOne?: (channels: C, index: number) => C;
|
|
53
|
+
inkSlackPx?: number;
|
|
54
|
+
contains?: (index: number, xPx: number, yPx: number) => boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The ink clause of {@link sweepMarkAgainstHit} alone, for a mark with no
|
|
58
|
+
* `hitNearest`: `boxes[i]` is what the painter recorded for instance `i`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function inkViolations<C, S extends MarkFrame>(mark: Mark<C, S>, channels: C, block: RenderBlock, state: S, boxes: readonly (Box | undefined)[], inkSlackPx: number): string[];
|
|
61
|
+
/**
|
|
62
|
+
* The draw-against-hit gate: paint the block, then walk it in `step` px and
|
|
63
|
+
* hold `hitNearest` to what the painter actually put on the canvas.
|
|
64
|
+
*
|
|
65
|
+
* **What the painter drew for instance `i` has to be attributed to `i`,** and
|
|
66
|
+
* there are two ways to get that. A mark whose every instance is one `fillRect`
|
|
67
|
+
* gets it positionally, which is the default and needs nothing. A mark that
|
|
68
|
+
* batches a colour run into one path (`point`'s glyphs), or that skips an
|
|
69
|
+
* instance the view has scrolled past (`cell`'s off-canvas rows), cannot be read
|
|
70
|
+
* that way at all — the batch has fewer rects than instances, or the wrong ones.
|
|
71
|
+
* `sliceOne` is the way in for those: hand back one instance's channels and the
|
|
72
|
+
* sweep paints it alone, so the attribution holds by construction and a culled
|
|
73
|
+
* instance is visibly an empty painting.
|
|
74
|
+
*
|
|
75
|
+
* Four claims, all of them one-directional and true of every mark:
|
|
76
|
+
*
|
|
77
|
+
* - an instance that painted nothing is never the answer,
|
|
78
|
+
* - `hit.x`/`hit.y` — where the mark says its ink is — lies inside the box the
|
|
79
|
+
* painter drew for the instance the hit names,
|
|
80
|
+
* - `hit.distSq` is no smaller than the distance to that box, since the box
|
|
81
|
+
* contains the ink and cannot be farther than it,
|
|
82
|
+
* - `hit.distSq` IS the distance to `hit.x`/`hit.y`, which is `MarkHit`'s own
|
|
83
|
+
* contract rather than a fact about the painting: a mark that answers a
|
|
84
|
+
* distance its own reported point does not support has two spellings of where
|
|
85
|
+
* its ink is, and the nearest-wins walk is resolved by the one the caller
|
|
86
|
+
* cannot see.
|
|
87
|
+
*
|
|
88
|
+
* The fifth is the containment rule: **a point the rule contains answers the
|
|
89
|
+
* nearest painted instance it contains**, the last-painted where tied, since the
|
|
90
|
+
* sweep hands candidates back to front. The default rule is the painted box, so
|
|
91
|
+
* a point on a box answers that box, and off every box a hit target wider than
|
|
92
|
+
* its ink may still answer. The default holds only where the box IS the hit
|
|
93
|
+
* target — every `fillRect` mark, and `cell`'s inversion triangle, which answers
|
|
94
|
+
* as its bounding box on purpose — and not for a glyph, whose box is a superset
|
|
95
|
+
* of its ink, so it runs exactly when the batch painted one rect per instance. A
|
|
96
|
+
* mark whose hit rule is not its box (the pileup's bp containment) passes
|
|
97
|
+
* `contains`, which is then the whole rule: the sweep covers the whole canvas,
|
|
98
|
+
* and a point the rule contains nowhere answers nothing.
|
|
99
|
+
*
|
|
100
|
+
* A mark declaring `ink` is held to one more clause, per instance: the box the
|
|
101
|
+
* painter recorded for `i` lies inside `ink(i)`, and each edge of `ink(i)` lies
|
|
102
|
+
* within `inkSlackPx` (default 1) of the painting's — so the rect is tight to
|
|
103
|
+
* the ink within a pixel on every side, which admits a seam overdraw or a pixel
|
|
104
|
+
* snap and rejects a rect that is the wrong row, the wrong width or the whole
|
|
105
|
+
* canvas. An instance that painted nothing must answer no ink, and one with ink
|
|
106
|
+
* must have painted.
|
|
107
|
+
*
|
|
108
|
+
* Returns the violations rather than asserting, so a test reads as
|
|
109
|
+
* `expect(sweep(...)).toEqual([])`. `maxDistSq` is the bound the hit test is
|
|
110
|
+
* asked with, `Infinity` unless the caller's differs.
|
|
111
|
+
*/
|
|
112
|
+
export declare function sweepMarkAgainstHit<C extends Counted, S extends MarkFrame>(mark: Mark<NoInfer<C>, S>, channels: C, block: RenderBlock, state: S, { maxDistSq, step, sliceOne, inkSlackPx, contains: rule, }?: SweepOptions<C>): string[];
|
|
113
|
+
export {};
|