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.
124 lines
4.5 KiB
124 lines
4.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using Avalonia.Logging;
|
|
using Avalonia.Media.Imaging;
|
|
using Avalonia.Media.Immutable;
|
|
using Avalonia.Platform;
|
|
using Avalonia.Rendering.SceneGraph;
|
|
using Avalonia.Threading;
|
|
using Avalonia.Utilities;
|
|
|
|
namespace Avalonia.Media;
|
|
|
|
internal sealed class PlatformDrawingContext : DrawingContext, IDrawingContextWithAcrylicLikeSupport
|
|
{
|
|
private readonly IDrawingContextImpl _impl;
|
|
private readonly bool _ownsImpl;
|
|
private static ThreadSafeObjectPool<Stack<Matrix>> TransformStackPool { get; } =
|
|
ThreadSafeObjectPool<Stack<Matrix>>.Default;
|
|
|
|
private Stack<Matrix>? _transforms;
|
|
|
|
|
|
public PlatformDrawingContext(IDrawingContextImpl impl, bool ownsImpl = true)
|
|
{
|
|
_impl = impl;
|
|
_ownsImpl = ownsImpl;
|
|
}
|
|
|
|
protected override void DrawLineCore(IPen pen, Point p1, Point p2) =>
|
|
_impl.DrawLine(pen, p1, p2);
|
|
|
|
protected override void DrawGeometryCore(IBrush? brush, IPen? pen, IGeometryImpl geometry) =>
|
|
_impl.DrawGeometry(brush, pen, geometry);
|
|
|
|
protected override void DrawRectangleCore(IBrush? brush, IPen? pen, RoundedRect rrect,
|
|
BoxShadows boxShadows = default) =>
|
|
_impl.DrawRectangle(brush, pen, rrect, boxShadows);
|
|
|
|
protected override void DrawEllipseCore(IBrush? brush, IPen? pen, Rect rect) => _impl.DrawEllipse(brush, pen, rect);
|
|
|
|
internal override void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect,
|
|
BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default) =>
|
|
_impl.DrawBitmap(source, opacity, sourceRect, destRect, bitmapInterpolationMode);
|
|
|
|
public override void Custom(ICustomDrawOperation custom)
|
|
{
|
|
using var immediateDrawingContext = new ImmediateDrawingContext(_impl, false);
|
|
try
|
|
{
|
|
custom.Render(immediateDrawingContext);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.TryGet(LogEventLevel.Error, LogArea.Visual)
|
|
?.Log(custom, $"Exception in {custom.GetType().Name}.{nameof(ICustomDrawOperation.Render)} {{0}}", e);
|
|
}
|
|
}
|
|
|
|
public override void DrawGlyphRun(IBrush? foreground, GlyphRun glyphRun)
|
|
{
|
|
_ = glyphRun ?? throw new ArgumentNullException(nameof(glyphRun));
|
|
|
|
if (foreground != null)
|
|
_impl.DrawGlyphRun(foreground, glyphRun.PlatformImpl);
|
|
}
|
|
|
|
protected override void PushClipCore(RoundedRect rect) => _impl.PushClip(rect);
|
|
|
|
protected override void PushClipCore(Rect rect) => _impl.PushClip(rect);
|
|
|
|
protected override void PushGeometryClipCore(Geometry clip) =>
|
|
_impl.PushGeometryClip(clip.PlatformImpl ?? throw new ArgumentException());
|
|
|
|
protected override void PushOpacityCore(double opacity, Rect bounds) =>
|
|
_impl.PushOpacity(opacity, bounds);
|
|
|
|
protected override void PushOpacityMaskCore(IBrush mask, Rect bounds) =>
|
|
_impl.PushOpacityMask(mask, bounds);
|
|
|
|
protected override void PushBitmapBlendModeCore(BitmapBlendingMode blendingMode) =>
|
|
_impl.PushBitmapBlendMode(blendingMode);
|
|
|
|
protected override void PushTransformCore(Matrix matrix)
|
|
{
|
|
_transforms ??= TransformStackPool.Get();
|
|
var current = _impl.Transform;
|
|
_transforms.Push(current);
|
|
_impl.Transform = matrix * current;
|
|
}
|
|
|
|
protected override void PopClipCore() => _impl.PopClip();
|
|
|
|
protected override void PopGeometryClipCore() => _impl.PopGeometryClip();
|
|
|
|
protected override void PopOpacityCore() => _impl.PopOpacity();
|
|
|
|
protected override void PopOpacityMaskCore() => _impl.PopOpacityMask();
|
|
|
|
protected override void PopBitmapBlendModeCore() => _impl.PopBitmapBlendMode();
|
|
|
|
protected override void PopTransformCore() =>
|
|
_impl.Transform =
|
|
(_transforms ?? throw new ObjectDisposedException(nameof(PlatformDrawingContext))).Pop();
|
|
|
|
protected override void DisposeCore()
|
|
{
|
|
if (_ownsImpl)
|
|
_impl.Dispose();
|
|
if (_transforms != null)
|
|
{
|
|
if (_transforms.Count != 0)
|
|
throw new InvalidOperationException("Not all states are disposed");
|
|
TransformStackPool.ReturnAndSetNull(ref _transforms);
|
|
}
|
|
}
|
|
|
|
public void DrawRectangle(IExperimentalAcrylicMaterial material, RoundedRect rect)
|
|
{
|
|
if (_impl is IDrawingContextWithAcrylicLikeSupport idc)
|
|
idc.DrawRectangle(material, rect);
|
|
else
|
|
DrawRectangle(new ImmutableSolidColorBrush(material.FallbackColor), null, rect);
|
|
}
|
|
}
|
|
|