Files
sheetless/lib/features/sheet_viewer/drawing/drawing_line.dart

100 lines
2.9 KiB
Dart

import 'dart:ui';
/// Represents a single stroke/line drawn on the canvas.
///
/// Points are stored in normalized coordinates (0.0 to 1.0) where:
/// - (0, 0) is the top-left corner of the drawing area
/// - (1, 1) is the bottom-right corner of the drawing area
///
/// This allows drawings to scale correctly when the canvas size changes.
class DrawingLine {
/// The minimal squared distance between to points which are normalized so that this point is allowed to be added to the line
static const minNormalizedPointDistanceSquared = 0.001 * 0.001;
/// Points in normalized coordinates (0.0 to 1.0)
final List<Offset> points;
/// Color of the line (stored as ARGB integer for JSON serialization)
final Color color;
/// Stroke width in normalized units (relative to canvas width)
/// A value of 0.01 means the stroke is 1% of the canvas width
final double strokeWidth;
const DrawingLine({
required this.points,
required this.color,
required this.strokeWidth,
});
/// Creates a DrawingLine from JSON data.
factory DrawingLine.fromJson(Map<String, dynamic> json) {
final pointsList = (json['points'] as List)
.map(
(p) => Offset((p['x'] as num).toDouble(), (p['y'] as num).toDouble()),
)
.toList();
return DrawingLine(
points: pointsList,
color: Color(json['color'] as int),
strokeWidth: (json['strokeWidth'] as num).toDouble(),
);
}
/// Converts this line to a JSON-serializable map.
Map<String, dynamic> toJson() {
return {
'points': points.map((p) => {'x': p.dx, 'y': p.dy}).toList(),
'color': color.toARGB32(),
'strokeWidth': strokeWidth,
};
}
/// Creates a copy of this line with an additional point.
DrawingLine addPoint(Offset normalizedPoint) {
return DrawingLine(
points: [...points, normalizedPoint],
color: color,
strokeWidth: strokeWidth,
);
}
bool isPointTooClose(Offset nextNormalizedPoint) {
if (points.isEmpty) {
return false;
}
return (points.last - nextNormalizedPoint).distanceSquared <
minNormalizedPointDistanceSquared;
}
/// Creates a copy with updated points.
DrawingLine copyWith({
List<Offset>? points,
Color? color,
double? strokeWidth,
}) {
return DrawingLine(
points: points ?? this.points,
color: color ?? this.color,
strokeWidth: strokeWidth ?? this.strokeWidth,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! DrawingLine) return false;
if (points.length != other.points.length) return false;
if (color != other.color) return false;
if (strokeWidth != other.strokeWidth) return false;
for (int i = 0; i < points.length; i++) {
if (points[i] != other.points[i]) return false;
}
return true;
}
@override
int get hashCode => Object.hash(Object.hashAll(points), color, strokeWidth);
}