Files
BadNote/test/pressure_curve_test.dart
Akiba So f31dd0fb52
Some checks failed
CI / Windows build (push) Has been cancelled
fix: PDF finger ink, chrome UX, OneNote pens, and pen physics
Wire finger drawing on PDF without breaking pinch; auto-hide page scrubber and fix bounce; share sticky tools with resize and per-page remember; side-button select; separate pen slots with colors; rnote pressure shapes plus tip-velocity width and lower stroke latency.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 16:01:01 +08:00

107 lines
4.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Tests for the configurable pen-pressure response (F5).
import 'dart:math' as math;
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));
});
group('PressureCurve.shaped', () {
const floor = 0.1;
test('every shape maps 0→floor and 1→1', () {
for (final shape in PressureCurveShape.values) {
final c = PressureCurve.shaped(shape, floor: floor);
expect(c.apply(0.0), closeTo(floor, 1e-9), reason: '$shape at 0');
expect(c.apply(1.0), closeTo(1.0, 1e-9), reason: '$shape at 1');
}
});
test('midpoints differ across shapes', () {
final mids = {
for (final shape in PressureCurveShape.values)
shape: PressureCurve.shaped(shape).apply(0.5),
};
expect(mids[PressureCurveShape.linear], closeTo(0.5, 1e-9));
expect(mids[PressureCurveShape.soft], closeTo(math.pow(0.5, 0.6), 1e-9));
expect(mids[PressureCurveShape.quadratic], closeTo(0.25, 1e-9));
expect(mids[PressureCurveShape.cubic], closeTo(0.125, 1e-9));
expect(mids[PressureCurveShape.sqrt], closeTo(math.sqrt(0.5), 1e-9));
final logMid = math.log(1 + kLogarithmicPressureK * 0.5) /
math.log(1 + kLogarithmicPressureK);
expect(mids[PressureCurveShape.logarithmic], closeTo(logMid, 1e-9));
// Soft (γ<1) > linear > quadratic > cubic at p=0.5; log is above linear.
expect(mids[PressureCurveShape.soft]! > mids[PressureCurveShape.linear]!,
isTrue);
expect(
mids[PressureCurveShape.linear]! >
mids[PressureCurveShape.quadratic]!,
isTrue);
expect(
mids[PressureCurveShape.quadratic]! >
mids[PressureCurveShape.cubic]!,
isTrue);
expect(
mids[PressureCurveShape.logarithmic]! >
mids[PressureCurveShape.linear]!,
isTrue);
// Distinct midpoints (no two shapes collide at p=0.5).
expect(mids.values.toSet().length, PressureCurveShape.values.length);
});
test('shaped presets set expected gamma (except log)', () {
expect(PressureCurve.shaped(PressureCurveShape.linear).gamma, 1.0);
expect(PressureCurve.shaped(PressureCurveShape.soft).gamma, 0.6);
expect(PressureCurve.shaped(PressureCurveShape.quadratic).gamma, 2.0);
expect(PressureCurve.shaped(PressureCurveShape.cubic).gamma, 3.0);
expect(PressureCurve.shaped(PressureCurveShape.sqrt).gamma, 0.5);
expect(PressureCurve.shaped(PressureCurveShape.logarithmic).shape,
PressureCurveShape.logarithmic);
});
});
}