@inditextech/weave-sdk 5.7.0 → 5.8.0-SNAPSHOT.613.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.
- package/dist/lab.d.ts +289 -0
- package/dist/lab.d.ts.map +1 -0
- package/dist/lab.js +1438 -0
- package/dist/lab.js.map +1 -0
- package/dist/lab.stats.html +5305 -0
- package/dist/sdk.js +3250 -174
- package/dist/sdk.node.js +3250 -174
- package/dist/sdk.node.stats.html +1 -1
- package/dist/sdk.stats.html +1 -1
- package/dist/types.d.ts +610 -31
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3250 -174
- package/dist/types.js.map +1 -1
- package/dist/types.stats.html +1 -1
- package/package.json +8 -3
package/dist/lab.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lab.js","names":[],"sources":["../src/actions/brush-tool/constants.ts","../src/actions/brush-tool/tunables/merge.ts","../src/actions/brush-tool/tunables/presets.ts","../src/plugins/brush-lab/constants.ts","../src/plugins/brush-lab/device-report.ts","../src/actions/brush-tool/stages/stabilizer.ts","../src/actions/brush-tool/stages/bezier-fit.ts","../src/actions/brush-tool/stages/finalize.ts","../src/plugins/brush-lab/ghosts.ts","../src/plugins/brush-lab/recorder.ts","../src/plugins/brush-lab/metrics.ts","../src/plugins/brush-lab/brush-lab.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { WeaveBrushInputProfile } from './types';\n\nexport const BRUSH_TOOL_ACTION_NAME = 'brushTool';\n\n/** Name under which the lab plugin registers itself. */\nexport const BRUSH_LAB_PLUGIN_NAME = 'brushLab';\n\nexport const BRUSH_TOOL_STATE = {\n ['INACTIVE']: 'inactive',\n ['IDLE']: 'idle',\n ['DEFINE_STROKE']: 'defineStroke',\n} as const;\n\n/**\n * Suffix applied to a finished stroke's preview node while it is briefly\n * kept on screen alongside the persisted node, so the two cannot collide on\n * the same id.\n */\nexport const PREVIEW_ID_SUFFIX = '--preview';\n\n/**\n * How many frames the preview of a finished stroke may wait for its\n * persisted counterpart to be rendered before it is removed regardless.\n * Bounds the handover so a preview can never be orphaned on screen.\n */\nexport const PREVIEW_HANDOVER_MAX_FRAMES = 30;\n\nexport const BRUSH_INPUT_PROFILE_KEYS = [\n 'mouse',\n 'touch',\n 'pen.applePencil',\n 'pen.desktop',\n] as const;\n\n/**\n * The legacy input profile: reproduces, point for point, what the brush tool\n * recorded before profiles existed. Every profile starts from it.\n */\nexport const BRUSH_LEGACY_INPUT_PROFILE: WeaveBrushInputProfile = {\n capture: {\n source: 'legacy',\n clock: 'now',\n minMovePx: 0,\n predicted: 'tail',\n event: 'pointermove',\n },\n pressure: {\n zero: 'legacy',\n filter: 'legacy',\n timeConstantMs: 40,\n oneEuro: { minCutoff: 1, beta: 0.01 },\n floor: 0.15,\n start: 'backfill',\n startSamples: 3,\n end: 'backfill',\n },\n stabilizer: {\n type: 'none',\n minCutoff: 3,\n beta: 0.01,\n radiusPx: 4,\n amount: 0.3,\n zoomAware: false,\n catchUpOnEnd: true,\n },\n finalize: {\n mode: 'dp',\n toleranceUnit: 'canvas',\n pressureWeight: 20,\n resampleSpacingPx: 2,\n },\n touchGuard: {\n waitMs: 0,\n movePx: 0,\n cancelOnSecondTouch: false,\n ignoreAfterPen: false,\n },\n};\n\nexport const BRUSH_TOOL_DEFAULT_CONFIG = {\n input: {\n forceProfile: null,\n profiles: {\n mouse: BRUSH_LEGACY_INPUT_PROFILE,\n touch: BRUSH_LEGACY_INPUT_PROFILE,\n 'pen.applePencil': BRUSH_LEGACY_INPUT_PROFILE,\n 'pen.desktop': BRUSH_LEGACY_INPUT_PROFILE,\n },\n },\n interpolationSteps: 10,\n // Douglas-Peucker tolerance (in canvas units) applied once, when a stroke\n // is finalized. This is the dominant cause of a finished stroke looking\n // less faithful than the one being drawn: while drawing, every raw sample\n // is rendered, but on pointer-up the point list is simplified and only\n // then re-rendered.\n //\n // Measured max deviation from the drawn path (spline resolution 8):\n // tolerance 1.0 → 0.79px / 6.22px / 0.46px (handwriting / signature / long sweep)\n // tolerance 0.5 → 0.40px / 1.60px / 0.30px\n // tolerance 0.25 → 0.21px / 1.18px / 0.15px\n // 0.5 removes most of the visible \"snap\" on finalize while still dropping\n // ~75% of raw samples; going below it buys little and costs point count\n // in every persisted document.\n simplifyTolerance: 0.5,\n};\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\ntype Plain = Record<string, unknown>;\n\nconst isPlain = (v: unknown): v is Plain =>\n v !== null && typeof v === 'object' && !Array.isArray(v);\n\n/** Deep clone of plain data. */\nexport function cloneData<T>(value: T): T {\n if (Array.isArray(value)) return value.map(cloneData) as unknown as T;\n if (isPlain(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, cloneData(v)])\n ) as T;\n }\n return value;\n}\n\n/** Returns a new object: `base` with every defined value of `patch` merged in. */\nexport function mergeData<T>(base: T, patch: unknown): T {\n const result = cloneData(base) as Plain;\n if (!isPlain(patch)) return result as T;\n for (const [k, v] of Object.entries(patch)) {\n if (v === undefined) continue;\n result[k] =\n isPlain(v) && isPlain(result[k]) ? mergeData(result[k], v) : cloneData(v);\n }\n return result as T;\n}\n\n/** Freezes plain data recursively. */\nexport function deepFreeze<T>(value: T): T {\n if (isPlain(value) || Array.isArray(value)) {\n for (const v of Object.values(value as object)) deepFreeze(v);\n Object.freeze(value);\n }\n return value;\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport { WEAVE_STROKE_LEGACY_LOOK } from '@/nodes/stroke/constants';\nimport type { WeaveStrokeLook } from '@/nodes/stroke/types';\nimport { BRUSH_LEGACY_INPUT_PROFILE } from '../constants';\nimport type {\n WeaveBrushInputProfile,\n WeaveBrushInputProfileKey,\n WeaveBrushInputProfilePatch,\n} from '../types';\nimport { deepFreeze, mergeData } from './merge';\n\nexport type WeaveStrokeLookPatch = {\n [K in keyof WeaveStrokeLook]?: K extends 'width'\n ? Partial<WeaveStrokeLook['width']>\n : WeaveStrokeLook[K];\n};\n\nexport type WeaveBrushProfilePreset = {\n id: string;\n label: string;\n description: string;\n /** Changes relative to the legacy profile. */\n patch: WeaveBrushInputProfilePatch;\n};\n\nexport type WeaveBrushLookPreset = {\n id: string;\n label: string;\n description: string;\n /** Changes relative to the legacy look; `null` means \"store no look\". */\n patch: WeaveStrokeLookPatch | null;\n};\n\nexport type WeaveBrushScenario = {\n id: string;\n label: string;\n description: string;\n /** Preset id chosen for each profile. */\n profiles: Record<WeaveBrushInputProfileKey, string>;\n /** Look preset id. */\n look: string;\n};\n\n// The values below are starting points to be tuned on real hardware.\n\nconst FIXES: WeaveBrushInputProfilePatch = {\n capture: { source: 'coalesced', clock: 'event' },\n pressure: { zero: 'keep' },\n};\n\nconst withFixes = (patch: WeaveBrushInputProfilePatch) =>\n mergeData(\n FIXES as WeaveBrushInputProfile,\n patch\n ) as WeaveBrushInputProfilePatch;\n\nconst PEN_SMOOTH: WeaveBrushInputProfilePatch = withFixes({\n pressure: {\n filter: 'oneEuro',\n oneEuro: { minCutoff: 1.5, beta: 0.02 },\n start: 'average',\n },\n stabilizer: { type: 'oneEuro', minCutoff: 6, beta: 0.05, zoomAware: true },\n finalize: {\n mode: 'bezierFit',\n toleranceUnit: 'screen',\n tolerance: 2,\n resampleSpacingPx: 8,\n },\n});\n\nconst PEN_ILLUSTRATOR: WeaveBrushInputProfilePatch = withFixes({\n pressure: { filter: 'timeEma', timeConstantMs: 30, start: 'average' },\n stabilizer: { type: 'streamline', amount: 0.25, zoomAware: true },\n finalize: {\n mode: 'bezierFit',\n toleranceUnit: 'screen',\n tolerance: 2,\n resampleSpacingPx: 8,\n },\n});\n\nconst TOUCH_GUARD: WeaveBrushInputProfilePatch = withFixes({\n touchGuard: { waitMs: 100, movePx: 6, cancelOnSecondTouch: true },\n});\n\nconst legacy = (): WeaveBrushProfilePreset => ({\n id: 'legacy',\n label: 'Legacy',\n description: 'Behaviour of earlier releases, point for point.',\n patch: {},\n});\n\nconst fixed = (): WeaveBrushProfilePreset => ({\n id: 'fixed',\n label: 'Fixed',\n description: 'Keeps every pen sample, uses event time, keeps zero pressure.',\n patch: FIXES,\n});\n\nconst penPresets = (): WeaveBrushProfilePreset[] => [\n legacy(),\n fixed(),\n {\n id: 'smooth',\n label: 'Smooth',\n description:\n 'Fixed, plus One Euro smoothing of pressure and position and a Bézier-fitted finish.',\n patch: PEN_SMOOTH,\n },\n {\n id: 'illustrator',\n label: 'Illustrator-like',\n description:\n 'Fixed, plus streamline stabilizing and a Bézier-fitted finish in screen pixels.',\n patch: PEN_ILLUSTRATOR,\n },\n];\n\nconst RAW_PROFILE_PRESETS: Record<\n WeaveBrushInputProfileKey,\n WeaveBrushProfilePreset[]\n> = {\n mouse: [\n legacy(),\n fixed(),\n {\n id: 'stabilized',\n label: 'Stabilized',\n description:\n 'Fixed, plus One Euro position smoothing that follows the zoom and a Bézier-fitted finish.',\n patch: withFixes({\n stabilizer: {\n type: 'oneEuro',\n minCutoff: 2,\n beta: 0.01,\n zoomAware: true,\n },\n finalize: {\n mode: 'bezierFit',\n toleranceUnit: 'screen',\n tolerance: 2,\n resampleSpacingPx: 8,\n },\n }),\n },\n {\n id: 'pulledString',\n label: 'Pulled string',\n description: 'Fixed, plus a pulled-string stabilizer.',\n patch: withFixes({\n stabilizer: { type: 'pulledString', radiusPx: 6, zoomAware: true },\n }),\n },\n ],\n touch: [\n legacy(),\n fixed(),\n {\n id: 'guarded',\n label: 'Guarded',\n description: 'Fixed, plus a short wait that a second finger can cancel.',\n patch: TOUCH_GUARD,\n },\n {\n id: 'smooth',\n label: 'Smooth',\n description:\n 'Guarded, plus One Euro position smoothing and a Bézier-fitted finish.',\n patch: mergeData(TOUCH_GUARD as WeaveBrushInputProfile, {\n stabilizer: {\n type: 'oneEuro',\n minCutoff: 3,\n beta: 0.02,\n zoomAware: true,\n },\n finalize: {\n mode: 'bezierFit',\n toleranceUnit: 'screen',\n tolerance: 2,\n resampleSpacingPx: 8,\n },\n }) as WeaveBrushInputProfilePatch,\n },\n ],\n 'pen.applePencil': penPresets(),\n 'pen.desktop': penPresets(),\n};\n\nconst WIDTH_CURVE: WeaveStrokeLookPatch = { width: { min: 0.2, gamma: 0.8 } };\nconst ROUND: WeaveStrokeLookPatch = {\n ...WIDTH_CURVE,\n outline: 'round',\n caps: 'merged',\n curve: 'centripetal',\n pressureInterp: 'linear',\n zoomAware: true,\n};\n\nconst RAW_LOOK_PRESETS: WeaveBrushLookPreset[] = [\n {\n id: 'legacy',\n label: 'Legacy',\n description: 'No look is stored: strokes are drawn as in earlier releases.',\n patch: null,\n },\n {\n id: 'widthCurve',\n label: 'Width curve',\n description: 'Legacy outline with a minimum width and a pressure curve.',\n patch: WIDTH_CURVE,\n },\n {\n id: 'round',\n label: 'Round',\n description:\n 'Round outline: no spikes at turns, uniform translucent colour.',\n patch: ROUND,\n },\n {\n id: 'freehand',\n label: 'Freehand',\n description: 'Freehand outline.',\n patch: {\n ...WIDTH_CURVE,\n outline: 'freehand',\n caps: 'merged',\n zoomAware: true,\n },\n },\n {\n id: 'illustrator',\n label: 'Illustrator-like',\n description: 'Round outline with a Size ± Variation style width range.',\n patch: { ...ROUND, width: { min: 0.4, max: 1, gamma: 1 } },\n },\n];\n\nconst RAW_SCENARIOS: WeaveBrushScenario[] = [\n {\n id: 'A',\n label: 'A: legacy',\n description: \"Today's behaviour, identical point for point.\",\n profiles: {\n mouse: 'legacy',\n touch: 'legacy',\n 'pen.applePencil': 'legacy',\n 'pen.desktop': 'legacy',\n },\n look: 'legacy',\n },\n {\n id: 'B',\n label: 'B: fixes',\n description: 'Every pen sample, event time and zero pressure kept.',\n profiles: {\n mouse: 'fixed',\n touch: 'fixed',\n 'pen.applePencil': 'fixed',\n 'pen.desktop': 'fixed',\n },\n look: 'legacy',\n },\n {\n id: 'C',\n label: 'C: smooth',\n description: 'B plus smoothing and a pressure curve.',\n profiles: {\n mouse: 'stabilized',\n touch: 'smooth',\n 'pen.applePencil': 'smooth',\n 'pen.desktop': 'smooth',\n },\n look: 'widthCurve',\n },\n {\n id: 'D',\n label: 'D: round',\n description: 'C plus the round outline.',\n profiles: {\n mouse: 'stabilized',\n touch: 'smooth',\n 'pen.applePencil': 'smooth',\n 'pen.desktop': 'smooth',\n },\n look: 'round',\n },\n {\n id: 'E',\n label: 'E: freehand',\n description: 'B plus the freehand outline.',\n profiles: {\n mouse: 'fixed',\n touch: 'fixed',\n 'pen.applePencil': 'fixed',\n 'pen.desktop': 'fixed',\n },\n look: 'freehand',\n },\n {\n id: 'F',\n label: 'F: Illustrator-like',\n description:\n 'Bézier-fitted finish, streamline stabilizing and a Size ± Variation width.',\n profiles: {\n mouse: 'stabilized',\n touch: 'smooth',\n 'pen.applePencil': 'illustrator',\n 'pen.desktop': 'illustrator',\n },\n look: 'illustrator',\n },\n];\n\n/** Factory profile presets per profile. Read-only. */\nexport const BRUSH_PROFILE_PRESETS = deepFreeze(RAW_PROFILE_PRESETS);\n/** Factory look presets. Read-only. */\nexport const BRUSH_LOOK_PRESETS = deepFreeze(RAW_LOOK_PRESETS);\n/** Factory scenarios. Read-only. */\nexport const BRUSH_SCENARIOS = deepFreeze(RAW_SCENARIOS);\n\n/** Full profile configuration of a preset: the legacy profile with its patch. */\nexport function resolveBrushProfilePatch(\n patch: WeaveBrushInputProfilePatch\n): WeaveBrushInputProfile {\n return mergeData(BRUSH_LEGACY_INPUT_PROFILE, patch);\n}\n\n/** Full look of a preset, or `null` when the preset stores no look. */\nexport function resolveBrushLookPatch(\n patch: WeaveStrokeLookPatch | null\n): WeaveStrokeLook | null {\n return patch === null ? null : mergeData(WEAVE_STROKE_LEGACY_LOOK, patch);\n}\n\nexport function getBrushScenario(id: string): WeaveBrushScenario | undefined {\n return BRUSH_SCENARIOS.find((s) => s.id === id);\n}\n\nexport type WeaveBrushPresetResult = { ok: boolean; error?: string };\n\n/**\n * Registry of profile and look presets: the read-only factory presets plus\n * custom ones. Factory presets cannot be changed or removed; a copy under a\n * new name can be made and edited. Custom presets live in memory; the\n * application decides whether to keep them.\n */\nexport class WeaveBrushPresetRegistry {\n private readonly customProfiles = new Map<string, WeaveBrushProfilePreset>();\n private readonly customLooks = new Map<string, WeaveBrushLookPreset>();\n\n private static profileKey(key: WeaveBrushInputProfileKey, id: string) {\n return `${key}/${id}`;\n }\n\n listProfilePresets(\n key: WeaveBrushInputProfileKey\n ): WeaveBrushProfilePreset[] {\n const custom = [...this.customProfiles.entries()]\n .filter(([k]) => k.startsWith(`${key}/`))\n .map(([, v]) => v);\n return [...BRUSH_PROFILE_PRESETS[key], ...custom];\n }\n\n getProfilePreset(key: WeaveBrushInputProfileKey, id: string) {\n return this.listProfilePresets(key).find((p) => p.id === id);\n }\n\n isFactoryProfilePreset(key: WeaveBrushInputProfileKey, id: string): boolean {\n return BRUSH_PROFILE_PRESETS[key].some((p) => p.id === id);\n }\n\n /** Changes a custom profile preset; a factory preset is rejected. */\n setProfilePreset(\n key: WeaveBrushInputProfileKey,\n id: string,\n patch: WeaveBrushInputProfilePatch\n ): WeaveBrushPresetResult {\n if (this.isFactoryProfilePreset(key, id)) {\n return {\n ok: false,\n error: `\"${id}\" is a factory preset and cannot be changed; copy it first`,\n };\n }\n const existing = this.customProfiles.get(\n WeaveBrushPresetRegistry.profileKey(key, id)\n );\n if (!existing) return { ok: false, error: `Unknown preset \"${id}\"` };\n this.customProfiles.set(WeaveBrushPresetRegistry.profileKey(key, id), {\n ...existing,\n patch: mergeData(\n existing.patch as WeaveBrushInputProfile,\n patch\n ) as WeaveBrushInputProfilePatch,\n });\n return { ok: true };\n }\n\n /** Copies a preset under a new id. */\n copyProfilePreset(\n key: WeaveBrushInputProfileKey,\n fromId: string,\n newId: string,\n label: string = newId\n ): WeaveBrushPresetResult {\n const from = this.getProfilePreset(key, fromId);\n if (!from) return { ok: false, error: `Unknown preset \"${fromId}\"` };\n if (this.getProfilePreset(key, newId)) {\n return { ok: false, error: `A preset \"${newId}\" already exists` };\n }\n this.customProfiles.set(WeaveBrushPresetRegistry.profileKey(key, newId), {\n id: newId,\n label,\n description: `Copy of ${from.label}`,\n patch: mergeData(\n from.patch as WeaveBrushInputProfile,\n {}\n ) as WeaveBrushInputProfilePatch,\n });\n return { ok: true };\n }\n\n removeProfilePreset(\n key: WeaveBrushInputProfileKey,\n id: string\n ): WeaveBrushPresetResult {\n if (this.isFactoryProfilePreset(key, id)) {\n return {\n ok: false,\n error: `\"${id}\" is a factory preset and cannot be removed`,\n };\n }\n return this.customProfiles.delete(\n WeaveBrushPresetRegistry.profileKey(key, id)\n )\n ? { ok: true }\n : { ok: false, error: `Unknown preset \"${id}\"` };\n }\n\n listLookPresets(): WeaveBrushLookPreset[] {\n return [...BRUSH_LOOK_PRESETS, ...this.customLooks.values()];\n }\n\n getLookPreset(id: string) {\n return this.listLookPresets().find((p) => p.id === id);\n }\n\n isFactoryLookPreset(id: string): boolean {\n return BRUSH_LOOK_PRESETS.some((p) => p.id === id);\n }\n\n /** Changes a custom look preset; a factory preset is rejected. */\n setLookPreset(\n id: string,\n patch: WeaveStrokeLookPatch\n ): WeaveBrushPresetResult {\n if (this.isFactoryLookPreset(id)) {\n return {\n ok: false,\n error: `\"${id}\" is a factory preset and cannot be changed; copy it first`,\n };\n }\n const existing = this.customLooks.get(id);\n if (!existing) return { ok: false, error: `Unknown preset \"${id}\"` };\n this.customLooks.set(id, {\n ...existing,\n patch: mergeData(\n (existing.patch ?? {}) as WeaveStrokeLook,\n patch\n ) as WeaveStrokeLookPatch,\n });\n return { ok: true };\n }\n\n copyLookPreset(\n fromId: string,\n newId: string,\n label: string = newId\n ): WeaveBrushPresetResult {\n const from = this.getLookPreset(fromId);\n if (!from) return { ok: false, error: `Unknown preset \"${fromId}\"` };\n if (this.getLookPreset(newId)) {\n return { ok: false, error: `A preset \"${newId}\" already exists` };\n }\n this.customLooks.set(newId, {\n id: newId,\n label,\n description: `Copy of ${from.label}`,\n patch:\n from.patch === null\n ? null\n : (mergeData(\n from.patch as WeaveStrokeLook,\n {}\n ) as WeaveStrokeLookPatch),\n });\n return { ok: true };\n }\n\n removeLookPreset(id: string): WeaveBrushPresetResult {\n if (this.isFactoryLookPreset(id)) {\n return {\n ok: false,\n error: `\"${id}\" is a factory preset and cannot be removed`,\n };\n }\n return this.customLooks.delete(id)\n ? { ok: true }\n : { ok: false, error: `Unknown preset \"${id}\"` };\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport { BRUSH_LAB_PLUGIN_NAME } from '@/actions/brush-tool/constants';\n\nexport { BRUSH_LAB_PLUGIN_NAME };\nexport const BRUSH_LAB_LAYER_ID = 'brushLabLayer';\nexport const BRUSH_LAB_METRICS_EVENT = 'onBrushLabMetrics';\n/** Strokes kept in memory for ghost comparison. */\nexport const BRUSH_LAB_DEFAULT_MAX_GHOSTS = 5;\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { WeaveBrushLabDeviceReport, WeaveBrushLabWarning } from './types';\nimport type { WeaveBrushInputProfileKey } from '@/actions/brush-tool/types';\n\nexport type DevicePointerEvent = {\n pointerType: string;\n pressure: number;\n tiltX?: number;\n tiltY?: number;\n timeStamp: number;\n getCoalescedEvents?: () => unknown[];\n getPredictedEvents?: () => unknown[];\n};\n\nconst WINDOW_MS = 2000;\n\n/**\n * Collects what pointer events say about the device. It keeps counters and a\n * short window of event times, nothing else.\n */\nexport class DeviceReporter {\n private pointerType: string | null = null;\n private times: number[] = [];\n private samples = 0;\n private events = 0;\n private minPressure = Infinity;\n private maxPressure = -Infinity;\n private tilt = false;\n private predicted = false;\n private penAsMouse = false;\n private resolvedProfile: WeaveBrushInputProfileKey | null = null;\n private zoom = 1;\n private fps = 0;\n\n record(e: DevicePointerEvent): void {\n this.pointerType = e.pointerType;\n this.events++;\n\n const coalesced = e.getCoalescedEvents?.().length ?? 0;\n this.samples += Math.max(coalesced, 1);\n\n if (typeof e.getPredictedEvents === 'function') {\n this.predicted = true;\n }\n\n this.times.push(e.timeStamp);\n const cutoff = e.timeStamp - WINDOW_MS;\n while (this.times.length > 1 && this.times[0] < cutoff) this.times.shift();\n\n if (e.pointerType === 'pen' || e.pointerType === 'touch') {\n this.minPressure = Math.min(this.minPressure, e.pressure);\n this.maxPressure = Math.max(this.maxPressure, e.pressure);\n }\n\n const tilted = Boolean(e.tiltX) || Boolean(e.tiltY);\n if (e.pointerType === 'pen' && tilted) this.tilt = true;\n\n // A pen that reports as a mouse still sends real pressure or tilt.\n if (\n e.pointerType === 'mouse' &&\n (tilted || (e.pressure > 0 && e.pressure !== 0.5))\n ) {\n this.penAsMouse = true;\n }\n }\n\n setResolvedProfile(key: WeaveBrushInputProfileKey): void {\n this.resolvedProfile = key;\n }\n\n setZoom(zoom: number): void {\n this.zoom = zoom;\n }\n\n setFps(fps: number): void {\n this.fps = fps;\n }\n\n report(): WeaveBrushLabDeviceReport {\n const first = this.times[0];\n const last = this.times[this.times.length - 1];\n const span = last - first;\n const warnings: WeaveBrushLabWarning[] = [];\n if (this.penAsMouse) warnings.push('penReportsAsMouse');\n\n return {\n pointerType: this.pointerType,\n resolvedProfile: this.resolvedProfile,\n sampleRateHz:\n this.times.length > 1 && span > 0\n ? ((this.times.length - 1) / span) * 1000\n : 0,\n samplesPerEvent: this.events ? this.samples / this.events : 0,\n pressure: Number.isFinite(this.minPressure)\n ? { min: this.minPressure, max: this.maxPressure }\n : null,\n tilt: this.tilt,\n predictedAvailable: this.predicted,\n zoom: this.zoom,\n fps: this.fps,\n warnings,\n };\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { WeaveBrushStabilizerConfig } from '../types';\n\nexport type StabilizerPoint = { x: number; y: number };\n\nexport type StabilizerContext = {\n /** Time of the sample, in ms. */\n now: number;\n /** Current stage zoom. */\n zoom: number;\n};\n\nexport interface BrushStabilizer {\n /** Clears the state; called before the first sample of every stroke. */\n reset(): void;\n /** Starts a stroke at `point`, so the first sample continues from it. */\n seed(point: StabilizerPoint, ctx: StabilizerContext): void;\n /** Returns the position to record for a sample at `point`. */\n apply(point: StabilizerPoint, ctx: StabilizerContext): StabilizerPoint;\n}\n\n/** Time assumed between two samples whose times do not advance, in ms. */\nconst NOMINAL_SAMPLE_INTERVAL_MS = 5;\n\nconst seconds = (now: number, last: number) =>\n (now - last > 0 ? now - last : NOMINAL_SAMPLE_INTERVAL_MS) / 1000;\n\n/**\n * Scale between canvas units and the units distances are configured in: screen\n * pixels when the stabilizer is zoom-aware, canvas units otherwise.\n */\nconst unitScale = (cfg: WeaveBrushStabilizerConfig, ctx: StabilizerContext) =>\n cfg.zoomAware && ctx.zoom > 0 && Number.isFinite(ctx.zoom) ? ctx.zoom : 1;\n\nclass NoStabilizer implements BrushStabilizer {\n reset(): void {\n // stateless\n }\n\n seed(): void {\n // stateless\n }\n\n apply(point: StabilizerPoint): StabilizerPoint {\n return point;\n }\n}\n\n/** One Euro low-pass filter on one axis. */\nclass OneEuroAxis {\n private last = 0;\n private derivative = 0;\n private lastTime = 0;\n private seeded = false;\n\n reset(): void {\n this.seeded = false;\n this.derivative = 0;\n }\n\n seed(value: number, time: number): void {\n this.last = value;\n this.lastTime = time;\n this.derivative = 0;\n this.seeded = true;\n }\n\n filter(value: number, time: number, minCutoff: number, beta: number): number {\n if (!this.seeded) {\n this.seed(value, time);\n return value;\n }\n const dt = seconds(time, this.lastTime);\n const factor = (cutoff: number) => {\n const r = 2 * Math.PI * cutoff * dt;\n return r / (r + 1);\n };\n\n const a = factor(1);\n this.derivative = a * ((value - this.last) / dt) + (1 - a) * this.derivative;\n\n const alpha = factor(minCutoff + beta * Math.abs(this.derivative));\n const filtered = alpha * value + (1 - alpha) * this.last;\n this.last = Number.isFinite(filtered) ? filtered : value;\n this.lastTime = time;\n return this.last;\n }\n}\n\n/**\n * One Euro filter (Casiez, Roussel, Vogel 2012) on the pen position: slow\n * movement is smoothed, fast movement is followed closely.\n */\nclass OneEuroStabilizer implements BrushStabilizer {\n private readonly x = new OneEuroAxis();\n private readonly y = new OneEuroAxis();\n\n constructor(private readonly cfg: WeaveBrushStabilizerConfig) {}\n\n reset(): void {\n this.x.reset();\n this.y.reset();\n }\n\n seed(point: StabilizerPoint, ctx: StabilizerContext): void {\n const s = unitScale(this.cfg, ctx);\n this.x.seed(point.x * s, ctx.now);\n this.y.seed(point.y * s, ctx.now);\n }\n\n apply(point: StabilizerPoint, ctx: StabilizerContext): StabilizerPoint {\n const s = unitScale(this.cfg, ctx);\n return {\n x: this.x.filter(point.x * s, ctx.now, this.cfg.minCutoff, this.cfg.beta) / s,\n y: this.y.filter(point.y * s, ctx.now, this.cfg.minCutoff, this.cfg.beta) / s,\n };\n }\n}\n\n/**\n * Pulled string: the recorded point is held back on a leash of fixed length\n * and only moves when the pen pulls it taut, so movement inside the leash\n * leaves no mark and tight curves are rounded.\n */\nclass PulledStringStabilizer implements BrushStabilizer {\n private tip: StabilizerPoint | null = null;\n\n constructor(private readonly cfg: WeaveBrushStabilizerConfig) {}\n\n reset(): void {\n this.tip = null;\n }\n\n seed(point: StabilizerPoint): void {\n this.tip = { ...point };\n }\n\n apply(point: StabilizerPoint, ctx: StabilizerContext): StabilizerPoint {\n if (!this.tip) {\n this.tip = { ...point };\n return point;\n }\n const leash = this.cfg.radiusPx / unitScale(this.cfg, ctx);\n const dx = point.x - this.tip.x;\n const dy = point.y - this.tip.y;\n const distance = Math.hypot(dx, dy);\n\n if (distance > leash && distance > 0) {\n const pull = (distance - leash) / distance;\n this.tip = { x: this.tip.x + dx * pull, y: this.tip.y + dy * pull };\n }\n return { ...this.tip };\n }\n}\n\n/** Longest time constant of the streamline stabilizer, at amount 1, in ms. */\nconst STREAMLINE_MAX_TAU_MS = 80;\n\n/**\n * Streamline: the recorded point eases towards the pen with a time constant\n * proportional to `amount`, so the result does not depend on how often samples\n * arrive. Amount 0 follows the pen exactly.\n */\nclass StreamlineStabilizer implements BrushStabilizer {\n private tip: StabilizerPoint | null = null;\n private lastTime = 0;\n\n constructor(private readonly cfg: WeaveBrushStabilizerConfig) {}\n\n reset(): void {\n this.tip = null;\n }\n\n seed(point: StabilizerPoint, ctx: StabilizerContext): void {\n this.tip = { ...point };\n this.lastTime = ctx.now;\n }\n\n apply(point: StabilizerPoint, ctx: StabilizerContext): StabilizerPoint {\n const tau = this.cfg.amount * STREAMLINE_MAX_TAU_MS;\n if (!this.tip || tau <= 0) {\n this.tip = { ...point };\n this.lastTime = ctx.now;\n return point;\n }\n const dt = seconds(ctx.now, this.lastTime) * 1000;\n const alpha = 1 - Math.exp(-dt / tau);\n this.tip = {\n x: this.tip.x + (point.x - this.tip.x) * alpha,\n y: this.tip.y + (point.y - this.tip.y) * alpha,\n };\n this.lastTime = ctx.now;\n return { ...this.tip };\n }\n}\n\n/** Creates the stabilizer selected by a profile. */\nexport function createStabilizer(cfg: WeaveBrushStabilizerConfig): BrushStabilizer {\n switch (cfg.type) {\n case 'oneEuro':\n return new OneEuroStabilizer(cfg);\n case 'pulledString':\n return new PulledStringStabilizer(cfg);\n case 'streamline':\n return new StreamlineStabilizer(cfg);\n default:\n return new NoStabilizer();\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Piecewise cubic Bézier fitting of a digitized curve, after Philip J.\n * Schneider, \"An Algorithm for Automatically Fitting Digitized Curves\"\n * (Graphics Gems, 1990). The result is G1-continuous and stays within a\n * tolerance of the input points.\n */\n\nexport type Vec = { x: number; y: number };\n\nexport type FittedSegment = {\n /** Control points: start, two handles, end. */\n bez: [Vec, Vec, Vec, Vec];\n /** Index of the first and last input point the segment covers. */\n first: number;\n last: number;\n /** Curve parameter of each covered input point, from 0 to 1. */\n u: number[];\n};\n\nconst sub = (a: Vec, b: Vec): Vec => ({ x: a.x - b.x, y: a.y - b.y });\nconst add = (a: Vec, b: Vec): Vec => ({ x: a.x + b.x, y: a.y + b.y });\nconst scale = (a: Vec, s: number): Vec => ({ x: a.x * s, y: a.y * s });\nconst dot = (a: Vec, b: Vec) => a.x * b.x + a.y * b.y;\nconst length = (a: Vec) => Math.hypot(a.x, a.y);\nconst normalize = (a: Vec): Vec => {\n const l = length(a);\n return l > 0 ? { x: a.x / l, y: a.y / l } : { x: 0, y: 0 };\n};\n\nconst B0 = (u: number) => (1 - u) ** 3;\nconst B1 = (u: number) => 3 * u * (1 - u) ** 2;\nconst B2 = (u: number) => 3 * u * u * (1 - u);\nconst B3 = (u: number) => u ** 3;\n\n/** Point on a cubic Bézier curve. */\nexport function bezierPoint(b: [Vec, Vec, Vec, Vec], t: number): Vec {\n return {\n x: B0(t) * b[0].x + B1(t) * b[1].x + B2(t) * b[2].x + B3(t) * b[3].x,\n y: B0(t) * b[0].y + B1(t) * b[1].y + B2(t) * b[2].y + B3(t) * b[3].y,\n };\n}\n\nfunction derivative(b: [Vec, Vec, Vec, Vec], t: number): Vec {\n const q = [sub(b[1], b[0]), sub(b[2], b[1]), sub(b[3], b[2])].map((v) => scale(v, 3));\n const s = 1 - t;\n return {\n x: s * s * q[0].x + 2 * s * t * q[1].x + t * t * q[2].x,\n y: s * s * q[0].y + 2 * s * t * q[1].y + t * t * q[2].y,\n };\n}\n\nfunction secondDerivative(b: [Vec, Vec, Vec, Vec], t: number): Vec {\n const q = [\n add(sub(b[2], scale(b[1], 2)), b[0]),\n add(sub(b[3], scale(b[2], 2)), b[1]),\n ].map((v) => scale(v, 6));\n return {\n x: (1 - t) * q[0].x + t * q[1].x,\n y: (1 - t) * q[0].y + t * q[1].y,\n };\n}\n\n/**\n * Direction of the curve at `index`, estimated over a window at least\n * `window` long on each side (but inside `first..last`), so that noise in the\n * nearest samples does not tilt it. With `before` false only the following\n * points are used (a start tangent); with `after` false only the preceding\n * ones (an end tangent). The vector points forward along the stroke.\n */\nfunction windowTangent(\n pts: Vec[],\n index: number,\n first: number,\n last: number,\n window: number,\n before: boolean,\n after: boolean\n): Vec {\n let back = index;\n if (before) {\n while (back > first && length(sub(pts[index], pts[back])) < window) back--;\n }\n let ahead = index;\n if (after) {\n while (ahead < last && length(sub(pts[ahead], pts[index])) < window) ahead++;\n }\n return normalize(sub(pts[ahead], pts[back]));\n}\n\nfunction chordLengthParameterize(pts: Vec[], first: number, last: number): number[] {\n const u = [0];\n for (let i = first + 1; i <= last; i++) {\n u.push(u[u.length - 1] + length(sub(pts[i], pts[i - 1])));\n }\n const total = u[u.length - 1] || 1;\n return u.map((v) => v / total);\n}\n\nfunction generateBezier(\n pts: Vec[],\n first: number,\n last: number,\n u: number[],\n tHat1: Vec,\n tHat2: Vec\n): [Vec, Vec, Vec, Vec] {\n const p0 = pts[first];\n const p3 = pts[last];\n\n let c00 = 0, c01 = 0, c11 = 0, x0 = 0, x1 = 0;\n for (let i = 0; i < u.length; i++) {\n const a0 = scale(tHat1, B1(u[i]));\n const a1 = scale(tHat2, B2(u[i]));\n c00 += dot(a0, a0);\n c01 += dot(a0, a1);\n c11 += dot(a1, a1);\n const tmp = sub(\n pts[first + i],\n add(scale(p0, B0(u[i]) + B1(u[i])), scale(p3, B2(u[i]) + B3(u[i])))\n );\n x0 += dot(a0, tmp);\n x1 += dot(a1, tmp);\n }\n\n const det = c00 * c11 - c01 * c01;\n const alphaL = det === 0 ? 0 : (x0 * c11 - x1 * c01) / det;\n const alphaR = det === 0 ? 0 : (c00 * x1 - c01 * x0) / det;\n\n const segLength = length(sub(p3, p0));\n const epsilon = 1e-6 * segLength;\n if (alphaL < epsilon || alphaR < epsilon) {\n const d = segLength / 3;\n return [p0, add(p0, scale(tHat1, d)), add(p3, scale(tHat2, d)), p3];\n }\n return [p0, add(p0, scale(tHat1, alphaL)), add(p3, scale(tHat2, alphaR)), p3];\n}\n\nfunction newtonRaphson(b: [Vec, Vec, Vec, Vec], p: Vec, u: number): number {\n const d = sub(bezierPoint(b, u), p);\n const d1 = derivative(b, u);\n const d2 = secondDerivative(b, u);\n const numerator = dot(d, d1);\n const denominator = dot(d1, d1) + dot(d, d2);\n return denominator === 0 ? u : u - numerator / denominator;\n}\n\nfunction maxError(\n pts: Vec[],\n first: number,\n last: number,\n b: [Vec, Vec, Vec, Vec],\n u: number[]\n): { error: number; split: number } {\n let split = Math.floor((last - first + 1) / 2) + first;\n let max = 0;\n for (let i = first + 1; i < last; i++) {\n const d = sub(bezierPoint(b, u[i - first]), pts[i]);\n const e = dot(d, d);\n if (e >= max) {\n max = e;\n split = i;\n }\n }\n return { error: max, split };\n}\n\nfunction fitCubic(\n pts: Vec[],\n first: number,\n last: number,\n tHat1: Vec,\n tHat2: Vec,\n errorSq: number,\n window: number,\n out: FittedSegment[]\n): void {\n if (last - first === 1) {\n const d = length(sub(pts[last], pts[first])) / 3;\n out.push({\n bez: [\n pts[first],\n add(pts[first], scale(tHat1, d)),\n add(pts[last], scale(tHat2, d)),\n pts[last],\n ],\n first,\n last,\n u: [0, 1],\n });\n return;\n }\n\n let u = chordLengthParameterize(pts, first, last);\n let bez = generateBezier(pts, first, last, u, tHat1, tHat2);\n let { error, split } = maxError(pts, first, last, bez, u);\n\n if (error < errorSq) {\n out.push({ bez, first, last, u });\n return;\n }\n\n if (error < errorSq * 4) {\n for (let i = 0; i < 4; i++) {\n const prime = u.map((v, k) => {\n const p = newtonRaphson(bez, pts[first + k], v);\n return Number.isFinite(p) ? Math.min(Math.max(p, 0), 1) : v;\n });\n bez = generateBezier(pts, first, last, prime, tHat1, tHat2);\n ({ error, split } = maxError(pts, first, last, bez, prime));\n u = prime;\n if (error < errorSq) {\n out.push({ bez, first, last, u });\n return;\n }\n }\n }\n\n const center = windowTangent(pts, split, first, last, window, true, true);\n const back = scale(center, -1);\n fitCubic(pts, first, split, tHat1, back, errorSq, window, out);\n fitCubic(pts, split, last, center, tHat2, errorSq, window, out);\n}\n\n/**\n * Fits cubic Bézier segments to a polyline so that no input point is farther\n * than `tolerance` from the curve. Needs at least two points, none repeated\n * consecutively.\n */\nexport function fitCurve(points: Vec[], tolerance: number): FittedSegment[] {\n if (points.length < 2) return [];\n const out: FittedSegment[] = [];\n const last = points.length - 1;\n // Tangents are estimated over a few tolerances, wider than the noise the\n // tolerance is meant to absorb, instead of from the two nearest samples.\n const window = tolerance * 3;\n fitCubic(\n points,\n 0,\n last,\n windowTangent(points, 0, 0, last, window, false, true),\n scale(windowTangent(points, last, 0, last, window, true, false), -1),\n tolerance * tolerance,\n window,\n out\n );\n return out;\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport simplify from 'simplify-js';\nimport type { WeaveStrokePoint } from '@/nodes/stroke/types';\nimport type { WeaveBrushFinalizeConfig } from '../types';\nimport { bezierPoint, fitCurve, type FittedSegment } from './bezier-fit';\n\n/** Size of one screen pixel in canvas units at a zoom level. */\nconst pixelSize = (zoom: number) =>\n zoom > 0 && Number.isFinite(zoom) ? 1 / zoom : 1;\n\n/**\n * Tolerance applied when a stroke is finished, in canvas units. The legacy\n * value is the tool-level tolerance in canvas units; with the `screen` unit the\n * configured pixels are converted with the zoom in force when the stroke ends,\n * so the same setting gives the same on-screen fidelity at any zoom.\n */\nexport function resolveFinalizeTolerance(\n cfg: WeaveBrushFinalizeConfig,\n toolTolerance: number,\n zoom = 1\n): number {\n const tolerance = cfg.tolerance ?? toolTolerance;\n return cfg.toleranceUnit === 'screen' ? tolerance * pixelSize(zoom) : tolerance;\n}\n\ntype Segment = { a: WeaveStrokePoint; b: WeaveStrokePoint };\n\n/** Distance from `p` to the segment, and where along it the closest point is. */\nfunction toSegment(p: WeaveStrokePoint, { a, b }: Segment) {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lengthSq = dx * dx + dy * dy;\n const t = lengthSq\n ? Math.min(1, Math.max(0, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSq))\n : 0;\n return { distance: Math.hypot(p.x - (a.x + dx * t), p.y - (a.y + dy * t)), t };\n}\n\n/**\n * Douglas-Peucker simplification that also keeps pressure detail: a point is\n * kept when it is off the straight path by more than `tolerance`, or when its\n * pressure differs from the pressure interpolated along that path by more than\n * `tolerance / pressureWeight`.\n */\nexport function simplifyWithPressure(\n points: WeaveStrokePoint[],\n tolerance: number,\n pressureWeight: number\n): WeaveStrokePoint[] {\n if (points.length <= 2) return points;\n\n const keep = new Uint8Array(points.length);\n keep[0] = keep[points.length - 1] = 1;\n const stack: [number, number][] = [[0, points.length - 1]];\n\n while (stack.length > 0) {\n const [first, last] = stack.pop()!;\n let worst = 0;\n let index = -1;\n\n for (let i = first + 1; i < last; i++) {\n const { distance, t } = toSegment(points[i], {\n a: points[first],\n b: points[last],\n });\n const expected =\n points[first].pressure +\n (points[last].pressure - points[first].pressure) * t;\n const error = Math.max(\n distance,\n Math.abs(points[i].pressure - expected) * pressureWeight\n );\n if (error > worst) {\n worst = error;\n index = i;\n }\n }\n\n if (worst > tolerance && index !== -1) {\n keep[index] = 1;\n stack.push([first, index], [index, last]);\n }\n }\n\n return points.filter((_, i) => keep[i] === 1);\n}\n\n/** Pressure at curve parameter `t` of a segment, interpolated between input points. */\nfunction pressureAt(\n seg: FittedSegment,\n points: WeaveStrokePoint[],\n t: number\n): number {\n let prev = seg.u[0];\n for (let k = 1; k < seg.u.length; k++) {\n const next = Math.max(seg.u[k], prev);\n if (t <= next || k === seg.u.length - 1) {\n const span = next - prev;\n const f = span > 0 ? Math.min(1, Math.max(0, (t - prev) / span)) : 0;\n const p0 = points[seg.first + k - 1].pressure;\n const p1 = points[seg.first + k].pressure;\n return p0 + (p1 - p0) * f;\n }\n prev = next;\n }\n return points[seg.last].pressure;\n}\n\n/**\n * Fits a smooth curve through the stroke and samples it back to points, so the\n * saved format stays `{x, y, pressure}`. `tolerance` is the largest distance\n * between the curve and an input point; `spacing` is the distance between\n * sampled points. Both are in canvas units. The first and last points are kept\n * exactly.\n */\nexport function fitAndResample(\n points: WeaveStrokePoint[],\n tolerance: number,\n spacing: number\n): WeaveStrokePoint[] {\n if (points.length < 3 || !(tolerance > 0)) return points;\n\n // Consecutive duplicates have no direction; the fit works on distinct points.\n const distinct = points.filter(\n (p, i) => i === 0 || p.x !== points[i - 1].x || p.y !== points[i - 1].y\n );\n if (distinct.length < 3) return points;\n\n const segments = fitCurve(distinct, tolerance);\n if (segments.length === 0) return points;\n\n const out: WeaveStrokePoint[] = [];\n for (const seg of segments) {\n // approximate arc length of the segment\n let arc = 0;\n let prev = seg.bez[0];\n for (let k = 1; k <= 16; k++) {\n const q = bezierPoint(seg.bez, k / 16);\n arc += Math.hypot(q.x - prev.x, q.y - prev.y);\n prev = q;\n }\n const steps = Math.max(1, Math.ceil(arc / Math.max(spacing, 1e-6)));\n for (let k = 0; k < steps; k++) {\n const t = k / steps;\n const q = k === 0 ? seg.bez[0] : bezierPoint(seg.bez, t);\n out.push({ x: q.x, y: q.y, pressure: pressureAt(seg, distinct, t) });\n }\n }\n\n const end = distinct[distinct.length - 1];\n out.push({ x: end.x, y: end.y, pressure: end.pressure });\n return out;\n}\n\n/** Reduces a finished stroke's points as selected by the profile. */\nexport function finalizePoints(\n points: WeaveStrokePoint[],\n cfg: WeaveBrushFinalizeConfig,\n toolTolerance: number,\n zoom = 1\n): WeaveStrokePoint[] {\n const tolerance = resolveFinalizeTolerance(cfg, toolTolerance, zoom);\n\n switch (cfg.mode) {\n case 'none':\n return points;\n case 'dpPressure':\n return simplifyWithPressure(\n points,\n tolerance,\n cfg.toleranceUnit === 'screen'\n ? cfg.pressureWeight * pixelSize(zoom)\n : cfg.pressureWeight\n );\n case 'bezierFit':\n return fitAndResample(\n points,\n tolerance,\n cfg.resampleSpacingPx * pixelSize(zoom)\n );\n default:\n // simplify-js returns the original point objects, so pressure is preserved.\n return simplify(points, tolerance, true) as WeaveStrokePoint[];\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport { createStabilizer } from '@/actions/brush-tool/stages/stabilizer';\nimport { finalizePoints } from '@/actions/brush-tool/stages/finalize';\nimport type { WeaveBrushInputProfile } from '@/actions/brush-tool/types';\nimport type { LabPressurePoint, LabRecording } from './types';\n\n/**\n * Draws a recorded gesture again through another brush: the same pointer\n * events, captured, stabilized and finished as that brush would have done.\n * Positions only: width, pressure smoothing and the outline are not replayed.\n */\nexport function replayRecording(\n recording: LabRecording,\n profile: WeaveBrushInputProfile,\n simplifyTolerance: number\n): LabPressurePoint[] {\n const coalesced = profile.capture.source === 'coalesced';\n const minMove = profile.capture.minMovePx;\n\n // What the brush would have kept: every sample of an event, or just its last.\n const captured: { time: number; point: LabPressurePoint }[] = [];\n for (const event of recording.gesture.events) {\n const picked = coalesced ? event.samples : event.samples.slice(-1);\n // each coalesced sample has its own time, as the brush reads it\n for (const point of picked) {\n captured.push({ time: point.time ?? event.time, point });\n }\n }\n if (captured.length === 0) return [];\n\n const kept = captured.filter((c, i) => {\n if (i === 0 || minMove <= 0) return true;\n const prev = captured[i - 1].point;\n return (\n Math.hypot(c.point.x - prev.x, c.point.y - prev.y) * recording.zoom >=\n minMove\n );\n });\n\n const stabilizer = createStabilizer(profile.stabilizer);\n stabilizer.reset();\n const ctx = (time: number) => ({ now: time, zoom: recording.zoom });\n stabilizer.seed(kept[0].point, ctx(kept[0].time));\n\n const points: LabPressurePoint[] = kept.map((c) => {\n const p = stabilizer.apply(c.point, ctx(c.time));\n return { x: p.x, y: p.y, pressure: c.point.pressure };\n });\n\n // A stabilized stroke lags the pen: the brush completes it where the pen\n // was lifted.\n const cfg = profile.stabilizer;\n const lastRaw = kept[kept.length - 1].point;\n const lastOut = points[points.length - 1];\n if (\n cfg.type !== 'none' &&\n cfg.catchUpOnEnd &&\n (lastRaw.x !== lastOut.x || lastRaw.y !== lastOut.y)\n ) {\n points.push({ x: lastRaw.x, y: lastRaw.y, pressure: lastOut.pressure });\n }\n\n return finalizePoints(\n points,\n profile.finalize,\n simplifyTolerance,\n recording.zoom\n );\n}\n\n/** The last `max` recordings; the oldest are dropped. Memory only. */\nexport class RecordingStore {\n private items: LabRecording[] = [];\n\n constructor(private max: number) {}\n\n setMax(max: number): void {\n this.max = Math.max(1, Math.floor(max));\n this.trim();\n }\n\n add(recording: LabRecording): void {\n this.items.push(recording);\n this.trim();\n }\n\n all(): LabRecording[] {\n return [...this.items];\n }\n\n last(): LabRecording | undefined {\n return this.items[this.items.length - 1];\n }\n\n clear(): void {\n this.items = [];\n }\n\n get size(): number {\n return this.items.length;\n }\n\n private trim(): void {\n while (this.items.length > this.max) this.items.shift();\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { LabGesture, LabPressurePoint } from './types';\n\nexport type RecorderEvent = {\n pointerId: number;\n time: number;\n /** One entry per coalesced sample, or the event itself when there are none. */\n samples: LabPressurePoint[];\n};\n\n/**\n * Records the pointer events of one gesture, whatever brush is active: every\n * coalesced sample of every event, with its time. The first pointer that goes\n * down owns the gesture; others are ignored.\n */\nexport class GestureRecorder {\n private pointerId: number | null = null;\n private events: LabGesture['events'] = [];\n\n begin(e: RecorderEvent): void {\n if (this.pointerId !== null) return;\n this.pointerId = e.pointerId;\n this.events = [{ time: e.time, samples: e.samples }];\n }\n\n add(e: RecorderEvent): void {\n if (e.pointerId !== this.pointerId) return;\n this.events.push({ time: e.time, samples: e.samples });\n }\n\n end(pointerId: number): void {\n if (pointerId === this.pointerId) this.pointerId = null;\n }\n\n /** A copy of the gesture so far. */\n snapshot(): LabGesture {\n return {\n events: this.events.map((ev) => ({\n time: ev.time,\n samples: ev.samples.map((s) => ({ ...s })),\n })),\n };\n }\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {\n LabPoint,\n LabPressurePoint,\n LabRecordedSample,\n WeaveBrushLabMetrics,\n} from './types';\n\nconst dist = (a: LabPoint, b: LabPoint) => Math.hypot(a.x - b.x, a.y - b.y);\n\nfunction distanceToSegment(p: LabPoint, a: LabPoint, b: LabPoint): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const l = dx * dx + dy * dy;\n const t = l\n ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / l))\n : 0;\n return Math.hypot(p.x - (a.x + dx * t), p.y - (a.y + dy * t));\n}\n\nconst mean = (values: number[]) =>\n values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0;\n\nexport type StrokeMetricsInput = {\n samples: LabRecordedSample[];\n beforeFinalize: LabPressurePoint[];\n finalPoints: LabPressurePoint[];\n strokeWidth: number;\n drawMs: number;\n};\n\n/** Measures a finished stroke from what the brush tool reported. */\nexport function computeStrokeMetrics(\n input: StrokeMetricsInput\n): Omit<WeaveBrushLabMetrics, 'profile' | 'preset' | 'scenario'> {\n const real = input.samples.filter((s) => !s.predicted);\n\n let droppedDuplicates = 0;\n for (let i = 1; i < real.length; i++) {\n if (dist(real[i].raw, real[i - 1].raw) === 0) droppedDuplicates++;\n }\n\n const spanMs =\n real.length > 1 ? real[real.length - 1].time - real[0].time : 0;\n const effectiveRateHz = spanMs > 0 ? ((real.length - 1) / spanMs) * 1000 : 0;\n\n const jitters: number[] = [];\n for (let i = 1; i < real.length - 1; i++) {\n jitters.push(\n distanceToSegment(real[i].raw, real[i - 1].raw, real[i + 1].raw)\n );\n }\n\n const lag = mean(real.map((s) => dist(s.raw, s.stabilized)));\n\n let movedOnFinish = 0;\n if (input.finalPoints.length > 0) {\n for (const p of input.beforeFinalize) {\n let best = Infinity;\n if (input.finalPoints.length === 1) {\n best = dist(p, input.finalPoints[0]);\n } else {\n for (let i = 1; i < input.finalPoints.length; i++) {\n best = Math.min(\n best,\n distanceToSegment(p, input.finalPoints[i - 1], input.finalPoints[i])\n );\n }\n }\n movedOnFinish = Math.max(movedOnFinish, best);\n }\n }\n\n const steps: number[] = [];\n for (let i = 1; i < input.finalPoints.length; i++) {\n steps.push(\n Math.abs(\n input.finalPoints[i].pressure - input.finalPoints[i - 1].pressure\n ) * input.strokeWidth\n );\n }\n\n return {\n samples: real.length,\n points: input.finalPoints.length,\n droppedDuplicates,\n effectiveRateHz,\n jitter: mean(jitters),\n lag,\n movedOnFinish,\n widthRoughness: mean(steps),\n drawMs: input.drawMs,\n };\n}\n","// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)\n//\n// SPDX-License-Identifier: Apache-2.0\n\nimport Konva from 'konva';\n// Resolved to the SDK itself when published, so the lab extends the SDK's own\n// WeavePlugin (see tsconfig `paths` and the lab build entry).\nimport { WeavePlugin } from '@inditextech/weave-sdk';\nimport {\n BRUSH_PROFILE_PRESETS,\n BRUSH_SCENARIOS,\n resolveBrushProfilePatch,\n} from '@/actions/brush-tool/tunables/presets';\nimport type {\n WeaveBrushInputProfile,\n WeaveBrushInputProfileKey,\n WeaveBrushTraceSink,\n} from '@/actions/brush-tool/types';\nimport {\n BRUSH_LAB_DEFAULT_MAX_GHOSTS,\n BRUSH_LAB_LAYER_ID,\n BRUSH_LAB_METRICS_EVENT,\n BRUSH_LAB_PLUGIN_NAME,\n} from './constants';\nimport { DeviceReporter, type DevicePointerEvent } from './device-report';\nimport { RecordingStore, replayRecording } from './ghosts';\nimport { GestureRecorder } from './recorder';\nimport { computeStrokeMetrics } from './metrics';\nimport type {\n LabPressurePoint,\n LabRecordedSample,\n WeaveBrushLabDeviceReport,\n WeaveBrushLabCompareResult,\n WeaveBrushLabMetrics,\n WeaveBrushLabOverlays,\n} from './types';\n\ntype CurrentStroke = {\n profileKey: WeaveBrushInputProfileKey;\n preset: string;\n scenario?: string;\n profile: WeaveBrushInputProfile;\n strokeWidth: number;\n zoom: number;\n samples: LabRecordedSample[];\n batchMs: number;\n};\n\ntype LastStroke = {\n samples: LabRecordedSample[];\n finalPoints: LabPressurePoint[];\n};\n\n/**\n * Lab for tuning the brush on real devices. It listens to the brush tool and\n * draws overlays on a layer of its own. It never changes the document, and it\n * keeps everything it records in memory only: nothing is stored, sent or\n * written anywhere.\n */\nexport class WeaveBrushLabPlugin\n extends WeavePlugin\n implements WeaveBrushTraceSink\n{\n private overlays: WeaveBrushLabOverlays = {\n raw: false,\n stabilized: false,\n final: false,\n pressure: false,\n };\n private reporter = new DeviceReporter();\n private recordings = new RecordingStore(BRUSH_LAB_DEFAULT_MAX_GHOSTS);\n private current: CurrentStroke | null = null;\n private last: LastStroke | null = null;\n private lastMetrics: WeaveBrushLabMetrics | null = null;\n private compareScenario: string | null = null;\n private recorder = new GestureRecorder();\n private listeners: [string, (e: PointerEvent) => void, boolean][] = [];\n private frameHandle: number | null = null;\n\n constructor(params?: { maxGhosts?: number }) {\n super();\n if (params?.maxGhosts) this.recordings.setMax(params.maxGhosts);\n this.initialize();\n }\n\n initialize(): void {\n this.enabled = true;\n }\n\n getName(): string {\n return BRUSH_LAB_PLUGIN_NAME;\n }\n\n getLayerName(): string {\n return BRUSH_LAB_LAYER_ID;\n }\n\n getLayer(): Konva.Layer | undefined {\n return this.instance?.getStage?.()?.findOne?.(`#${this.getLayerName()}`) as\n | Konva.Layer\n | undefined;\n }\n\n onInit(): void {\n const stage = this.instance.getStage();\n stage.add(\n new Konva.Layer({\n id: this.getLayerName(),\n draggable: false,\n listening: false,\n })\n );\n if (this.enabled) this.attach();\n }\n\n onRender(): void {\n // nothing to render on its own\n }\n\n enable(): void {\n this.enabled = true;\n this.attach();\n this.getLayer()?.show();\n }\n\n disable(): void {\n this.enabled = false;\n this.detach();\n this.getLayer()?.hide();\n }\n\n /** Pointer event position in the stage's drawing coordinates. */\n private toStagePoint(e: PointerEvent): { x: number; y: number } {\n const stage = this.instance.getStage();\n const rect = stage.container().getBoundingClientRect();\n return stage\n .getAbsoluteTransform()\n .copy()\n .invert()\n .point({ x: e.clientX - rect.left, y: e.clientY - rect.top });\n }\n\n private recorderEvent(e: PointerEvent) {\n const sources =\n typeof e.getCoalescedEvents === 'function' &&\n e.getCoalescedEvents().length > 0\n ? e.getCoalescedEvents()\n : [e];\n return {\n pointerId: e.pointerId,\n time: e.timeStamp,\n samples: sources.map((c) => ({\n ...this.toStagePoint(c),\n pressure: c.pressure,\n time:\n typeof c.timeStamp === 'number' && c.timeStamp > 0\n ? c.timeStamp\n : e.timeStamp,\n })),\n };\n }\n\n private attach(): void {\n const container = this.instance?.getStage?.()?.container?.();\n if (container && this.listeners.length === 0) {\n // On the window, in the capture phase: once a stroke starts, the app may\n // capture the pointer on another element, and a listener on the stage\n // container would then stop hearing the moves.\n const inStage = (e: PointerEvent) =>\n typeof e.composedPath === 'function'\n ? e.composedPath().includes(container)\n : true;\n const add = (type: string, fn: (e: PointerEvent) => void) => {\n window.addEventListener(type, fn as EventListener, {\n passive: true,\n capture: true,\n });\n this.listeners.push([type, fn, true]);\n };\n add('pointerdown', (e) => {\n if (inStage(e)) this.recorder.begin(this.recorderEvent(e));\n });\n add('pointermove', (e) => {\n if (inStage(e)) {\n this.reporter.record(e as unknown as DevicePointerEvent);\n this.reporter.setZoom(this.instance.getStage().scaleX());\n }\n this.recorder.add(this.recorderEvent(e));\n });\n add('pointerup', (e) => this.recorder.end(e.pointerId));\n add('pointercancel', (e) => this.recorder.end(e.pointerId));\n }\n if (\n this.frameHandle === null &&\n typeof requestAnimationFrame === 'function'\n ) {\n this.countFrames();\n }\n }\n\n private detach(): void {\n for (const [type, fn, capture] of this.listeners) {\n window.removeEventListener(type, fn as EventListener, { capture });\n }\n this.listeners = [];\n if (\n this.frameHandle !== null &&\n typeof cancelAnimationFrame === 'function'\n ) {\n cancelAnimationFrame(this.frameHandle);\n }\n this.frameHandle = null;\n }\n\n private countFrames(): void {\n let frames = 0;\n let since = performance.now();\n const tick = (now: number) => {\n frames++;\n if (now - since >= 1000) {\n this.reporter.setFps((frames * 1000) / (now - since));\n frames = 0;\n since = now;\n }\n this.frameHandle = requestAnimationFrame(tick);\n };\n this.frameHandle = requestAnimationFrame(tick);\n }\n\n // -- reading ----------------------------------------------------------\n\n getDeviceReport(): WeaveBrushLabDeviceReport {\n return this.reporter.report();\n }\n\n getLastMetrics(): WeaveBrushLabMetrics | null {\n return this.lastMetrics;\n }\n\n getOverlays(): WeaveBrushLabOverlays {\n return { ...this.overlays };\n }\n\n getRecordingCount(): number {\n return this.recordings.size;\n }\n\n // -- overlays ---------------------------------------------------------\n\n setOverlay(name: keyof WeaveBrushLabOverlays, on: boolean): void {\n this.overlays[name] = on;\n this.redraw();\n }\n\n // -- ghosts -----------------------------------------------------------\n\n setMaxGhosts(max: number): void {\n this.recordings.setMax(max);\n this.redraw();\n }\n\n /**\n * Draws the last stroke again through each named brush (every one when none\n * are given), so the same handwriting can be compared across them.\n */\n compareLast(scenarioId: string): WeaveBrushLabCompareResult {\n if (!BRUSH_SCENARIOS.some((x) => x.id === scenarioId)) {\n return { lines: 0, reason: `Unknown brush \"${scenarioId}\"` };\n }\n this.compareScenario = scenarioId;\n const recording = this.recordings.last();\n if (!recording) {\n return { lines: 0, reason: 'No stroke recorded yet: draw one first' };\n }\n const events = recording.gesture.events.length;\n if (events === 0) {\n return {\n lines: 0,\n reason: 'The stroke has no pointer events (nothing was recorded)',\n };\n }\n this.redraw();\n const lines = this.getLayer()?.find('.lab-ghost').length ?? 0;\n return lines > 0\n ? { lines, events }\n : { lines: 0, events, reason: 'No brush produced a line' };\n }\n\n /** Forgets every kept stroke and removes the ghosts. */\n clearGhosts(): void {\n this.recordings.clear();\n this.compareScenario = null;\n this.redraw();\n }\n\n // -- brush tool sink ----------------------------------------------------\n\n onStrokeStart(\n info: Parameters<WeaveBrushTraceSink['onStrokeStart']>[0]\n ): void {\n this.reporter.setResolvedProfile(info.profile);\n this.current = {\n profileKey: info.profile,\n preset: info.preset,\n ...(info.scenario ? { scenario: info.scenario } : {}),\n profile: info.profileConfig,\n strokeWidth: info.strokeWidth,\n zoom: info.zoom,\n samples: [],\n batchMs: 0,\n };\n this.getLayer()?.destroyChildren();\n this.last = null;\n this.compareScenario = null;\n }\n\n onSample(sample: LabRecordedSample): void {\n if (!this.current) return;\n this.current.samples.push(sample);\n\n if (sample.predicted) return;\n const layer = this.getLayer();\n if (!layer) return;\n const r = this.markerRadius();\n if (this.overlays.raw) {\n layer.add(\n new Konva.Circle({\n x: sample.raw.x,\n y: sample.raw.y,\n radius: r,\n fill: '#ef4444',\n name: 'lab-raw',\n })\n );\n }\n if (this.overlays.stabilized) {\n layer.add(\n new Konva.Circle({\n x: sample.stabilized.x,\n y: sample.stabilized.y,\n radius: r,\n fill: '#2563eb',\n name: 'lab-stabilized',\n })\n );\n }\n layer.batchDraw();\n }\n\n onBatch(info: { ms: number; samples: number }): void {\n if (this.current) this.current.batchMs += info.ms;\n }\n\n onStrokeEnd(info: Parameters<WeaveBrushTraceSink['onStrokeEnd']>[0]): void {\n const current = this.current;\n this.current = null;\n if (!current) return;\n\n const measured = computeStrokeMetrics({\n samples: current.samples,\n beforeFinalize: info.beforeFinalize,\n finalPoints: info.finalPoints,\n strokeWidth: info.strokeWidth,\n drawMs: current.batchMs + info.finalizeMs,\n });\n\n const metrics: WeaveBrushLabMetrics = {\n profile: current.profileKey,\n preset: current.preset,\n ...(current.scenario ? { scenario: current.scenario } : {}),\n ...measured,\n };\n this.lastMetrics = metrics;\n\n this.recordings.add({\n profileKey: current.profileKey,\n gesture: this.recorder.snapshot(),\n strokeWidth: current.strokeWidth,\n zoom: current.zoom,\n });\n this.last = { samples: current.samples, finalPoints: info.finalPoints };\n\n this.instance.emitEvent<WeaveBrushLabMetrics>(\n BRUSH_LAB_METRICS_EVENT,\n metrics\n );\n this.redraw();\n }\n\n // -- drawing ------------------------------------------------------------\n\n private markerRadius(): number {\n const zoom = this.instance.getStage().scaleX();\n return 2 / (zoom > 0 ? zoom : 1);\n }\n\n private redraw(): void {\n const layer = this.getLayer();\n if (!layer) return;\n layer.destroyChildren();\n\n const r = this.markerRadius();\n const last = this.last;\n\n if (last) {\n const real = last.samples.filter((s) => !s.predicted);\n if (this.overlays.raw) {\n for (const s of real) {\n layer.add(\n new Konva.Circle({\n x: s.raw.x,\n y: s.raw.y,\n radius: r,\n fill: '#ef4444',\n name: 'lab-raw',\n })\n );\n }\n }\n if (this.overlays.stabilized) {\n for (const s of real) {\n layer.add(\n new Konva.Circle({\n x: s.stabilized.x,\n y: s.stabilized.y,\n radius: r,\n fill: '#2563eb',\n name: 'lab-stabilized',\n })\n );\n }\n }\n if (this.overlays.final) {\n for (const p of last.finalPoints) {\n layer.add(\n new Konva.Circle({\n x: p.x,\n y: p.y,\n radius: r * 1.5,\n stroke: '#16a34a',\n strokeWidth: r / 2,\n name: 'lab-final',\n })\n );\n }\n }\n if (this.overlays.pressure && last.finalPoints.length > 1) {\n const bottom = Math.max(...last.finalPoints.map((p) => p.y)) + 30 * r;\n const flat: number[] = [];\n for (const p of last.finalPoints)\n flat.push(p.x, bottom - p.pressure * 20 * r);\n layer.add(\n new Konva.Line({\n points: flat,\n stroke: '#a855f7',\n strokeWidth: r,\n name: 'lab-pressure',\n })\n );\n }\n }\n\n const recording = this.recordings.last();\n if (recording && this.compareScenario) {\n const scenario = BRUSH_SCENARIOS.find(\n (x) => x.id === this.compareScenario\n );\n const preset = scenario\n ? BRUSH_PROFILE_PRESETS[recording.profileKey].find(\n (p) => p.id === scenario.profiles[recording.profileKey]\n )\n : undefined;\n const toFlat = (pts: { x: number; y: number }[]) =>\n pts.flatMap((p) => [p.x, p.y]);\n\n // what was actually drawn, in black, under the chosen brush in red\n if (this.last && this.last.finalPoints.length > 1) {\n layer.add(\n new Konva.Line({\n points: toFlat(this.last.finalPoints),\n stroke: '#111111',\n strokeWidth: r * 2.5,\n lineCap: 'round',\n lineJoin: 'round',\n opacity: 0.9,\n name: 'lab-actual',\n })\n );\n }\n if (scenario && preset) {\n const points = replayRecording(\n recording,\n resolveBrushProfilePatch(preset.patch),\n 1\n );\n if (points.length >= 2) {\n layer.add(\n new Konva.Line({\n points: toFlat(points),\n stroke: '#e11d48',\n strokeWidth: r,\n lineCap: 'round',\n lineJoin: 'round',\n name: 'lab-ghost',\n })\n );\n layer.add(\n new Konva.Text({\n x: points[0].x,\n y: points[0].y - 14 * r,\n text: `${scenario.label.replace(\n /^[A-Z]: /,\n ''\n )} (red) vs drawn (black)`,\n fontSize: 10 * r,\n fill: '#e11d48',\n name: 'lab-ghost-label',\n })\n );\n }\n }\n }\n\n layer.moveToTop();\n layer.batchDraw();\n }\n}\n"],"mappings":"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"}
|