diff --git a/build/ApiDiff.props b/build/ApiDiff.props index da82fbcc51..3d322f56d5 100644 --- a/build/ApiDiff.props +++ b/build/ApiDiff.props @@ -7,6 +7,6 @@ - + diff --git a/src/Avalonia.OpenGL/Egl/EglContext.cs b/src/Avalonia.OpenGL/Egl/EglContext.cs index 5365354418..249b4d547f 100644 --- a/src/Avalonia.OpenGL/Egl/EglContext.cs +++ b/src/Avalonia.OpenGL/Egl/EglContext.cs @@ -73,7 +73,8 @@ namespace Avalonia.OpenGL.Egl var old = new RestoreContext(_egl, _disp.Handle, _lock); var surf = surface ?? OffscreenSurface; _egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); - if (!_egl.MakeCurrent(_disp.Handle, surf.DangerousGetHandle(), surf.DangerousGetHandle(), Context)) + if (!_egl.MakeCurrent(_disp.Handle, surf?.DangerousGetHandle() ?? IntPtr.Zero, + surf?.DangerousGetHandle() ?? IntPtr.Zero, Context)) throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl); success = true; return old; diff --git a/src/Avalonia.OpenGL/Egl/EglDisplay.cs b/src/Avalonia.OpenGL/Egl/EglDisplay.cs index fd3de854f5..623364866b 100644 --- a/src/Avalonia.OpenGL/Egl/EglDisplay.cs +++ b/src/Avalonia.OpenGL/Egl/EglDisplay.cs @@ -158,15 +158,21 @@ namespace Avalonia.OpenGL.Egl var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes); if (ctx == IntPtr.Zero) throw OpenGlException.GetFormattedException("eglCreateContext", _egl); - var surf = _egl.CreatePBufferSurface(_display, _config, new[] + + var extensions = _egl.QueryString(Handle, EGL_EXTENSIONS); + + IntPtr surf = IntPtr.Zero; + if (extensions?.Contains("EGL_KHR_surfaceless_context") != true) { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }); - if (surf == IntPtr.Zero) - throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl); - var rv = new EglContext(this, _egl, shareCtx, ctx, context => new EglSurface(this, context, surf), + surf = _egl.CreatePBufferSurface(_display, _config, + new[] { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }); + if (surf == IntPtr.Zero) + throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl); + } + + var rv = new EglContext(this, _egl, shareCtx, ctx, + context => + surf == IntPtr.Zero ? null : new EglSurface(this, context, surf), _version, _sampleCount, _stencilSize); return rv; } 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))) { diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs index 72eed9e543..dc44d2d55f 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs @@ -141,17 +141,7 @@ namespace Avalonia.LinuxFramebuffer.Output _platformGl = new EglPlatformOpenGlInterface(_eglDisplay); _eglSurface = _platformGl.CreateWindowSurface(_gbmTargetSurface); - - EglContext CreateContext(EglContext share) - { - var offSurf = gbm_surface_create(device, 1, 1, GbmColorFormats.GBM_FORMAT_XRGB8888, - GbmBoFlags.GBM_BO_USE_RENDERING); - if (offSurf == null) - throw new InvalidOperationException("Unable to create 1x1 sized GBM surface"); - return _eglDisplay.CreateContext(share, _platformGl.CreateWindowSurface(offSurf)); - } - - _deferredContext = CreateContext(null); + _deferredContext = _platformGl.PrimaryEglContext; using (_deferredContext.MakeCurrent(_eglSurface)) { diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 9a486b60aa..cbc896813f 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -42,6 +42,11 @@ namespace Avalonia.Skia /// public struct CreateInfo { + /// + /// Canvas to draw to. + /// + public SKCanvas Canvas; + /// /// Surface to draw to. /// @@ -89,7 +94,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) { 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); + } + } +}