diff --git a/Ink Canvas/Helpers/MultiTouchInput.cs b/Ink Canvas/Helpers/MultiTouchInput.cs index afaff15d..aa0a7274 100644 --- a/Ink Canvas/Helpers/MultiTouchInput.cs +++ b/Ink Canvas/Helpers/MultiTouchInput.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Windows; using System.Windows.Ink; using System.Windows.Input; @@ -8,18 +9,19 @@ namespace Ink_Canvas.Helpers { public class VisualCanvas : FrameworkElement { + private readonly List _visuals = new List(); + protected override Visual GetVisualChild(int index) { - return Visual; + if (index < 0 || index >= _visuals.Count) + throw new ArgumentOutOfRangeException(nameof(index)); + return _visuals[index]; } - protected override int VisualChildrenCount => 1; + protected override int VisualChildrenCount => _visuals.Count; - public VisualCanvas(DrawingVisual visual) + public VisualCanvas() { - Visual = visual; - AddVisualChild(visual); - CacheMode = new BitmapCache(); RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality); @@ -27,17 +29,32 @@ namespace Ink_Canvas.Helpers RenderOptions.SetCachingHint(this, CachingHint.Cache); } - public DrawingVisual Visual { get; } + public void AddVisual(DrawingVisual visual) + { + if (visual == null) return; + _visuals.Add(visual); + AddVisualChild(visual); + } + public void Clear() + { + foreach (var visual in _visuals) + { + RemoveVisualChild(visual); + } + _visuals.Clear(); + } + + public IReadOnlyList Visuals => _visuals; } /// /// 用于显示笔迹的类 /// - public class StrokeVisual : DrawingVisual + public class StrokeVisual { - private bool _needsRedraw = true; - private int _lastPointCount = 0; - private const int REDRAW_THRESHOLD = 3; + private int _lastDrawnPointCount = 0; + private const int INCREMENTAL_DRAW_THRESHOLD = 2; + private VisualCanvas _visualCanvas; /// /// 创建显示笔迹的类 @@ -59,10 +76,6 @@ namespace Ink_Canvas.Helpers public StrokeVisual(DrawingAttributes drawingAttributes) { _drawingAttributes = drawingAttributes; - - RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality); - RenderOptions.SetEdgeMode(this, EdgeMode.Aliased); - RenderOptions.SetCachingHint(this, CachingHint.Cache); } /// @@ -70,6 +83,14 @@ namespace Ink_Canvas.Helpers /// public Stroke Stroke { set; get; } + /// + /// 设置关联的VisualCanvas + /// + public void SetVisualCanvas(VisualCanvas visualCanvas) + { + _visualCanvas = visualCanvas; + } + /// /// 在笔迹中添加点 /// @@ -80,16 +101,61 @@ namespace Ink_Canvas.Helpers { var collection = new StylusPointCollection { point }; Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes }; - _lastPointCount = 1; } else { Stroke.StylusPoints.Add(point); - _lastPointCount++; + } + } + + /// + /// 绘制点段到新的DrawingVisual + /// + private void DrawSegmentToNewVisual(int startIndex, int endIndex) + { + if (Stroke == null || Stroke.StylusPoints.Count == 0 || _visualCanvas == null) return; + if (startIndex >= endIndex || startIndex < 0 || endIndex > Stroke.StylusPoints.Count) return; + + var points = Stroke.StylusPoints; + var drawingAttributes = Stroke.DrawingAttributes; + + // 创建新的DrawingVisual用于绘制这个点段 + var segmentVisual = new DrawingVisual(); + + RenderOptions.SetBitmapScalingMode(segmentVisual, BitmapScalingMode.LowQuality); + RenderOptions.SetEdgeMode(segmentVisual, EdgeMode.Aliased); + RenderOptions.SetCachingHint(segmentVisual, CachingHint.Cache); + + using (var dc = segmentVisual.RenderOpen()) + { + var pen = new Pen(new SolidColorBrush(drawingAttributes.Color), drawingAttributes.Width); + pen.StartLineCap = PenLineCap.Round; + pen.EndLineCap = PenLineCap.Round; + pen.LineJoin = PenLineJoin.Round; + + // 绘制指定范围内的点段 + if (endIndex - startIndex >= 2) + { + // 多个点,绘制线段 + for (int i = startIndex; i < endIndex - 1 && i < points.Count - 1; i++) + { + var startPoint = new Point(points[i].X, points[i].Y); + var endPoint = new Point(points[i + 1].X, points[i + 1].Y); + dc.DrawLine(pen, startPoint, endPoint); + } + } + else if (endIndex - startIndex == 1 && startIndex < points.Count) + { + // 只有一个点,绘制圆点 + var brush = new SolidColorBrush(drawingAttributes.Color); + var point = points[startIndex]; + dc.DrawEllipse(brush, null, new Point(point.X, point.Y), + drawingAttributes.Width / 2, drawingAttributes.Height / 2); + } } - // 标记需要重绘 - _needsRedraw = true; + // 将新的DrawingVisual添加到VisualCanvas中 + _visualCanvas.AddVisual(segmentVisual); } /// @@ -97,22 +163,35 @@ namespace Ink_Canvas.Helpers /// public void Redraw() { - if (!_needsRedraw || Stroke == null) return; + if (Stroke == null || _visualCanvas == null) return; - if (_lastPointCount % REDRAW_THRESHOLD != 0 && _lastPointCount > REDRAW_THRESHOLD) - { - return; - } + var currentPointCount = Stroke.StylusPoints.Count; + if (currentPointCount == 0) return; - try + // 计算新增的点数 + int newPointCount = currentPointCount - _lastDrawnPointCount; + + // 如果新增点数达到阈值,才进行增量绘制 + if (newPointCount >= INCREMENTAL_DRAW_THRESHOLD || _lastDrawnPointCount == 0) { - using (var dc = RenderOpen()) + try { - Stroke.Draw(dc); + if (_lastDrawnPointCount == 0) + { + // 首次绘制:绘制所有点 + DrawSegmentToNewVisual(0, currentPointCount); + _lastDrawnPointCount = currentPointCount; + } + else + { + // 从上次绘制的最后一个点开始 + int startIndex = Math.Max(0, _lastDrawnPointCount - 1); + DrawSegmentToNewVisual(startIndex, currentPointCount); + _lastDrawnPointCount = currentPointCount; + } } - _needsRedraw = false; + catch { } } - catch { } } /// @@ -120,7 +199,11 @@ namespace Ink_Canvas.Helpers /// public void ForceRedraw() { - _needsRedraw = true; + if (_visualCanvas != null) + { + _visualCanvas.Clear(); + } + _lastDrawnPointCount = 0; Redraw(); } diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 1a526ef9..420fcf53 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -482,8 +482,8 @@ namespace Ink_Canvas var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone()); StrokeVisualList[id] = strokeVisual; - StrokeVisualList[id] = strokeVisual; - var visualCanvas = new VisualCanvas(strokeVisual); + var visualCanvas = new VisualCanvas(); + strokeVisual.SetVisualCanvas(visualCanvas); VisualCanvasList[id] = visualCanvas; inkCanvas.Children.Add(visualCanvas);