Commit Graph

5 Commits

Author SHA1 Message Date
4f6fb69dee fix: soft-clamp pinch zoom and Krita-inspired brush opacity
All checks were successful
CI / Windows build (push) Successful in 10m28s
Hard SDROP avalanches froze lastRaw while zoom still crawled; soft-clamp
and re-anchor instead. Ballpoint is near-solid, pencil uses soft √p without
multiply stacking; PDF ink falls back to nearest page during zoom settle.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 20:51:15 +08:00
4a6fe7d05e fix: Surface pen pressure, zoom glitches, sticky notes, selection UX
All checks were successful
CI / Windows build (push) Successful in 8m19s
Wire Win32 pressure into Dart, tighten pinch guards, use geometric shape
strokes, expand the ink palette, and replace scratch-link split view with
an on-page sticky that shares the sidecar repo.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 19:52:15 +08:00
46589a4c87 feat(pen): persist brush kind so it survives reload
Some checks failed
CI / Windows build (push) Has been cancelled
Closes TODO(brush-persist). EditorStroke now serializes its brush as
the stable BrushKind name; sidecars written before this field, and any
unknown name, load as fountainPen (back-compat). PenStroke<->EditorStroke
carry brush both ways, so a ballpoint/highlighter/pencil stroke keeps
its opacity/blend after a document is closed and reopened.

Note: InkStroke (the note/scratchpad world-coord format) has no brush
field, so notes derive brush from the tool — highlighter is preserved,
ballpoint/pencil collapse to fountainPen on reload (TODO: extend
InkStroke). PDF documents persist brush fully. analyze clean,
379 tests green.
2026-06-24 23:40:40 +08:00
6c2dd71b82 feat(pen): brush opacity + highlighter multiply
Some checks failed
CI / Windows build (push) Has been cancelled
Honor each brush's opacity/blend so the brushes feel distinct
(closes TODO(brush-opacity)).

- Shared paint resolver: a stroke's color alpha is multiplied by its
  brush opacity; ballpoint/pencil opacity is tied to pressure
  (per-stroke average this increment) so a ballpoint reads lighter
  than a solid fountain pen.
- Highlighter paints with BlendMode.multiply and draws once, so
  cross-stroke overlap darkens like a real marker while self-overlap
  doesn't.
- Applied across BOTH render paths (PenCanvas static/live painters and
  the PDF _PageOverlayPainter).

Pencil paper-grain texture still deferred (TODO brush-texture); brush
kind is not yet serialized (TODO brush-persist — next). analyze clean,
tests green.
2026-06-24 23:27:11 +08:00
0feca74278 feat(pen): extensible brush model (4 brushes)
All checks were successful
CI / Windows build (push) Successful in 14m54s
Replace the 2-tool ink system with a data-driven, Krita-style
BrushProfile (lib/editor/engine/brush.dart). Adding a brush is a
const map entry, not render-path branching.

Four presets from the rnote/krita spec:
- fountain pen: quadratic (p^2) pressure, wide dynamic width
- ballpoint:    near-constant width (thinning 0.15)
- highlighter:  flat width, square caps
- pencil:       sqrt(p) pressure, moderate width

Pressure is pre-warped per brush via PressureCurve(gamma) before
perfect_freehand; geometry fields (thinning/streamline/smoothing/
caps) flow through the shared stroke recipe so the PDF overlay and
the note/slide PenCanvas both honor the brush. Brush kind is now
persisted on the stroke model. Picker added to all three toolbars.

Opacity/multiply and pencil grain are carried as data but not yet
composited (TODO brush-opacity / brush-texture); this increment is
width + pressure-curve differentiation. analyze clean, 283 tests.
2026-06-24 11:13:43 +08:00