From c02d97cf84f2f2516114540f5aa8f4d281558094 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 29 Sep 2020 14:42:38 +0300 Subject: [PATCH 1/5] allow to create Skia drawing context from existing canvas --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 98528a128a..fd6ccd2eca 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -41,6 +41,11 @@ namespace Avalonia.Skia /// public struct CreateInfo { + /// + /// Canvas to draw to. + /// + public SKCanvas Canvas; + /// /// Surface to draw to. /// @@ -82,7 +87,7 @@ namespace Avalonia.Skia if (_grContext != null) Monitor.Enter(_grContext); Surface = createInfo.Surface; - Canvas = createInfo.Surface.Canvas; + Canvas = createInfo.Canvas ?? createInfo.Surface?.Canvas; if (Canvas == null) { From e893705823862945c4cfa0316e77f8293817d59c Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 2 Oct 2020 16:07:38 +0300 Subject: [PATCH 2/5] add a way to render to canvas with DrawingContext with public api --- .../ExternalCanvasRenderTarget.cs | 32 +++++++++++++++++++ .../Avalonia.Skia/IExternalCanvasSurface.cs | 11 +++++++ .../Avalonia.Skia/PlatformRenderInterface.cs | 2 ++ 3 files changed, 45 insertions(+) create mode 100644 src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs create mode 100644 src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs diff --git a/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs b/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs new file mode 100644 index 0000000000..c9e779797b --- /dev/null +++ b/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs @@ -0,0 +1,32 @@ +using Avalonia.Platform; +using Avalonia.Rendering; + +namespace Avalonia.Skia +{ + internal class ExternalCanvasRenderTarget : IRenderTarget + { + private IExternalCanvasSurface _surface; + + public ExternalCanvasRenderTarget(IExternalCanvasSurface canvas) + { + _surface = canvas; + } + + public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) + { + var createInfo = new DrawingContextImpl.CreateInfo + { + Canvas = _surface.Canvas, + Dpi = _surface.Dpi, + VisualBrushRenderer = visualBrushRenderer, + DisableTextLcdRendering = true, + }; + + return new DrawingContextImpl(createInfo); + } + + public void Dispose() + { + } + } +} diff --git a/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs b/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs new file mode 100644 index 0000000000..38347f2caa --- /dev/null +++ b/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs @@ -0,0 +1,11 @@ +using SkiaSharp; + +namespace Avalonia.Skia +{ + public interface IExternalCanvasSurface + { + SKCanvas Canvas { get; } + + Vector Dpi { get; } + } +} diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index b9c1cbc673..397d358ba7 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -145,6 +145,8 @@ namespace Avalonia.Skia { if (surface is IFramebufferPlatformSurface framebufferSurface) return new FramebufferRenderTarget(framebufferSurface); + if (surface is IExternalCanvasSurface canvas) + return new ExternalCanvasRenderTarget(canvas); } throw new NotSupportedException( From 40941043f37d34145576bf405f90ec190b44730a Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Mon, 5 Oct 2020 12:14:10 +0300 Subject: [PATCH 3/5] Revert "add a way to render to canvas with DrawingContext with public api" This reverts commit e893705823862945c4cfa0316e77f8293817d59c. --- .../ExternalCanvasRenderTarget.cs | 32 ------------------- .../Avalonia.Skia/IExternalCanvasSurface.cs | 11 ------- .../Avalonia.Skia/PlatformRenderInterface.cs | 2 -- 3 files changed, 45 deletions(-) delete mode 100644 src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs delete mode 100644 src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs diff --git a/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs b/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs deleted file mode 100644 index c9e779797b..0000000000 --- a/src/Skia/Avalonia.Skia/ExternalCanvasRenderTarget.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Avalonia.Platform; -using Avalonia.Rendering; - -namespace Avalonia.Skia -{ - internal class ExternalCanvasRenderTarget : IRenderTarget - { - private IExternalCanvasSurface _surface; - - public ExternalCanvasRenderTarget(IExternalCanvasSurface canvas) - { - _surface = canvas; - } - - public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) - { - var createInfo = new DrawingContextImpl.CreateInfo - { - Canvas = _surface.Canvas, - Dpi = _surface.Dpi, - VisualBrushRenderer = visualBrushRenderer, - DisableTextLcdRendering = true, - }; - - return new DrawingContextImpl(createInfo); - } - - public void Dispose() - { - } - } -} diff --git a/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs b/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs deleted file mode 100644 index 38347f2caa..0000000000 --- a/src/Skia/Avalonia.Skia/IExternalCanvasSurface.cs +++ /dev/null @@ -1,11 +0,0 @@ -using SkiaSharp; - -namespace Avalonia.Skia -{ - public interface IExternalCanvasSurface - { - SKCanvas Canvas { get; } - - Vector Dpi { get; } - } -} diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index 397d358ba7..b9c1cbc673 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -145,8 +145,6 @@ namespace Avalonia.Skia { if (surface is IFramebufferPlatformSurface framebufferSurface) return new FramebufferRenderTarget(framebufferSurface); - if (surface is IExternalCanvasSurface canvas) - return new ExternalCanvasRenderTarget(canvas); } throw new NotSupportedException( From 9c1e31aeced7791e6a7aba251dbc9ad9ff2cf076 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Mon, 5 Oct 2020 12:22:31 +0300 Subject: [PATCH 4/5] add public api to create skia drawing context from canvas --- .../Helpers/DrawingContextHelper.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs diff --git a/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs new file mode 100644 index 0000000000..72438609d5 --- /dev/null +++ b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs @@ -0,0 +1,31 @@ +using Avalonia.Platform; +using Avalonia.Rendering; +using SkiaSharp; + +namespace Avalonia.Skia.Helpers +{ + public class DrawingContextHelper + { + /// + /// Wrap Skia canvas in drawing context so we can use Avalonia api to render to external skia canvas + /// this is useful in scenarios where canvas is not controlled by application, but received from another non avalonia api + /// like: SKCanvas canvas = SKDocument.BeginPage(...); + /// + /// + /// + /// + /// DrawingContext + public static IDrawingContextImpl WrapSkiaCanvas(SKCanvas canvas, Vector dpi, IVisualBrushRenderer visualBrushRenderer = null) + { + var createInfo = new DrawingContextImpl.CreateInfo + { + Canvas = canvas, + Dpi = dpi, + VisualBrushRenderer = visualBrushRenderer, + DisableTextLcdRendering = true, + }; + + return new DrawingContextImpl(createInfo); + } + } +} From 9eed4c974e98d840b883e3534588c09eaab333d6 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Fri, 9 Oct 2020 18:29:02 +0200 Subject: [PATCH 5/5] Make sure a GlyphRun's bounds are properly calculated --- src/Avalonia.Visuals/Media/GlyphRun.cs | 15 +++++++++++++-- .../Media/TextFormatting/TextLineImpl.cs | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Visuals/Media/GlyphRun.cs b/src/Avalonia.Visuals/Media/GlyphRun.cs index 155339b985..66a8c1dd0c 100644 --- a/src/Avalonia.Visuals/Media/GlyphRun.cs +++ b/src/Avalonia.Visuals/Media/GlyphRun.cs @@ -18,7 +18,7 @@ namespace Avalonia.Media private double _fontRenderingEmSize; private Size? _size; private int _biDiLevel; - private Point _baselineOrigin; + private Point? _baselineOrigin; private ReadOnlySlice _glyphIndices; private ReadOnlySlice _glyphAdvances; @@ -97,7 +97,9 @@ namespace Avalonia.Media { get { - return _baselineOrigin; + _baselineOrigin ??= CalculateBaselineOrigin(); + + return _baselineOrigin.Value; } set => Set(ref _baselineOrigin, value); } @@ -538,6 +540,15 @@ namespace Avalonia.Media return GlyphAdvances[index]; } + /// + /// Calculates the default baseline origin of the . + /// + /// The baseline origin. + private Point CalculateBaselineOrigin() + { + return new Point(0, -GlyphTypeface.Ascent * Scale); + } + /// /// Calculates the size of the . /// diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs index d13b4836ea..fc98e9f6f8 100644 --- a/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs @@ -39,7 +39,7 @@ namespace Avalonia.Media.TextFormatting foreach (var textRun in _textRuns) { - var offsetY = LineMetrics.TextBaseline; + var offsetY = LineMetrics.TextBaseline - textRun.GlyphRun.BaselineOrigin.Y; using (drawingContext.PushPostTransform(Matrix.CreateTranslation(currentX, offsetY))) {