({ canvasWidth, canvasHeight, devicePixelRatio, instances })
| 165 | }; |
| 166 | |
| 167 | const prepare: AnnotationMarkerRenderer['prepare'] = ({ canvasWidth, canvasHeight, devicePixelRatio, instances }) => { |
| 168 | assertNotDisposed(); |
| 169 | |
| 170 | if (!Number.isFinite(canvasWidth) || !Number.isFinite(canvasHeight) || canvasWidth <= 0 || canvasHeight <= 0) { |
| 171 | throw new Error('AnnotationMarkerRenderer.prepare: canvasWidth/canvasHeight must be positive finite numbers.'); |
| 172 | } |
| 173 | if (!Array.isArray(instances)) { |
| 174 | throw new Error('AnnotationMarkerRenderer.prepare: instances must be an array.'); |
| 175 | } |
| 176 | |
| 177 | writeVsUniforms(canvasWidth, canvasHeight, devicePixelRatio); |
| 178 | |
| 179 | ensureCpuInstanceCapacityFloats(instances.length * INSTANCE_STRIDE_FLOATS); |
| 180 | const f32 = cpuInstanceStagingF32; |
| 181 | let outFloats = 0; |
| 182 | |
| 183 | for (let i = 0; i < instances.length; i++) { |
| 184 | const m = instances[i]; |
| 185 | if (!Number.isFinite(m.xCssPx) || !Number.isFinite(m.yCssPx)) continue; |
| 186 | if (!Number.isFinite(m.sizeCssPx) || m.sizeCssPx <= 0) continue; |
| 187 | |
| 188 | const strokeWidthCss = m.strokeWidthCssPx ?? 0; |
| 189 | const strokeRgba = m.strokeRgba ?? ([0, 0, 0, 0] as const); |
| 190 | |
| 191 | // Clamp colors to [0,1] for deterministic output. |
| 192 | const fr = clamp01(m.fillRgba[0]); |
| 193 | const fg = clamp01(m.fillRgba[1]); |
| 194 | const fb = clamp01(m.fillRgba[2]); |
| 195 | const fa = clamp01(m.fillRgba[3]); |
| 196 | |
| 197 | const sr = clamp01(strokeRgba[0]); |
| 198 | const sg = clamp01(strokeRgba[1]); |
| 199 | const sb = clamp01(strokeRgba[2]); |
| 200 | const sa = clamp01(strokeRgba[3]); |
| 201 | |
| 202 | f32[outFloats + 0] = m.xCssPx; |
| 203 | f32[outFloats + 1] = m.yCssPx; |
| 204 | f32[outFloats + 2] = m.sizeCssPx; |
| 205 | f32[outFloats + 3] = Number.isFinite(strokeWidthCss) ? Math.max(0, strokeWidthCss) : 0; |
| 206 | |
| 207 | f32[outFloats + 4] = fr; |
| 208 | f32[outFloats + 5] = fg; |
| 209 | f32[outFloats + 6] = fb; |
| 210 | f32[outFloats + 7] = fa; |
| 211 | |
| 212 | f32[outFloats + 8] = sr; |
| 213 | f32[outFloats + 9] = sg; |
| 214 | f32[outFloats + 10] = sb; |
| 215 | f32[outFloats + 11] = sa; |
| 216 | |
| 217 | outFloats += INSTANCE_STRIDE_FLOATS; |
| 218 | } |
| 219 | |
| 220 | instanceCount = outFloats / INSTANCE_STRIDE_FLOATS; |
| 221 | |
| 222 | // PERFORMANCE: Early exit if no valid instances (skip buffer allocation/write) |
| 223 | if (instanceCount === 0) { |
| 224 | return; |
nothing calls this directly
no test coverage detected