mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-09-04 08:56:15 +02:00
Add SkiaPlugin support and benchmark plugins for SkiaSharp and GDI+
This commit is contained in:
@@ -0,0 +1,128 @@
|
|||||||
|
using DesktopMagic.Api;
|
||||||
|
using DesktopMagic.Api.Settings;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace DesktopMagic.BuiltInPlugins;
|
||||||
|
|
||||||
|
internal class BenchmarkPlugin : Plugin
|
||||||
|
{
|
||||||
|
private const int BitmapWidth = 400;
|
||||||
|
private const int BitmapHeight = 300;
|
||||||
|
|
||||||
|
private readonly Random rng = new(42);
|
||||||
|
private readonly object rngLock = new();
|
||||||
|
|
||||||
|
private readonly System.Diagnostics.Stopwatch frameTimer = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
private double fps;
|
||||||
|
private long lastFrameMs;
|
||||||
|
|
||||||
|
[Setting("shape-count", "Shapes")]
|
||||||
|
private readonly IntegerUpDown shapeCount = new(10, 10000, 1000);
|
||||||
|
|
||||||
|
[Setting("shape-type", "Shape Type")]
|
||||||
|
private readonly ComboBox shapeType = new("Rectangles", "Ellipses", "Lines", "Text", "Mixed");
|
||||||
|
|
||||||
|
[Setting("fps-counter", "Fps")]
|
||||||
|
private readonly Label fpsCounter = new("");
|
||||||
|
|
||||||
|
public override int UpdateInterval => 16;
|
||||||
|
|
||||||
|
public override Bitmap? Main()
|
||||||
|
{
|
||||||
|
long now = frameTimer.ElapsedMilliseconds;
|
||||||
|
if (lastFrameMs > 0)
|
||||||
|
{
|
||||||
|
double elapsed = now - lastFrameMs;
|
||||||
|
fps = (fps * 0.9) + (1000.0 / Math.Max(elapsed, 1) * 0.1);
|
||||||
|
}
|
||||||
|
lastFrameMs = now;
|
||||||
|
|
||||||
|
int w = BitmapWidth;
|
||||||
|
int h = BitmapHeight;
|
||||||
|
|
||||||
|
Bitmap bmp = new Bitmap(w, h);
|
||||||
|
using Graphics g = Graphics.FromImage(bmp);
|
||||||
|
g.Clear(Color.Transparent);
|
||||||
|
g.SmoothingMode = SmoothingMode.HighSpeed;
|
||||||
|
g.CompositingQuality = CompositingQuality.HighSpeed;
|
||||||
|
g.InterpolationMode = InterpolationMode.Low;
|
||||||
|
|
||||||
|
Color color = Application.Theme.PrimaryColor;
|
||||||
|
int count = shapeCount.Value;
|
||||||
|
string type = shapeType.Value;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int x, y, rw, rh;
|
||||||
|
lock (rngLock)
|
||||||
|
{
|
||||||
|
x = rng.Next(0, w);
|
||||||
|
y = rng.Next(0, h);
|
||||||
|
rw = rng.Next(5, 60);
|
||||||
|
rh = rng.Next(5, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
using Brush brush = new SolidBrush(Color.FromArgb(rng.Next(100, 255), color));
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "Rectangles":
|
||||||
|
g.FillRectangle(brush, x, y, rw, rh);
|
||||||
|
break;
|
||||||
|
case "Ellipses":
|
||||||
|
g.FillEllipse(brush, x, y, rw, rh);
|
||||||
|
break;
|
||||||
|
case "Lines":
|
||||||
|
{
|
||||||
|
int thickness;
|
||||||
|
lock (rngLock) { thickness = rng.Next(1, 5); }
|
||||||
|
g.DrawLine(new Pen(brush, thickness), x, y, x + rw, y + rh);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Text":
|
||||||
|
{
|
||||||
|
int fontSize;
|
||||||
|
lock (rngLock) { fontSize = rng.Next(8, 24); }
|
||||||
|
using Font font = new("Arial", fontSize);
|
||||||
|
g.DrawString("Mg", font, brush, x, y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
int shape, thickness, fontSize;
|
||||||
|
lock (rngLock)
|
||||||
|
{
|
||||||
|
shape = rng.Next(0, 4);
|
||||||
|
thickness = rng.Next(1, 5);
|
||||||
|
fontSize = rng.Next(8, 24);
|
||||||
|
}
|
||||||
|
if (shape == 0)
|
||||||
|
{
|
||||||
|
g.FillRectangle(brush, x, y, rw, rh);
|
||||||
|
}
|
||||||
|
else if (shape == 1)
|
||||||
|
{
|
||||||
|
g.FillEllipse(brush, x, y, rw, rh);
|
||||||
|
}
|
||||||
|
else if (shape == 2)
|
||||||
|
{
|
||||||
|
g.DrawLine(new Pen(brush, thickness), x, y, x + rw, y + rh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using Font font = new("Arial", fontSize);
|
||||||
|
g.DrawString("Mg", font, brush, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fpsCounter.Value = fps.ToString();
|
||||||
|
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
using DesktopMagic.Api;
|
||||||
|
using DesktopMagic.Api.Settings;
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DesktopMagic.BuiltInPlugins;
|
||||||
|
|
||||||
|
internal class SkiaBenchmarkPlugin : SkiaPlugin
|
||||||
|
{
|
||||||
|
private readonly Random rng = new(42);
|
||||||
|
private readonly object rngLock = new();
|
||||||
|
|
||||||
|
private readonly System.Diagnostics.Stopwatch frameTimer = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
private double fps;
|
||||||
|
private long lastFrameMs;
|
||||||
|
|
||||||
|
[Setting("skia-shape-count", "Shapes")]
|
||||||
|
private readonly IntegerUpDown shapeCount = new(10, 10000, 1000);
|
||||||
|
|
||||||
|
[Setting("skia-shape-type", "Shape Type")]
|
||||||
|
private readonly ComboBox shapeType = new("Rectangles", "Ellipses", "Lines", "Text", "Mixed");
|
||||||
|
|
||||||
|
public override int UpdateInterval => 16;
|
||||||
|
|
||||||
|
public override void Main(SKCanvas canvas)
|
||||||
|
{
|
||||||
|
long now = frameTimer.ElapsedMilliseconds;
|
||||||
|
if (lastFrameMs > 0)
|
||||||
|
{
|
||||||
|
double elapsed = now - lastFrameMs;
|
||||||
|
fps = fps * 0.9 + (1000.0 / Math.Max(elapsed, 1)) * 0.1;
|
||||||
|
}
|
||||||
|
lastFrameMs = now;
|
||||||
|
|
||||||
|
int w = (int)canvas.DeviceClipBounds.Width;
|
||||||
|
int h = (int)canvas.DeviceClipBounds.Height;
|
||||||
|
|
||||||
|
canvas.Clear(SKColors.Transparent);
|
||||||
|
|
||||||
|
SKColor color = new(
|
||||||
|
Application.Theme.PrimaryColor.R,
|
||||||
|
Application.Theme.PrimaryColor.G,
|
||||||
|
Application.Theme.PrimaryColor.B,
|
||||||
|
Application.Theme.PrimaryColor.A);
|
||||||
|
|
||||||
|
int count = shapeCount.Value;
|
||||||
|
string type = shapeType.Value;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int x, y, rw, rh;
|
||||||
|
lock (rngLock)
|
||||||
|
{
|
||||||
|
x = rng.Next(0, w);
|
||||||
|
y = rng.Next(0, h);
|
||||||
|
rw = rng.Next(5, 60);
|
||||||
|
rh = rng.Next(5, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte alpha = (byte)rng.Next(100, 255);
|
||||||
|
using var paint = new SKPaint
|
||||||
|
{
|
||||||
|
Color = color.WithAlpha(alpha),
|
||||||
|
IsAntialias = false,
|
||||||
|
Style = SKPaintStyle.Fill
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "Rectangles":
|
||||||
|
canvas.DrawRect(x, y, rw, rh, paint);
|
||||||
|
break;
|
||||||
|
case "Ellipses":
|
||||||
|
canvas.DrawOval(x + rw / 2f, y + rh / 2f, rw / 2f, rh / 2f, paint);
|
||||||
|
break;
|
||||||
|
case "Lines":
|
||||||
|
paint.Style = SKPaintStyle.Stroke;
|
||||||
|
paint.StrokeWidth = 2;
|
||||||
|
canvas.DrawLine(x, y, x + rw, y + rh, paint);
|
||||||
|
break;
|
||||||
|
case "Text":
|
||||||
|
using (var textFont = new SKFont(SKTypeface.Default, 16))
|
||||||
|
{
|
||||||
|
canvas.DrawText("Mg", x, y + 16, SKTextAlign.Left, textFont, paint);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
int shape;
|
||||||
|
lock (rngLock) { shape = rng.Next(0, 4); }
|
||||||
|
if (shape == 0)
|
||||||
|
{
|
||||||
|
canvas.DrawRect(x, y, rw, rh, paint);
|
||||||
|
}
|
||||||
|
else if (shape == 1)
|
||||||
|
{
|
||||||
|
canvas.DrawOval(x + rw / 2f, y + rh / 2f, rw / 2f, rh / 2f, paint);
|
||||||
|
}
|
||||||
|
else if (shape == 2)
|
||||||
|
{
|
||||||
|
paint.Style = SKPaintStyle.Stroke;
|
||||||
|
paint.StrokeWidth = 2;
|
||||||
|
canvas.DrawLine(x, y, x + rw, y + rh, paint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using var textFont2 = new SKFont(SKTypeface.Default, 16);
|
||||||
|
canvas.DrawText("Mg", x, y + 16, SKTextAlign.Left, textFont2, paint);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var fpsFont = new SKFont(SKTypeface.Default, 14);
|
||||||
|
using var fpsPaint = new SKPaint
|
||||||
|
{
|
||||||
|
Color = color,
|
||||||
|
IsAntialias = false
|
||||||
|
};
|
||||||
|
canvas.DrawText($"FPS: {fps:F1} | Shapes: {count} | Type: {type}", 8, 18, SKTextAlign.Left, fpsFont, fpsPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3650.58" />
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3650.58" />
|
||||||
<PackageReference Include="Modio" Version="1.0.0" />
|
<PackageReference Include="Modio" Version="1.0.0" />
|
||||||
<PackageReference Include="NAudio" Version="2.2.1" />
|
<PackageReference Include="NAudio" Version="2.2.1" />
|
||||||
|
<PackageReference Include="SkiaSharp" Version="4.148.0" />
|
||||||
<PackageReference Include="System.Management" Version="8.0.0" />
|
<PackageReference Include="System.Management" Version="8.0.0" />
|
||||||
<PackageReference Include="WPF-UI" Version="4.2.0" />
|
<PackageReference Include="WPF-UI" Version="4.2.0" />
|
||||||
<PackageReference Include="WPF-UI.Markdown" Version="4.0.2" />
|
<PackageReference Include="WPF-UI.Markdown" Version="4.0.2" />
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ public sealed class Manager
|
|||||||
{new((string)App.LanguageDictionary["weather"], 5) { Author = "Stone_Red" }, typeof(WeatherPlugin)},
|
{new((string)App.LanguageDictionary["weather"], 5) { Author = "Stone_Red" }, typeof(WeatherPlugin)},
|
||||||
{new((string)App.LanguageDictionary["nextMeetingCountdown"], 6) { Author = "Stone_Red" }, typeof(NextMeetingCountdownPlugin)},
|
{new((string)App.LanguageDictionary["nextMeetingCountdown"], 6) { Author = "Stone_Red" }, typeof(NextMeetingCountdownPlugin)},
|
||||||
{new((string)App.LanguageDictionary["agenda"], 7) { Author = "Stone_Red" }, typeof(AgendaPlugin)},
|
{new((string)App.LanguageDictionary["agenda"], 7) { Author = "Stone_Red" }, typeof(AgendaPlugin)},
|
||||||
|
{new((string)App.LanguageDictionary["benchmark"], 8) { Author = "Stone_Red" }, typeof(BenchmarkPlugin)},
|
||||||
|
{new((string)App.LanguageDictionary["skiaBenchmark"], 9) { Author = "Stone_Red" }, typeof(SkiaBenchmarkPlugin)},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Window management
|
// Window management
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ using DesktopMagic.Helpers;
|
|||||||
using DesktopMagic.Plugins;
|
using DesktopMagic.Plugins;
|
||||||
using DesktopMagic.Settings;
|
using DesktopMagic.Settings;
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@@ -834,16 +836,36 @@ public partial class PluginWindow : Window, IPluginWindow
|
|||||||
{
|
{
|
||||||
if (IsRunning && pluginClassInstance is not null)
|
if (IsRunning && pluginClassInstance is not null)
|
||||||
{
|
{
|
||||||
Bitmap? result;
|
if (pluginClassInstance is SkiaPlugin or SkiaAsyncPlugin)
|
||||||
|
|
||||||
if (pluginClassInstance is AsyncPlugin asyncPlugin)
|
|
||||||
{
|
{
|
||||||
CancellationToken token = pluginCancellationTokenSource?.Token ?? CancellationToken.None;
|
await RenderSkiaFrame();
|
||||||
result = await asyncPlugin.MainAsync(token);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = pluginClassInstance.Main();
|
Bitmap? result;
|
||||||
|
|
||||||
|
if (pluginClassInstance is AsyncPlugin asyncPlugin)
|
||||||
|
{
|
||||||
|
CancellationToken token = pluginCancellationTokenSource?.Token ?? CancellationToken.None;
|
||||||
|
result = await asyncPlugin.MainAsync(token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = pluginClassInstance.Main();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result is not null)
|
||||||
|
{
|
||||||
|
BitmapScalingMode renderOptions = pluginClassInstance.RenderQuality switch
|
||||||
|
{
|
||||||
|
RenderQuality.High => BitmapScalingMode.HighQuality,
|
||||||
|
RenderQuality.Low => BitmapScalingMode.LowQuality,
|
||||||
|
RenderQuality.Performance => BitmapScalingMode.NearestNeighbor,
|
||||||
|
_ => BitmapScalingMode.Unspecified
|
||||||
|
};
|
||||||
|
|
||||||
|
UpdateImageFromBitmap(result, renderOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginClassInstance.UpdateInterval > 0)
|
if (pluginClassInstance.UpdateInterval > 0)
|
||||||
@@ -854,19 +876,6 @@ public partial class PluginWindow : Window, IPluginWindow
|
|||||||
{
|
{
|
||||||
updateTimer!.Stop();
|
updateTimer!.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result is not null)
|
|
||||||
{
|
|
||||||
BitmapScalingMode renderOptions = pluginClassInstance.RenderQuality switch
|
|
||||||
{
|
|
||||||
RenderQuality.High => BitmapScalingMode.HighQuality,
|
|
||||||
RenderQuality.Low => BitmapScalingMode.LowQuality,
|
|
||||||
RenderQuality.Performance => BitmapScalingMode.NearestNeighbor,
|
|
||||||
_ => BitmapScalingMode.Unspecified
|
|
||||||
};
|
|
||||||
|
|
||||||
UpdateImageFromBitmap(result, renderOptions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -893,6 +902,66 @@ public partial class PluginWindow : Window, IPluginWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task RenderSkiaFrame()
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
await Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
width = Math.Max(1, (int)ActualWidth);
|
||||||
|
height = Math.Max(1, (int)ActualHeight);
|
||||||
|
});
|
||||||
|
|
||||||
|
using SKSurface surface = SKSurface.Create(new SKImageInfo(width, height, SKColorType.Bgra8888, SKAlphaType.Premul));
|
||||||
|
surface.Canvas.Clear(SKColors.Transparent);
|
||||||
|
|
||||||
|
if (pluginClassInstance is SkiaAsyncPlugin skiaAsyncPlugin)
|
||||||
|
{
|
||||||
|
CancellationToken token = pluginCancellationTokenSource?.Token ?? CancellationToken.None;
|
||||||
|
await skiaAsyncPlugin.MainAsync(surface.Canvas, token);
|
||||||
|
}
|
||||||
|
else if (pluginClassInstance is SkiaPlugin skiaPlugin)
|
||||||
|
{
|
||||||
|
skiaPlugin.Main(surface.Canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
SKPixmap? pixmap = surface.PeekPixels();
|
||||||
|
|
||||||
|
if (pixmap is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
if (writeableBitmap is null || writeableBitmap.PixelWidth != width || writeableBitmap.PixelHeight != height)
|
||||||
|
{
|
||||||
|
writeableBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
|
||||||
|
image.Source = writeableBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeableBitmap.Lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(
|
||||||
|
pixmap.GetPixels().ToPointer(),
|
||||||
|
writeableBitmap.BackBuffer.ToPointer(),
|
||||||
|
writeableBitmap.BackBufferStride * height,
|
||||||
|
pixmap.RowBytes * pixmap.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
writeableBitmap.Unlock();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void Border_SizeChanged(object sender, SizeChangedEventArgs e)
|
private void Border_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
{
|
{
|
||||||
rectangleGeometry.Rect = new Rect(-settings.Theme.Margin, -settings.Theme.Margin, e.NewSize.Width, e.NewSize.Height);
|
rectangleGeometry.Rect = new Rect(-settings.Theme.Margin, -settings.Theme.Margin, e.NewSize.Width, e.NewSize.Height);
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
<system:String x:Key="weather">Wetter</system:String>
|
<system:String x:Key="weather">Wetter</system:String>
|
||||||
<system:String x:Key="nextMeetingCountdown">Nächstes Meeting Countdown</system:String>
|
<system:String x:Key="nextMeetingCountdown">Nächstes Meeting Countdown</system:String>
|
||||||
<system:String x:Key="agenda">Agenda</system:String>
|
<system:String x:Key="agenda">Agenda</system:String>
|
||||||
|
<system:String x:Key="benchmark">Performance Benchmark</system:String>
|
||||||
|
<system:String x:Key="skiaBenchmark">SkiaSharp Benchmark</system:String>
|
||||||
<system:String x:Key="amplifier">Signalverstärkung:</system:String>
|
<system:String x:Key="amplifier">Signalverstärkung:</system:String>
|
||||||
<system:String x:Key="newLayout">Neues Layout</system:String>
|
<system:String x:Key="newLayout">Neues Layout</system:String>
|
||||||
<system:String x:Key="deleteLayout">Layout Löschen</system:String>
|
<system:String x:Key="deleteLayout">Layout Löschen</system:String>
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
<system:String x:Key="weather">Weather</system:String>
|
<system:String x:Key="weather">Weather</system:String>
|
||||||
<system:String x:Key="nextMeetingCountdown">Next Meeting Countdown</system:String>
|
<system:String x:Key="nextMeetingCountdown">Next Meeting Countdown</system:String>
|
||||||
<system:String x:Key="agenda">Agenda</system:String>
|
<system:String x:Key="agenda">Agenda</system:String>
|
||||||
|
<system:String x:Key="benchmark">Performance Benchmark</system:String>
|
||||||
|
<system:String x:Key="skiaBenchmark">SkiaSharp Benchmark</system:String>
|
||||||
<system:String x:Key="amplifier">Signal Amplification:</system:String>
|
<system:String x:Key="amplifier">Signal Amplification:</system:String>
|
||||||
<system:String x:Key="newLayout">New Layout</system:String>
|
<system:String x:Key="newLayout">New Layout</system:String>
|
||||||
<system:String x:Key="deleteLayout">Delete Layout</system:String>
|
<system:String x:Key="deleteLayout">Delete Layout</system:String>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="SkiaSharp" Version="4.148.0" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DesktopMagic.Api;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an abstract base class for creating asynchronous plugins using SkiaSharp rendering.
|
||||||
|
/// Plugins override <see cref="MainAsync(SKCanvas, CancellationToken)"/> instead of <see cref="Plugin.Main()"/>.
|
||||||
|
/// All existing <see cref="Plugin"/>, <see cref="AsyncPlugin"/>, and <see cref="SkiaPlugin"/> code is unaffected.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class SkiaAsyncPlugin : AsyncPlugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This method is sealed and returns null for async Skia plugins.
|
||||||
|
/// Override <see cref="MainAsync(SKCanvas, CancellationToken)"/> instead.
|
||||||
|
/// </summary>
|
||||||
|
public sealed override Task<Bitmap?> MainAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.FromResult<Bitmap?>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every <see cref="Plugin.UpdateInterval"/> milliseconds to render the plugin asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="canvas">The SkiaSharp canvas to draw on.</param>
|
||||||
|
/// <param name="cancellationToken">Token signaled when the host requests cancellation.</param>
|
||||||
|
public abstract Task MainAsync(SKCanvas canvas, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace DesktopMagic.Api;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an abstract base class for creating plugins using SkiaSharp rendering.
|
||||||
|
/// Plugins override <see cref="Main(SKCanvas)"/> instead of <see cref="Plugin.Main()"/>.
|
||||||
|
/// All existing <see cref="Plugin"/> and <see cref="AsyncPlugin"/> code is unaffected.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class SkiaPlugin : Plugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This method is sealed and returns null for Skia plugins.
|
||||||
|
/// Override <see cref="Main(SKCanvas)"/> instead.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Always null.</returns>
|
||||||
|
public sealed override Bitmap? Main()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every <see cref="Plugin.UpdateInterval"/> milliseconds to render the plugin.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="canvas">The SkiaSharp canvas to draw on.</param>
|
||||||
|
public abstract void Main(SKCanvas canvas);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user