feat(f5): configurable pen pressure curve (floor + gamma) pure core
Some checks failed
CI / Windows build (push) Has been cancelled
Some checks failed
CI / Windows build (push) Has been cancelled
The user's repeated "可配置笔" ask, as a pure value type: raw normalized pressure is pre-shaped into [floor, 1] via a min-width floor (the plan's marker fixed-pressure floor) and a gamma response (γ<1 = more sensitive at light touch, γ>1 = firmer). Clamps out-of-range + NaN inputs; endpoints anchored at floor and 1. Widget-free/storage-free; PenConfig + the canvas wire it later (live-path, on-device validated). flutter analyze lib/editor clean; 145/145 tests (+6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
49
test/pressure_curve_test.dart
Normal file
49
test/pressure_curve_test.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
// Tests for the configurable pen-pressure response (F5).
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:badnote/editor/input/pressure_curve.dart';
|
||||
|
||||
void main() {
|
||||
test('linear is the identity over [0,1]', () {
|
||||
const c = PressureCurve.linear;
|
||||
expect(c.apply(0.0), closeTo(0.0, 1e-9));
|
||||
expect(c.apply(0.5), closeTo(0.5, 1e-9));
|
||||
expect(c.apply(1.0), closeTo(1.0, 1e-9));
|
||||
});
|
||||
|
||||
test('floor raises the minimum, endpoints stay anchored at floor and 1', () {
|
||||
const c = PressureCurve(floor: 0.4);
|
||||
expect(c.apply(0.0), closeTo(0.4, 1e-9)); // floor
|
||||
expect(c.apply(1.0), closeTo(1.0, 1e-9)); // full
|
||||
expect(c.apply(0.5), closeTo(0.4 + 0.6 * 0.5, 1e-9)); // 0.7
|
||||
});
|
||||
|
||||
test('gamma < 1 boosts light pressure (more sensitive)', () {
|
||||
const c = PressureCurve(gamma: 0.5);
|
||||
// pow(0.25, 0.5) = 0.5 → output 0.5 > input 0.25
|
||||
expect(c.apply(0.25), closeTo(0.5, 1e-9));
|
||||
expect(c.apply(0.25), greaterThan(0.25));
|
||||
});
|
||||
|
||||
test('gamma > 1 dampens light pressure (firmer)', () {
|
||||
const c = PressureCurve(gamma: 2.0);
|
||||
expect(c.apply(0.5), closeTo(0.25, 1e-9)); // 0.5^2
|
||||
expect(c.apply(0.5), lessThan(0.5));
|
||||
});
|
||||
|
||||
test('output is clamped: out-of-range and NaN inputs are safe', () {
|
||||
const c = PressureCurve(floor: 0.2);
|
||||
expect(c.apply(-1.0), closeTo(0.2, 1e-9)); // clamped to 0 → floor
|
||||
expect(c.apply(2.0), closeTo(1.0, 1e-9)); // clamped to 1 → full
|
||||
expect(c.apply(double.nan), closeTo(0.2, 1e-9)); // NaN → 0 → floor
|
||||
});
|
||||
|
||||
test('marker-style high floor compresses the range toward full width', () {
|
||||
const marker = PressureCurve(floor: 0.9);
|
||||
expect(marker.apply(0.0), closeTo(0.9, 1e-9));
|
||||
expect(marker.apply(1.0), closeTo(1.0, 1e-9));
|
||||
// Even a light touch stays near full width.
|
||||
expect(marker.apply(0.1), greaterThan(0.9));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user