diff --git a/binding/Binding/SKPaint.cs b/binding/Binding/SKPaint.cs index 391a981456..e53ed28930 100644 --- a/binding/Binding/SKPaint.cs +++ b/binding/Binding/SKPaint.cs @@ -14,6 +14,7 @@ public enum SKPaintHinting public unsafe class SKPaint : SKObject, ISKSkipObjectRegistration { private SKFont font; + private bool lcdRenderText; internal SKPaint (IntPtr handle, bool owns) : base (handle, owns) @@ -38,6 +39,8 @@ public SKPaint (SKFont font) if (Handle == IntPtr.Zero) throw new InvalidOperationException ("Unable to create a new SKPaint instance."); + + LcdRenderText = font.Edging == SKFontEdging.SubpixelAntialias; } protected override void Dispose (bool disposing) => @@ -55,7 +58,10 @@ public void Reset () => public bool IsAntialias { get => SkiaApi.sk_paint_is_antialias (Handle); - set => SkiaApi.sk_paint_set_antialias (Handle, value); + set { + SkiaApi.sk_paint_set_antialias (Handle, value); + UpdateFontEdging (value); + } } public bool IsDither { @@ -81,8 +87,11 @@ public bool SubpixelText { } public bool LcdRenderText { - get => GetFont ().Edging == SKFontEdging.SubpixelAntialias; - set => GetFont ().Edging = value ? SKFontEdging.SubpixelAntialias : SKFontEdging.Antialias; + get => lcdRenderText; + set { + lcdRenderText = value; + UpdateFontEdging (IsAntialias); + } } public bool IsEmbeddedBitmapText { @@ -701,6 +710,17 @@ public SKFont ToFont () => internal SKFont GetFont () => font ??= OwnedBy (SKFont.GetObject (SkiaApi.sk_compatpaint_get_font (Handle), false), this); + private void UpdateFontEdging (bool antialias) + { + var edging = SKFontEdging.Alias; + if (antialias) { + edging = lcdRenderText + ? SKFontEdging.SubpixelAntialias + : SKFontEdging.Antialias; + } + GetFont ().Edging = edging; + } + // internal static SKPaint GetObject (IntPtr handle) => diff --git a/externals/skia b/externals/skia index afebb8307c..b2c81806f3 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit afebb8307c05be3e11bc3cf71cb2270da771ed88 +Subproject commit b2c81806f30929802d755eab1e49ee1024a950dc diff --git a/scripts/azure-pipelines.yml b/scripts/azure-pipelines.yml index 03bec0a312..c27a33fb07 100644 --- a/scripts/azure-pipelines.yml +++ b/scripts/azure-pipelines.yml @@ -831,7 +831,7 @@ stages: notifyAlwaysV2: false instanceUrlForTsaV2: 'DEVDIV' projectNameDEVDIV: 'DevDiv' - areaPath: 'DevDiv\Xamarin SDK\SkiaSharp' + areaPath: 'DevDiv\VS Client - Runtime SDKs\SkiaSharp' iterationPath: 'DevDiv\OneVS' uploadAPIScan: false uploadBinSkim: false diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs index 0f33de1108..f28880a582 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs @@ -46,5 +46,19 @@ public override void Draw(CGRect dirtyRect) // draw the surface to the context drawable.DrawSurface(ctx, Bounds, info, surface); } + + public override void WillMoveToWindow(UIWindow window) + { + if (drawable != null) + { + // release the memory if we are leaving the window + if (window == null) + drawable?.Dispose(); + else + SetNeedsDisplay(); + } + + base.WillMoveToWindow(window); + } } } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCGSurfaceFactory.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCGSurfaceFactory.cs index fe027073ec..ae3bcde693 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCGSurfaceFactory.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCGSurfaceFactory.cs @@ -47,6 +47,15 @@ public SKSurface CreateSurface(CGRect contentsBounds, nfloat scale, out SKImageI if (bitmapData == null) { bitmapData = NSMutableData.FromLength(info.BytesSize); + + // in case allocation has failed + if (bitmapData == null) + { + Dispose(); + info = Info; + return null; + } + dataProvider = new CGDataProvider(bitmapData.MutableBytes, info.BytesSize, Dummy); void Dummy(IntPtr data) diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs index 303dc6a918..7209ee81bf 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs @@ -105,6 +105,20 @@ public override void Draw(CGRect rect) } } + public override void WillMoveToWindow(UIWindow window) + { + if (drawable != null) + { + // release the memory if we are leaving the window + if (window == null) + drawable?.Dispose(); + else + SetNeedsDisplay(); + } + + base.WillMoveToWindow(window); + } + public event EventHandler PaintSurface; protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e) diff --git a/tests/Tests/SKPaintTest.cs b/tests/Tests/SKPaintTest.cs index f3e6349bb0..ed4dd7f8d4 100644 --- a/tests/Tests/SKPaintTest.cs +++ b/tests/Tests/SKPaintTest.cs @@ -554,5 +554,92 @@ public void GetTextPathSucceedsForEmtptyString() Assert.NotNull(paint.GetTextPath("", 0, 0)); } + + [SkippableTheory] + [InlineData(true, true, SKFontEdging.SubpixelAntialias)] + [InlineData(false, true, SKFontEdging.Alias)] + [InlineData(true, false, SKFontEdging.Antialias)] + [InlineData(false, false, SKFontEdging.Alias)] + public void UpdatingPropertiesIsAntialiasLcdRenderText(bool isAntialias, bool lcd, SKFontEdging newEdging) + { + var paint = new SKPaint(); + + paint.IsAntialias = isAntialias; + paint.LcdRenderText = lcd; + + Assert.Equal(newEdging, paint.GetFont().Edging); + } + + [SkippableTheory] + [InlineData(true, true, SKFontEdging.SubpixelAntialias)] + [InlineData(false, true, SKFontEdging.Alias)] + [InlineData(true, false, SKFontEdging.Antialias)] + [InlineData(false, false, SKFontEdging.Alias)] + public void UpdatingPropertiesLcdRenderTextIsAntialias(bool isAntialias, bool lcd, SKFontEdging newEdging) + { + var paint = new SKPaint(); + + paint.LcdRenderText = lcd; + paint.IsAntialias = isAntialias; + + Assert.Equal(newEdging, paint.GetFont().Edging); + } + + [SkippableFact] + public void PaintWithSubpixelEdgingIsPreserved() + { + var font = new SKFont(); + font.Edging = SKFontEdging.SubpixelAntialias; + + var paint = new SKPaint(font); + + Assert.True(paint.LcdRenderText); + Assert.False(paint.IsAntialias); + Assert.Equal(SKFontEdging.Alias, paint.GetFont().Edging); + + paint.IsAntialias = true; + + Assert.True(paint.LcdRenderText); + Assert.True(paint.IsAntialias); + Assert.Equal(SKFontEdging.SubpixelAntialias, paint.GetFont().Edging); + } + + [SkippableFact] + public void PaintWithAntialiasEdgingIsPreserved() + { + var font = new SKFont(); + font.Edging = SKFontEdging.Antialias; + + var paint = new SKPaint(font); + + Assert.False(paint.LcdRenderText); + Assert.False(paint.IsAntialias); + Assert.Equal(SKFontEdging.Alias, paint.GetFont().Edging); + + paint.IsAntialias = true; + + Assert.False(paint.LcdRenderText); + Assert.True(paint.IsAntialias); + Assert.Equal(SKFontEdging.Antialias, paint.GetFont().Edging); + } + + [SkippableFact] + public void PaintWithAliasEdgingIsPreserved() + { + var font = new SKFont(); + font.Edging = SKFontEdging.Alias; + + var paint = new SKPaint(font); + + Assert.False(paint.LcdRenderText); + Assert.False(paint.IsAntialias); + Assert.Equal(SKFontEdging.Alias, paint.GetFont().Edging); + + paint.IsAntialias = true; + + Assert.False(paint.LcdRenderText); + Assert.True(paint.IsAntialias); + Assert.Equal(SKFontEdging.Antialias, paint.GetFont().Edging); + } } }