Skip to content

Instantly share code, notes, and snippets.

@Redth
Last active March 6, 2021 23:11
Show Gist options
  • Save Redth/c00ff6780473bc4a7bddd2382e935b52 to your computer and use it in GitHub Desktop.
Save Redth/c00ff6780473bc4a7bddd2382e935b52 to your computer and use it in GitHub Desktop.
Meadow Graphics Xamarin.Forms Tester app
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:meadowgraphicstester="clr-namespace:MeadowGraphicsTester"
x:Class="MeadowGraphicsTester.MainPage"
Title="Meadow Graphics"
Padding="20">
<Grid RowDefinitions="Auto, Auto, Auto, *" RowSpacing="20">
<Label Text="240 x 240" HorizontalOptions="Center" FontSize="Title" Grid.Row="0" />
<Frame Grid.Row="1" BorderColor="Black" BackgroundColor="Black" HorizontalOptions="Center">
<meadowgraphicstester:SkiaSharpMeadowDisplayView
x:Name="canvas"
WidthRequest="240" HeightRequest="240" />
</Frame>
<Button Grid.Row="2" CornerRadius="8" BackgroundColor="{x:Static Color.Accent}" TextColor="White" Clicked="Button_Clicked" Text="Draw" />
</Grid>
</ContentPage>
using Xamarin.Forms;
namespace MeadowGraphicsTester
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
void Button_Clicked(System.Object sender, System.EventArgs e)
{
var graphics = canvas.Graphics;
graphics.Clear(true);
graphics.DrawRoundedRectangle(
10,
10,
canvas.DisplayWidth - 20,
canvas.DisplayHeight - 20, 20,
Meadow.Foundation.Color.LightBlue,
true);
graphics.CurrentFont = new Meadow.Foundation.Graphics.Font12x20();
graphics.DrawText(
canvas.DisplayWidth / 2,
canvas.DisplayHeight / 2 - canvas.Graphics.CurrentFont.Height,
"MEADOW",
Meadow.Foundation.Color.Black,
Meadow.Foundation.Graphics.GraphicsLibrary.ScaleFactor.X2,
Meadow.Foundation.Graphics.GraphicsLibrary.TextAlignment.Center);
graphics.Show();
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2012" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.80.3-preview.40" />
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
<PackageReference Include="Meadow.Foundation" Version="0.23.0" />
<PackageReference Include="Meadow.Foundation.Displays.GraphicsLibrary" Version="0.9.34" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using Meadow.Foundation.Displays;
using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
namespace MeadowGraphicsTester
{
public class SkiaSharpMeadowDisplay : DisplayBase
{
public SkiaSharpMeadowDisplay(int width, int height, Action<SKDrawUpdate> drawHandler)
{
this.drawHandler = drawHandler;
var density = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density;
_width = (int)(width * density);
_height = (int)(height * density);
}
int _width;
int _height;
Action<SKDrawUpdate> drawHandler;
List<SKDrawAction> drawActions = new List<SKDrawAction>();
void QueueDraw(int x, int y, SKColor color, bool invert = false)
=> drawActions.Add(new SKDrawAction { X = x, Y = y, Color = color, Invert = invert });
public override DisplayColorMode ColorMode
=> DisplayColorMode.Format24bppRgb888;
public override int Width => _width;
public override int Height => _height;
bool clearNextDraw = false;
Meadow.Foundation.Color penColor = Meadow.Foundation.Color.Black;
public override void Clear(bool updateDisplay = false)
{
if (updateDisplay)
drawHandler?.Invoke(new SKDrawUpdate { Clear = true });
clearNextDraw = true;
}
public override void DrawPixel(int x, int y, Meadow.Foundation.Color color)
{
var c = color.ToSKColor();
QueueDraw(x, y, c);
}
public override void DrawPixel(int x, int y, bool colored)
=> QueueDraw(x, y, colored ? penColor.ToSKColor() : SKColor.Empty);
public override void DrawPixel(int x, int y)
=> QueueDraw(x, y, penColor.ToSKColor());
public override void InvertPixel(int x, int y)
=> QueueDraw(x, y, SKColor.Empty, true);
public override void SetPenColor(Meadow.Foundation.Color pen)
=> penColor = pen;
public override void Show()
{
var clear = clearNextDraw;
clearNextDraw = false;
drawHandler?.Invoke(new SKDrawUpdate { Clear = clear, Actions = drawActions.ToArray() });
}
}
public static class ColorExtensions
{
public static SKColor ToSKColor(this Meadow.Foundation.Color color)
=> new SKColor(
(byte)(color.R * 255),
(byte)(color.G * 255),
(byte)(color.B * 255),
(byte)(color.A * 255));
public static SKColor Invert(this SKColor color)
=> new SKColor((byte)(255 - color.Red), (byte)(255 - color.Green), (byte)(255 - color.Blue), color.Alpha);
};
public struct SKDrawUpdate
{
public bool Clear;
public SKDrawAction[] Actions;
}
public struct SKDrawAction
{
public int X;
public int Y;
public SKColor Color;
public bool Invert;
}
}
using System;
using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
namespace MeadowGraphicsTester
{
public class SkiaSharpMeadowDisplayView : SKCanvasView
{
Meadow.Foundation.Graphics.GraphicsLibrary graphics;
public SkiaSharpMeadowDisplay Display { get; private set; }
public Meadow.Foundation.Graphics.GraphicsLibrary Graphics { get; private set; }
public int DisplayWidth { get; private set; }
public int DisplayHeight { get; private set; }
SKBitmap bitmap;
SKDrawUpdate nextUpdate = default;
bool initialized = false;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (initialized)
return;
DisplayWidth = (int)WidthRequest;
DisplayHeight = (int)HeightRequest;
bitmap = new SKBitmap(DisplayWidth, DisplayHeight);
Display = new SkiaSharpMeadowDisplay(DisplayWidth, DisplayHeight, drawUpdate =>
{
nextUpdate = drawUpdate;
InvalidateSurface();
});
Graphics = new Meadow.Foundation.Graphics.GraphicsLibrary(Display);
initialized = true;
}
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
base.OnPaintSurface(e);
if (!initialized)
return;
if (nextUpdate.Actions != null)
{
foreach (var a in nextUpdate.Actions)
{
var c = a.Color;
if (a.Invert)
c = bitmap.GetPixel(a.X, a.Y).Invert();
bitmap.SetPixel(a.X, a.Y, c);
}
}
nextUpdate = default;
var surface = e.Surface;
if (nextUpdate.Clear)
surface.Canvas.Clear();
var density = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density;
var scaledBitmap = new SKBitmap((int)(bitmap.Width * density), (int)(bitmap.Height * density));
bitmap.ScalePixels(scaledBitmap, SKFilterQuality.Medium);
surface.Canvas.DrawBitmap(scaledBitmap, 0, 0);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment