-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBufferedScreen.cs
More file actions
101 lines (80 loc) · 3.52 KB
/
BufferedScreen.cs
File metadata and controls
101 lines (80 loc) · 3.52 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
using SkiaSharp;
using TuringSmartScreenLib;
using TuringSmartScreenLib.Helpers.SkiaSharp;
namespace GameOfLife.SmartScreen {
public abstract class BufferedScreen {
public readonly IScreen Screen;
protected SKBitmap _tmpBuffer;
private SKBitmap _screenBuffer;
private SKColor _backgroundColor;
public BufferedScreen(IScreen screen) : this(screen, SKColors.Gray) { }
public BufferedScreen(IScreen screen, SKColor backgroundColor) {
Screen = screen;
_screenBuffer = new SKBitmap(Screen.Width, screen.Height);
_backgroundColor = backgroundColor;
_tmpBuffer = new SKBitmap(Screen.Width, Screen.Height);
clearBuffers(_backgroundColor);
}
public void clearBuffers(SKColor color) {
using (SKCanvas canvas = new SKCanvas(_screenBuffer)) {
canvas.Clear(_backgroundColor);
}
using (SKCanvas canvas = new SKCanvas(_tmpBuffer)) {
canvas.Clear(_backgroundColor);
}
}
public void SetBackground(SKColor color) {
using (SKCanvas canvas = new SKCanvas(_tmpBuffer)) {
canvas.Clear(color);
}
}
public void Flush(int radX = 32, int radY = 32) {
var diffs = updateScreenBufferAndGetDiffs();
var updates = getUpdatedBoxes(diffs, radX, radY);
foreach ((int x, int y, int w, int h) in updates) {
var buffer = Screen.CreateBuffer(w, h);
buffer.ReadFrom(_tmpBuffer, x, y, w, h);
Screen.DisplayBuffer(x, y, buffer);
}
}
private List<(int x, int y, int w, int h)> getUpdatedBoxes(List<(int x, int y)> diffs, int radX, int radY) {
var boxes = new List<(int x, int y, int w, int h)>();
while (diffs.Count > 0) {
var center = diffs[0];
diffs.RemoveAt(0);
int cx = center.x, cy = center.y;
int mx = cx, my = cy, Mx = cx, My = cy;
var remaining = diffs.ToArray();
for (var j = 1; j < remaining.Length; j++) {
var neighbor = remaining[j];
int nx = neighbor.x, ny = neighbor.y;
int dx = Math.Abs(cx - nx), dy = Math.Abs(cy - ny);
if (dx <= radX && dy <= radY) {
diffs.Remove(neighbor);
mx = Math.Min(nx, mx); my = Math.Min(ny, my);
Mx = Math.Max(nx, Mx); My = Math.Max(ny, My);
}
}
boxes.Add((mx, my, (Mx - mx) + 1, (My - my) + 1));
}
return boxes;
}
private unsafe List<(int x, int y)> updateScreenBufferAndGetDiffs() {
var tmpPixes = (int*)_tmpBuffer.GetPixels().ToPointer();
var screenPixels = (int*)_screenBuffer.GetPixels().ToPointer();
var diffs = new List<(int x, int y)>(Screen.Width * Screen.Height);
int W = Screen.Width, H = Screen.Height;
for (var y = 0; y < H; y++) {
for (var x = 0; x < W; x++) {
var offset = (y * W) + x;
var newColor = tmpPixes[offset];
if (newColor != screenPixels[offset]) {
screenPixels[offset] = newColor;
diffs.Add((x, y));
}
}
}
return diffs;
}
}
}