feat(engine): P0 stroke engine + persistence
Per the full-refactor plan §9 (input-independent half of P0): - engine: canonical EditorStroke (lossless InkStroke round-trip) + stroke_geometry (single getStroke outline) + revision-gated StrokeStore - render: static/live ink painters + ink_picture_cache (revision-keyed) + annotation_layer (RepaintBoundary) - persistence: DB v6 (ink, notebook_pages) + editor_repository diff-write (UPSERT changed / DELETE removed in one txn; id-set after commit) + save_scheduler - pdf_service export now FILLS the getStroke outline (R7 hairline fix) Not yet wired into the live editor (input relocation pending pen-pressure diagnostic). 28 new tests pass.
This commit is contained in:
47
lib/editor/render/live_ink_painter.dart
Normal file
47
lib/editor/render/live_ink_painter.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
// lib/editor/render/live_ink_painter.dart
|
||||
//
|
||||
// CustomPainter for the in-progress stroke (live) layer.
|
||||
//
|
||||
// Paints only the single EditorStroke? currently being drawn, with
|
||||
// isComplete:false so perfect_freehand tapers the trailing end correctly.
|
||||
// Kept in a separate RepaintBoundary so committed strokes are never
|
||||
// re-rasterized on pointer-move events.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../engine/stroke_geometry.dart';
|
||||
import '../engine/stroke_model.dart';
|
||||
|
||||
/// Paints the single in-progress [EditorStroke] (or nothing when [live] is
|
||||
/// null / empty). Use alongside [StaticInkPainter] in stacked [CustomPaint]s.
|
||||
class LiveInkPainter extends CustomPainter {
|
||||
const LiveInkPainter({
|
||||
required this.live,
|
||||
required this.pageSize,
|
||||
});
|
||||
|
||||
/// The stroke currently being drawn, or null when idle.
|
||||
final EditorStroke? live;
|
||||
final Size pageSize;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final stroke = live;
|
||||
if (stroke == null || stroke.points.isEmpty) return;
|
||||
|
||||
final path = buildStrokeOutline(stroke, pageSize, isComplete: false);
|
||||
if (path.getBounds().isEmpty) return;
|
||||
|
||||
canvas.drawPath(
|
||||
path,
|
||||
Paint()
|
||||
..color = Color(stroke.color)
|
||||
..style = PaintingStyle.fill
|
||||
..isAntiAlias = true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(LiveInkPainter old) =>
|
||||
!identical(old.live, live) || old.pageSize != pageSize;
|
||||
}
|
||||
Reference in New Issue
Block a user