42 lines
1.9 KiB
Dart
42 lines
1.9 KiB
Dart
|
|
// lib/editor/canvas/pinch_scale_solver.dart
|
||
|
|
//
|
||
|
|
// Pure math for the pen canvas's absolute pinch-zoom. Extracted so the
|
||
|
|
// re-baseline behavior (the subtle part) can be unit-tested without simulating
|
||
|
|
// a flaky multi-pointer gesture.
|
||
|
|
//
|
||
|
|
// The pinch is driven ABSOLUTELY: the scale shown is always
|
||
|
|
// scaleStart * (rawScale / rawScaleAtBaseline)
|
||
|
|
// where `scaleStart` is the matrix scale captured at the current baseline and
|
||
|
|
// `rawScaleAtBaseline` is the recognizer's cumulative `details.scale` at that
|
||
|
|
// same baseline. Dividing by `rawScaleAtBaseline` re-normalizes the cumulative
|
||
|
|
// scale so it reads 1.0 at the baseline instant.
|
||
|
|
//
|
||
|
|
// Why this matters: a baseline is captured at gesture start AND on every
|
||
|
|
// pointer-count change (a finger blips 2→1→2, routine on Windows touch). At
|
||
|
|
// gesture start `details.scale` is 1.0, so a naive `scaleStart * rawScale` is
|
||
|
|
// correct. But at a MID-GESTURE re-baseline `details.scale` is whatever the
|
||
|
|
// pinch has accumulated (e.g. 0.40) — multiplying the fresh `scaleStart` by
|
||
|
|
// that stale 0.40 popped the zoom to a wrong scale and snapped back (the
|
||
|
|
// reported flicker). Normalizing against `rawScaleAtBaseline` removes the pop.
|
||
|
|
|
||
|
|
import 'package:flutter/foundation.dart' show clampDouble;
|
||
|
|
|
||
|
|
/// Returns the absolute target scale for a pinch frame.
|
||
|
|
///
|
||
|
|
/// [scaleStart] — matrix scale captured at the current baseline.
|
||
|
|
/// [rawScaleAtBaseline] — recognizer cumulative `details.scale` at that
|
||
|
|
/// baseline (1.0 at gesture start; the live value at a re-baseline).
|
||
|
|
/// [rawScale] — the recognizer's current cumulative `details.scale`.
|
||
|
|
/// Result is clamped to [minScale, maxScale].
|
||
|
|
double absolutePinchScale({
|
||
|
|
required double scaleStart,
|
||
|
|
required double rawScaleAtBaseline,
|
||
|
|
required double rawScale,
|
||
|
|
required double minScale,
|
||
|
|
required double maxScale,
|
||
|
|
}) {
|
||
|
|
final double cumulative =
|
||
|
|
rawScaleAtBaseline > 0 ? rawScale / rawScaleAtBaseline : 1.0;
|
||
|
|
return clampDouble(scaleStart * cumulative, minScale, maxScale);
|
||
|
|
}
|