csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.9 KiB
135 lines
3.9 KiB
using System;
|
|
using Avalonia.Media;
|
|
using Avalonia.Platform;
|
|
using SkiaSharp;
|
|
using CoreGraphics;
|
|
using UIKit;
|
|
|
|
namespace Avalonia.Skia
|
|
{
|
|
internal partial class RenderTarget : IRenderTarget
|
|
{
|
|
public SKSurface Surface { get; protected set; }
|
|
|
|
public virtual DrawingContext CreateDrawingContext()
|
|
{
|
|
return
|
|
new DrawingContext(
|
|
new DrawingContextImpl(Surface.Canvas));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
}
|
|
|
|
internal class WindowRenderTarget : RenderTarget
|
|
{
|
|
|
|
SKBitmap _bitmap;
|
|
int Width { get; set; }
|
|
int Height { get; set; }
|
|
|
|
public WindowRenderTarget()
|
|
{
|
|
FixSize();
|
|
}
|
|
|
|
private CGRect GetApplicationFrame()
|
|
{
|
|
// if we are excluding Status Bar then we use ApplicationFrame
|
|
// otherwise we use full screen bounds. Note that this must also match
|
|
// the Skia/AvaloniaView!!!
|
|
//
|
|
bool excludeStatusArea = false; // TODO: make this configurable later
|
|
if (excludeStatusArea)
|
|
{
|
|
return UIScreen.MainScreen.ApplicationFrame;
|
|
}
|
|
else
|
|
{
|
|
return UIScreen.MainScreen.Bounds;
|
|
}
|
|
}
|
|
|
|
private void FixSize()
|
|
{
|
|
int width, height;
|
|
GetPlatformWindowSize(out width, out height);
|
|
if (Width == width && Height == height)
|
|
return;
|
|
|
|
Width = width;
|
|
Height = height;
|
|
|
|
if (Surface != null)
|
|
{
|
|
Surface.Dispose();
|
|
}
|
|
|
|
if (_bitmap != null)
|
|
{
|
|
_bitmap.Dispose();
|
|
}
|
|
|
|
_bitmap = new SKBitmap(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
|
|
|
|
IntPtr length;
|
|
var pixels = _bitmap.GetPixels(out length);
|
|
|
|
// Wrap the bitmap in a Surface and keep it cached
|
|
Surface = SKSurface.Create(_bitmap.Info, pixels, _bitmap.RowBytes);
|
|
}
|
|
|
|
private void GetPlatformWindowSize(out int w, out int h)
|
|
{
|
|
var bounds = GetApplicationFrame();
|
|
w = (int)bounds.Width;
|
|
h = (int)bounds.Height;
|
|
}
|
|
|
|
public override DrawingContext CreateDrawingContext()
|
|
{
|
|
FixSize();
|
|
|
|
var canvas = Surface.Canvas;
|
|
canvas.RestoreToCount(0);
|
|
canvas.Save();
|
|
|
|
var screenScale = UIScreen.MainScreen.Scale;
|
|
canvas.Scale((float)screenScale, (float)screenScale);
|
|
|
|
canvas.Clear(SKColors.Red);
|
|
canvas.ResetMatrix();
|
|
|
|
return
|
|
new DrawingContext(
|
|
new WindowDrawingContextImpl(this));
|
|
}
|
|
|
|
public void Present()
|
|
{
|
|
_bitmap.LockPixels();
|
|
IntPtr length;
|
|
var pixels = _bitmap.GetPixels(out length);
|
|
|
|
const int bitmapInfo = ((int)CGBitmapFlags.ByteOrder32Big) | ((int)CGImageAlphaInfo.PremultipliedLast);
|
|
var bounds = GetApplicationFrame();
|
|
var statusBarOffset = UIScreen.MainScreen.Bounds.Height - bounds.Height;
|
|
|
|
using (var colorSpace = CGColorSpace.CreateDeviceRGB())
|
|
using (var bContext = new CGBitmapContext(pixels, _bitmap.Width, _bitmap.Height, 8, _bitmap.Width * 4, colorSpace, (CGImageAlphaInfo)bitmapInfo))
|
|
using (var image = bContext.ToImage())
|
|
using (var context = UIGraphics.GetCurrentContext())
|
|
{
|
|
// flip the image for CGContext.DrawImage
|
|
context.TranslateCTM(0, bounds.Height + statusBarOffset);
|
|
context.ScaleCTM(1, -1);
|
|
context.DrawImage(bounds, image);
|
|
}
|
|
|
|
_bitmap.UnlockPixels();
|
|
}
|
|
}
|
|
}
|
|
|