Skip to content

Commit

Permalink
Implemented SKGLView for Android and iOS
Browse files Browse the repository at this point in the history
- Mac Catalyst will not get support - a new Metal-based view needs to be created
- Tizen needs the support in the native view
- Windows will come in a separate PR
  • Loading branch information
mattleibow committed Feb 3, 2024
1 parent 79162b3 commit 16c8828
Show file tree
Hide file tree
Showing 24 changed files with 598 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static MauiAppBuilder UseSkiaSharp(this MauiAppBuilder builder) =>
.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<SKCanvasView, SKCanvasViewHandler>();
handlers.AddHandler<SKGLView, SKGLViewHandler>();
})
.ConfigureImageSources(sources =>
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,107 +8,60 @@

namespace SkiaSharp.Views.Maui.Controls
{
public partial class SKCanvasView : View, ISKCanvasViewController
public partial class SKCanvasView : View, ISKCanvasView
{
public static readonly BindableProperty IgnorePixelScalingProperty =
BindableProperty.Create(nameof(IgnorePixelScaling), typeof(bool), typeof(SKCanvasView), false);

public static readonly BindableProperty EnableTouchEventsProperty =
BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKCanvasView), false);

// the user can subscribe to repaint
private SKSizeI lastCanvasSize;

public SKCanvasView()
{
}

public event EventHandler<SKPaintSurfaceEventArgs>? PaintSurface;

// the user can subscribe to touch events
public event EventHandler<SKTouchEventArgs>? Touch;

// the native listens to this event
private event EventHandler? SurfaceInvalidated;
private event EventHandler<GetPropertyValueEventArgs<SKSize>>? GetCanvasSize;

// the user asks the for the size
public SKSize CanvasSize
{
get
{
// send a mesage to the native view
var args = new GetPropertyValueEventArgs<SKSize>();
GetCanvasSize?.Invoke(this, args);
return args.Value;
}
}
public SKSize CanvasSize => lastCanvasSize;

public bool IgnorePixelScaling
{
get { return (bool)GetValue(IgnorePixelScalingProperty); }
set { SetValue(IgnorePixelScalingProperty, value); }
get => (bool)GetValue(IgnorePixelScalingProperty);
set => SetValue(IgnorePixelScalingProperty, value);
}

public bool EnableTouchEvents
{
get { return (bool)GetValue(EnableTouchEventsProperty); }
set { SetValue(EnableTouchEventsProperty, value); }
get => (bool)GetValue(EnableTouchEventsProperty);
set => SetValue(EnableTouchEventsProperty, value);
}

// the user asks to repaint
public void InvalidateSurface()
{
// send a mesage to the native view
SurfaceInvalidated?.Invoke(this, EventArgs.Empty);
Handler?.Invoke(nameof(ISKCanvasView.InvalidateSurface));
}

// the native view tells the user to repaint
protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
PaintSurface?.Invoke(this, e);
}

// the native view responds to a touch
protected virtual void OnTouch(SKTouchEventArgs e)
{
Touch?.Invoke(this, e);
}

// ISKViewController implementation

event EventHandler ISKCanvasViewController.SurfaceInvalidated
{
add { SurfaceInvalidated += value; }
remove { SurfaceInvalidated -= value; }
}

event EventHandler<GetPropertyValueEventArgs<SKSize>> ISKCanvasViewController.GetCanvasSize
{
add { GetCanvasSize += value; }
remove { GetCanvasSize -= value; }
}
void ISKCanvasView.OnCanvasSizeChanged(SKSizeI size) =>
lastCanvasSize = size;

void ISKCanvasViewController.OnPaintSurface(SKPaintSurfaceEventArgs e)
{
void ISKCanvasView.OnPaintSurface(SKPaintSurfaceEventArgs e) =>
OnPaintSurface(e);
}

void ISKCanvasViewController.OnTouch(SKTouchEventArgs e)
{
void ISKCanvasView.OnTouch(SKTouchEventArgs e) =>
OnTouch(e);
}

protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
return new SizeRequest(new Size(40.0, 40.0));
}
}

public interface ISKCanvasViewController : IViewController
{
// the native listens to this event
event EventHandler SurfaceInvalidated;
event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;

// the native view tells the user to repaint
void OnPaintSurface(SKPaintSurfaceEventArgs e);

// the native view responds to a touch
void OnTouch(SKTouchEventArgs e);
}
}
108 changes: 26 additions & 82 deletions source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Controls/SKGLView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,127 +8,71 @@

namespace SkiaSharp.Views.Maui.Controls
{
public partial class SKGLView : View, ISKGLViewController
public partial class SKGLView : View, ISKGLView
{
public static readonly BindableProperty IgnorePixelScalingProperty =
BindableProperty.Create(nameof(IgnorePixelScaling), typeof(bool), typeof(SKGLView), false);

public static readonly BindableProperty HasRenderLoopProperty =
BindableProperty.Create(nameof(HasRenderLoop), typeof(bool), typeof(SKGLView), false);

public static readonly BindableProperty EnableTouchEventsProperty =
BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKGLView), false);

private SKSizeI lastCanvasSize;
private GRContext? lastGRContext;

public bool IgnorePixelScaling
{
get => (bool)GetValue(IgnorePixelScalingProperty);
set => SetValue(IgnorePixelScalingProperty, value);
}

public bool HasRenderLoop
{
get { return (bool)GetValue(HasRenderLoopProperty); }
set { SetValue(HasRenderLoopProperty, value); }
get => (bool)GetValue(HasRenderLoopProperty);
set => SetValue(HasRenderLoopProperty, value);
}

public bool EnableTouchEvents
{
get { return (bool)GetValue(EnableTouchEventsProperty); }
set { SetValue(EnableTouchEventsProperty, value); }
get => (bool)GetValue(EnableTouchEventsProperty);
set => SetValue(EnableTouchEventsProperty, value);
}

// the user can subscribe to repaint
public event EventHandler<SKPaintGLSurfaceEventArgs>? PaintSurface;

// the user can subscribe to touch events
public event EventHandler<SKTouchEventArgs>? Touch;

// the native listens to this event
private event EventHandler? SurfaceInvalidated;
private event EventHandler<GetPropertyValueEventArgs<SKSize>>? GetCanvasSize;
private event EventHandler<GetPropertyValueEventArgs<GRContext>>? GetGRContext;
public SKSize CanvasSize => lastCanvasSize;

// the user asks the for the size
public SKSize CanvasSize
{
get
{
// send a mesage to the native view
var args = new GetPropertyValueEventArgs<SKSize>();
GetCanvasSize?.Invoke(this, args);
return args.Value;
}
}
public GRContext? GRContext => lastGRContext;

// the user asks the for the current GRContext
public GRContext GRContext
{
get
{
// send a mesage to the native view
var args = new GetPropertyValueEventArgs<GRContext>();
GetGRContext?.Invoke(this, args);
return args.Value;
}
}

// the user asks to repaint
public void InvalidateSurface()
{
// send a mesage to the native view
SurfaceInvalidated?.Invoke(this, EventArgs.Empty);
Handler?.Invoke(nameof(ISKGLView.InvalidateSurface));
}

// the native view tells the user to repaint
protected virtual void OnPaintSurface(SKPaintGLSurfaceEventArgs e)
{
PaintSurface?.Invoke(this, e);
}

// the native view responds to a touch
protected virtual void OnTouch(SKTouchEventArgs e)
{
Touch?.Invoke(this, e);
}

// ISKViewController implementation

event EventHandler ISKGLViewController.SurfaceInvalidated
{
add { SurfaceInvalidated += value; }
remove { SurfaceInvalidated -= value; }
}

event EventHandler<GetPropertyValueEventArgs<SKSize>> ISKGLViewController.GetCanvasSize
{
add { GetCanvasSize += value; }
remove { GetCanvasSize -= value; }
}
void ISKGLView.OnCanvasSizeChanged(SKSizeI size) =>
lastCanvasSize = size;

event EventHandler<GetPropertyValueEventArgs<GRContext>> ISKGLViewController.GetGRContext
{
add { GetGRContext += value; }
remove { GetGRContext -= value; }
}
void ISKGLView.OnGRContextChanged(GRContext? context) =>
lastGRContext = context;

void ISKGLViewController.OnPaintSurface(SKPaintGLSurfaceEventArgs e)
{
void ISKGLView.OnPaintSurface(SKPaintGLSurfaceEventArgs e) =>
OnPaintSurface(e);
}

void ISKGLViewController.OnTouch(SKTouchEventArgs e)
{
void ISKGLView.OnTouch(SKTouchEventArgs e) =>
OnTouch(e);
}

protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
return new SizeRequest(new Size(40.0, 40.0));
}
}

public interface ISKGLViewController : IViewController
{
// the native listens to this event
event EventHandler SurfaceInvalidated;
event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;
event EventHandler<GetPropertyValueEventArgs<GRContext>> GetGRContext;

// the native view tells the user to repaint
void OnPaintSurface(SKPaintGLSurfaceEventArgs e);

// the native view responds to a touch
void OnTouch(SKTouchEventArgs e);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace SkiaSharp.Views.Maui.Controls
{
public sealed partial class SKImageImageSource : ImageSource
public sealed partial class SKImageImageSource : ImageSource, ISKImageImageSource
{
public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(Image), typeof(SKImage), typeof(SKImageImageSource), default(SKImage));

Expand Down Expand Up @@ -41,7 +41,7 @@ protected override void OnPropertyChanged(string propertyName = null)
}
}

public sealed partial class SKBitmapImageSource : ImageSource
public sealed partial class SKBitmapImageSource : ImageSource, ISKBitmapImageSource
{
public static readonly BindableProperty BitmapProperty = BindableProperty.Create(nameof(Bitmap), typeof(SKBitmap), typeof(SKBitmapImageSource), default(SKBitmap));

Expand Down Expand Up @@ -77,7 +77,7 @@ protected override void OnPropertyChanged(string propertyName = null)
}
}

public sealed partial class SKPixmapImageSource : ImageSource
public sealed partial class SKPixmapImageSource : ImageSource, ISKPixmapImageSource
{
public static readonly BindableProperty PixmapProperty = BindableProperty.Create(nameof(Pixmap), typeof(SKPixmap), typeof(SKPixmapImageSource), default(SKPixmap));

Expand Down Expand Up @@ -113,7 +113,7 @@ protected override void OnPropertyChanged(string propertyName = null)
}
}

public sealed partial class SKPictureImageSource : ImageSource
public sealed partial class SKPictureImageSource : ImageSource, ISKPictureImageSource
{
public static readonly BindableProperty PictureProperty = BindableProperty.Create(nameof(Picture), typeof(SKPicture), typeof(SKPictureImageSource), default(SKPicture));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Maui.Handlers;
using Microsoft.UI.Xaml;
using SkiaSharp.Views.Maui.Platform;
using SkiaSharp.Views.Windows;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public partial class SKCanvasViewHandler
};

public static CommandMapper<ISKCanvasView, SKCanvasViewHandler> SKCanvasViewCommandMapper =
new CommandMapper<ISKCanvasView, SKCanvasViewHandler>()
new CommandMapper<ISKCanvasView, SKCanvasViewHandler>(ViewHandler.ViewCommandMapper)
{
[nameof(ISKCanvasView.InvalidateSurface)] = OnInvalidateSurface,
};
Expand Down
Loading

0 comments on commit 16c8828

Please sign in to comment.