Repository navigation
Expand file tree
/
Copy pathStyledDynamicRenderer.cs
More file actions
161 lines (133 loc) · 4.46 KB
/
Copy pathStyledDynamicRenderer.cs
File metadata and controls
161 lines (133 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;
namespace FlowInk;
public sealed class StyledDynamicRenderer : DynamicRenderer
{
[ThreadStatic]
private static bool _hasPreviousPoint;
[ThreadStatic]
private static Point _previousPoint;
private volatile LineStyleKind _lineStyle = LineStyleKind.Solid;
private int _argb = unchecked((int)0xFFFF0000);
private double _width = 4.0;
private double _height = 4.0;
public LineStyleKind LineStyle
{
get => _lineStyle;
set => _lineStyle = value;
}
public void UpdateDrawingAttributes(DrawingAttributes drawingAttributes)
{
ArgumentNullException.ThrowIfNull(drawingAttributes);
// DynamicRenderer internally also needs its own attributes.
DrawingAttributes = drawingAttributes.Clone();
Color color = drawingAttributes.Color;
int argb = color.A << 24 | color.R << 16 | color.G << 8 | color.B;
Volatile.Write(ref _argb, argb);
Volatile.Write(ref _width, drawingAttributes.Width);
Volatile.Write(ref _height, drawingAttributes.Height);
}
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
_hasPreviousPoint = false;
base.OnStylusDown(rawStylusInput);
}
protected override void OnStylusUp(RawStylusInput rawStylusInput)
{
base.OnStylusUp(rawStylusInput);
_hasPreviousPoint = false;
}
protected override void OnDraw(
DrawingContext drawingContext,
StylusPointCollection stylusPoints,
Geometry geometry,
Brush fillBrush)
{
LineStyleKind lineStyle = LineStyle;
if (lineStyle == LineStyleKind.Solid)
{
drawingContext.DrawGeometry(fillBrush, null, geometry);
return;
}
if (stylusPoints.Count == 0)
{
return;
}
var points = new List<Point>(stylusPoints.Count + 1);
if (_hasPreviousPoint)
{
points.Add(_previousPoint);
}
foreach (StylusPoint point in stylusPoints)
{
points.Add(new Point(point.X, point.Y));
}
int argb = Volatile.Read(ref _argb);
Color color = Color.FromArgb(
(byte)((argb >> 24) & 0xFF),
(byte)((argb >> 16) & 0xFF),
(byte)((argb >> 8) & 0xFF),
(byte)(argb & 0xFF));
double width = Volatile.Read(ref _width);
double height = Volatile.Read(ref _height);
double thickness = Math.Max(0.1, (width + height) / 2.0);
var brush = new SolidColorBrush(color);
if (brush.CanFreeze)
{
brush.Freeze();
}
if (points.Count == 1)
{
Point point = points[0];
drawingContext.DrawEllipse(brush, null, point, thickness / 2.0, thickness / 2.0);
_previousPoint = point;
_hasPreviousPoint = true;
return;
}
DashStyle? dashStyle = LineStyleDrawing.CreateDashStyle(lineStyle);
if (dashStyle == null)
{
drawingContext.DrawGeometry(fillBrush, null, geometry);
return;
}
var pen = new Pen(brush, thickness)
{
StartLineCap = PenLineCap.Round,
EndLineCap = PenLineCap.Round,
DashCap = PenLineCap.Round,
LineJoin = PenLineJoin.Round,
DashStyle = dashStyle
};
if (pen.CanFreeze)
{
pen.Freeze();
}
drawingContext.DrawGeometry(null, pen, CreatePolylineGeometry(points));
StylusPoint lastPoint = stylusPoints[stylusPoints.Count - 1];
_previousPoint = new Point(lastPoint.X, lastPoint.Y);
_hasPreviousPoint = true;
}
private static Geometry CreatePolylineGeometry(IReadOnlyList<Point> points)
{
var geometry = new StreamGeometry();
using (StreamGeometryContext context = geometry.Open())
{
context.BeginFigure(points[0], isFilled: false, isClosed: false);
for (int index = 1; index < points.Count; index++)
{
context.LineTo(points[index], isStroked: true, isSmoothJoin: false);
}
}
if (geometry.CanFreeze)
{
geometry.Freeze();
}
return geometry;
}
}