diff --git a/source/SkiaSharp.Build.props b/source/SkiaSharp.Build.props index 4afcc9bdcaf..95abf2aa23d 100644 --- a/source/SkiaSharp.Build.props +++ b/source/SkiaSharp.Build.props @@ -49,7 +49,7 @@ netstandard1.3;netstandard2.0;net462 net6.0-ios;net6.0-maccatalyst;net6.0-tvos;net6.0-macos;net6.0-android - $(Net6PlatformTargetFrameworks);net6.0-tizen6.5 + $(Net6PlatformTargetFrameworks);net6.0-tizen net6.0;$(Net6PlatformTargetFrameworks) @@ -62,7 +62,7 @@ net6.0;net6.0-ios;net6.0-maccatalyst;net6.0-android - $(MauiTargetFrameworks);net6.0-tizen6.5 + $(MauiTargetFrameworks);net6.0-tizen $(MauiTargetFrameworks);net6.0-windows10.0.19041.0 diff --git a/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKCanvasView/SKCanvasViewHandler.Tizen.cs b/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKCanvasView/SKCanvasViewHandler.Tizen.cs new file mode 100644 index 00000000000..2e8516cfdd8 --- /dev/null +++ b/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKCanvasView/SKCanvasViewHandler.Tizen.cs @@ -0,0 +1,84 @@ +using Microsoft.Maui; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; +using SkiaSharp.Views.Tizen; +using SkiaSharp.Views.Maui.Platform; + +namespace SkiaSharp.Views.Maui.Handlers +{ + public partial class SKCanvasViewHandler : ViewHandler + { + private SKSizeI lastCanvasSize; + private SKTouchHandler? touchHandler; + + protected override SKCanvasView CreatePlatformView() => new SKCanvasView(PlatformParent); + + protected override void ConnectHandler(SKCanvasView platformView) + { + platformView.PaintSurface += OnPaintSurface; + + base.ConnectHandler(platformView); + } + + protected override void DisconnectHandler(SKCanvasView platformView) + { + touchHandler?.Detach(platformView); + touchHandler = null; + + platformView.PaintSurface -= OnPaintSurface; + + base.DisconnectHandler(platformView); + } + + // Mapper actions / properties + + public static void OnInvalidateSurface(SKCanvasViewHandler handler, ISKCanvasView canvasView, object? args) + { + handler.PlatformView?.Invalidate(); + } + + public static void MapIgnorePixelScaling(SKCanvasViewHandler handler, ISKCanvasView canvasView) + { + handler.PlatformView?.UpdateIgnorePixelScaling(canvasView); + } + + public static void MapEnableTouchEvents(SKCanvasViewHandler handler, ISKCanvasView canvasView) + { + if (handler.PlatformView == null) + return; + + handler.touchHandler ??= new SKTouchHandler( + args => canvasView.OnTouch(args), + (x, y) => handler.OnGetScaledCoord(x, y)); + + handler.touchHandler?.SetEnabled(handler.PlatformView, canvasView.EnableTouchEvents); + } + + // helper methods + + private void OnPaintSurface(object? sender, Tizen.SKPaintSurfaceEventArgs e) + { + var newCanvasSize = e.Info.Size; + if (lastCanvasSize != newCanvasSize) + { + lastCanvasSize = newCanvasSize; + VirtualView?.OnCanvasSizeChanged(newCanvasSize); + } + + VirtualView?.OnPaintSurface(new SKPaintSurfaceEventArgs(e.Surface, e.Info, e.RawInfo)); + } + + private SKPoint OnGetScaledCoord(double x, double y) + { + if (VirtualView?.IgnorePixelScaling == false && PlatformView != null) + { + var scale = PlatformView.ContentScaleFactor; + + x *= scale; + y *= scale; + } + + return new SKPoint((float)x, (float)y); + } + } +} diff --git a/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKImageSourceService/SKImageSourceService.Tizen.cs b/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKImageSourceService/SKImageSourceService.Tizen.cs new file mode 100644 index 00000000000..b1f5b2f588d --- /dev/null +++ b/source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Handlers/SKImageSourceService/SKImageSourceService.Tizen.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Maui; +using Microsoft.Extensions.Logging; +using SkiaSharp.Views.Tizen; +using Tizen.UIExtensions.ElmSharp; + +namespace SkiaSharp.Views.Maui.Handlers +{ + public partial class SKImageSourceService + { + public override Task?> GetImageAsync(IImageSource imageSource, Image image, CancellationToken cancellationToken = default) => + GetImageAsync((IStreamImageSource)imageSource, image, cancellationToken); + + + public async Task?> GetImageAsync(IStreamImageSource imageSource, Image image, CancellationToken cancellationToken = default) + { + if (imageSource.IsEmpty) + return null; + + try + { + var stream = imageSource switch + { + ISKImageImageSource img => ToStream(img.Image), + ISKBitmapImageSource bmp => ToStream(SKImage.FromBitmap(bmp.Bitmap)), + ISKPixmapImageSource pix => ToStream(SKImage.FromPixels(pix.Pixmap)), + ISKPictureImageSource pic => ToStream(SKImage.FromPicture(pic.Picture, pic.Dimensions)), + _ => null, + }; + + if (stream == null) + throw new InvalidOperationException("Unable to load image stream."); + + var isLoadComplated = await image.LoadAsync(stream, cancellationToken); + + if (!isLoadComplated) + throw new InvalidOperationException("Unable to decode image from stream."); + + return new ImageSourceServiceResult(image); + } + catch (Exception ex) + { + Logger?.LogWarning(ex, "Unable to load image stream."); + throw; + } + } + + private static Stream ToStream(SKImage skiaImage) + { + return skiaImage.Encode().AsStream(); + } + } +}