import 'dart:async'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import '../models/ink_point.dart'; import '../models/pen_tool.dart'; import '../models/pointer_device_kind.dart'; class PenInputService { final StreamController _pointController = StreamController.broadcast(); Stream get pointStream => _pointController.stream; PenTool currentTool = PenTool.pen; Color currentColor = Colors.black; double currentStrokeWidth = 2.0; void addPoint(InkPoint point) { _pointController.add(point); } InputDeviceKind mapFlutterKind(PointerDeviceKind kind) { switch (kind) { case PointerDeviceKind.touch: return InputDeviceKind.touch; case PointerDeviceKind.mouse: return InputDeviceKind.mouse; case PointerDeviceKind.stylus: return InputDeviceKind.stylus; case PointerDeviceKind.invertedStylus: return InputDeviceKind.invertedStylus; case PointerDeviceKind.trackpad: return InputDeviceKind.trackpad; case PointerDeviceKind.unknown: return InputDeviceKind.unknown; } } InkPoint fromPointerEvent(PointerEvent event) { // Devices without real pressure support (mouse, basic touch) report a // degenerate range where pressureMin == pressureMax, which can yield a // pressure of 0.0 and produce zero-width strokes. In that case fall back // to a neutral mid-pressure value so strokes remain visible. final pressure = event.pressureMin == event.pressureMax ? 0.5 : event.pressure; return InkPoint( x: event.localPosition.dx, y: event.localPosition.dy, pressure: pressure, tilt: event is PointerMoveEvent ? event.tilt : 0.0, timestamp: event.timeStamp.inMicroseconds, pointerDeviceKind: mapFlutterKind(event.kind), ); } void dispose() { _pointController.close(); } }