Browse Source

Deleted a bunch of obsolete files, addressed all of the code styling comments, etc.

pull/506/head
Jason Jarvis 11 years ago
parent
commit
2c7d457057
  1. 42
      samples/TestApplicationShared/App.cs
  2. 53
      src/Skia/Perspex.Skia.Android/AndroidRenderTarget.cs
  3. 26
      src/Skia/Perspex.Skia.iOS/SkiaView.cs
  4. 23
      src/Skia/Perspex.Skia.iOS/iOSMethodTable.cs
  5. 27
      src/Skia/Perspex.Skia/DrawingContextImpl.cs
  6. 72
      src/Skia/Perspex.Skia/FormattedTextImpl.cs
  7. 240
      src/Skia/Perspex.Skia/MethodTable.cs
  8. 115
      src/Skia/Perspex.Skia/NativeBrush.cs
  9. 12
      src/Skia/Perspex.Skia/NativeDrawingContextSettings.cs
  10. 27
      src/Skia/Perspex.Skia/NativeFormattedText.cs
  11. 1
      src/Skia/Perspex.Skia/Perspex.Skia.projitems
  12. 110
      src/Skia/Perspex.Skia/PerspexHandleHolder.cs
  13. 24
      src/Skia/Perspex.Skia/PlatformRenderInterface.cs
  14. 13
      src/Skia/Perspex.Skia/RenderTarget.cs
  15. 31
      src/Skia/Perspex.Skia/SkRect.cs
  16. 5
      src/Skia/Perspex.Skia/SkiaPlatform.cs
  17. 33
      src/Skia/Perspex.Skia/SkiaPoint.cs
  18. 11
      src/Skia/Perspex.Skia/StreamGeometryImpl.cs
  19. 21
      src/Skia/Perspex.Skia/WindowDrawingContextImpl.cs
  20. 7
      src/Skia/Perspex.Skia/readme.md
  21. 18
      src/Windows/Perspex.Win32/SystemDialogImpl.cs
  22. 2
      src/iOS/Perspex.iOS/Perspex.iOS.csproj
  23. 77
      src/iOS/Perspex.iOS/PerspexAppDelegate.cs
  24. 30
      src/iOS/Perspex.iOS/PerspexView.cs
  25. 33
      src/iOS/Perspex.iOS/WindowingPlatformImpl.cs
  26. 41
      src/iOS/Perspex.iOS/iOSPlatform.cs
  27. 56
      src/iOS/Perspex.iOSTestApplication/AppDelegate.cs

42
samples/TestApplicationShared/App.cs

@ -11,6 +11,7 @@ using Perspex.Themes.Default;
using Perspex.Diagnostics; using Perspex.Diagnostics;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Shared.PlatformSupport; using Perspex.Shared.PlatformSupport;
using Perspex.Media;
namespace TestApplication namespace TestApplication
{ {
@ -43,10 +44,49 @@ namespace TestApplication
}; };
MainWindow.RootNamespace = "TestApplication"; MainWindow.RootNamespace = "TestApplication";
var wnd = MainWindow.Create(); var wnd = MainWindow.Create();
wnd.AttachDevTools(); wnd.AttachDevTools();
Run(wnd); Run(wnd);
} }
// This provides a simple UI tree for testing input handling, drawing, etc
public static Window CreateSimpleWindow()
{
Window window = new Window
{
Title = "Perspex Test Application",
Background = Brushes.Red,
Content = new StackPanel
{
Margin = new Thickness(30),
Background = Brushes.Yellow,
Children = new Controls
{
new TextBlock
{
Text = "TEXT BLOCK",
Width = 300,
Height = 40,
Background = Brushes.White,
Foreground = Brushes.Black
},
new Button
{
Content = "BUTTON",
Width = 150,
Height = 40,
Background = Brushes.LightGreen,
Foreground = Brushes.Black
}
}
}
};
return window;
}
} }
} }

53
src/Skia/Perspex.Skia.Android/AndroidRenderTarget.cs

@ -14,54 +14,11 @@ using Perspex.Platform;
namespace Perspex.Skia namespace Perspex.Skia
{ {
/* This lives in shared project now, but we may need an android specific implementation anyways /// <summary>
* /// We will likely need platform specific pieces to support HW acceleration
class RenderTarget : IRenderTarget /// so leaving this class here for now as placeholder.
/// </summary>
internal partial class RenderTarget : IRenderTarget
{ {
private IntPtr _currentRenderTarget = IntPtr.Zero;
private Surface _currentSurface = null;
private SurfaceView _view = null;
public RenderTarget(IPlatformHandle handle)
{
_view = (SurfaceView) handle;
}
public void Dispose()
{
if (_currentRenderTarget != IntPtr.Zero)
{
MethodTable.Instance.DisposeRenderTarget(_currentRenderTarget);
_currentRenderTarget = IntPtr.Zero;
GC.SuppressFinalize(this);
}
}
~RenderTarget()
{
Dispose();
}
public DrawingContext CreateDrawingContext()
{
var surface = _view.Holder.Surface;
if (surface == null)
throw new InvalidOperationException("Surface isn't available");
if (_currentSurface != surface)
{
_currentSurface = null;
if (_currentRenderTarget != IntPtr.Zero)
{
MethodTable.Instance.DisposeRenderTarget(_currentRenderTarget);
_currentRenderTarget = IntPtr.Zero;
}
_currentRenderTarget = MethodTable.Instance.CreateWindowRenderTarget(surface.Handle);
_currentSurface = surface;
}
return new DrawingContext(
new DrawingContextImpl(MethodTable.Instance.RenderTargetCreateRenderingContext(_currentRenderTarget)));
}
} }
*/
} }

26
src/Skia/Perspex.Skia.iOS/SkiaView.cs

@ -15,35 +15,25 @@ using UIKit;
namespace Perspex.Skia.iOS namespace Perspex.Skia.iOS
{ {
public abstract class SkiaView : UIView //GLKView // TODO: This implementation will be revised as part of HW acceleration work
// and we may use the GLKView as a base for the implementation.
//
public abstract class SkiaView : UIView
{ {
//[DllImport("__Internal")]
//static extern IntPtr GetPerspexEAGLContext();
bool _drawQueued; bool _drawQueued;
//CADisplayLink _link;
static EAGLContext GetContext() static EAGLContext GetContext()
{ {
/* No longer needed with SkiaSharp, but require a variant for HW accel
//Ensure initialization
MethodTable.Instance.SetOption((MethodTable.Option)0x10009999, IntPtr.Zero);
var ctx = GetPerspexEAGLContext();
var rv = Runtime.GetNSObject<EAGLContext>(ctx);
rv.DangerousRetain();
return rv;
*/
return null; return null;
} }
protected SkiaView(Action<Action> registerFrame) : base(UIScreen.MainScreen.ApplicationFrame) //, GetContext()) protected SkiaView(Action<Action> registerFrame) : base(UIScreen.MainScreen.ApplicationFrame)
{ {
registerFrame(OnFrame); registerFrame(OnFrame);
} }
protected SkiaView() : base(UIScreen.MainScreen.ApplicationFrame) //, GetContext()) protected SkiaView() : base(UIScreen.MainScreen.ApplicationFrame)
{ {
//(_link = CADisplayLink.Create(() => OnFrame())).AddToRunLoop(NSRunLoop.Main, NSRunLoop.NSDefaultRunLoopMode);
} }
protected void OnFrame() protected void OnFrame()
@ -51,10 +41,6 @@ namespace Perspex.Skia.iOS
if (_drawQueued) if (_drawQueued)
{ {
_drawQueued = false; _drawQueued = false;
// GLKView
//Display();
this.SetNeedsDisplay(); this.SetNeedsDisplay();
} }
} }

23
src/Skia/Perspex.Skia.iOS/iOSMethodTable.cs

@ -1,23 +0,0 @@
using System;
using System.Runtime.InteropServices;
using ObjCRuntime;
/* No longer needed with SkiaSharp
[assembly: LinkWith("Perspex.Skia.iOS.libperspesk_standalone.a", ForceLoad = true, SmartLink = true, IsCxx = true, Frameworks = "ImageIO MobileCoreServices CoreText")]
namespace Perspex.Skia
{
class MethodTableImpl : MethodTable
{
[DllImport("__Internal")]
static extern IntPtr GetPerspexMethodTable();
public MethodTableImpl() : base(GetPerspexMethodTable())
{
}
}
}
*/

27
src/Skia/Perspex.Skia/DrawingContextImpl.cs

@ -2,13 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using Perspex.Media; using Perspex.Media;
using Perspex.Media.Imaging; using Perspex.Media.Imaging;
using Perspex.RenderHelpers;
using SkiaSharp; using SkiaSharp;
using System.Linq; using System.Linq;
namespace Perspex.Skia namespace Perspex.Skia
{ {
unsafe class DrawingContextImpl : IDrawingContextImpl internal class DrawingContextImpl : IDrawingContextImpl
{ {
public SKCanvas Canvas { get; private set; } public SKCanvas Canvas { get; private set; }
@ -160,6 +159,8 @@ namespace Perspex.Skia
paint.StrokeMiter = (float)pen.MiterLimit; paint.StrokeMiter = (float)pen.MiterLimit;
// TODO: Implement Dash Style support
//
//if (pen.DashStyle?.Dashes != null) //if (pen.DashStyle?.Dashes != null)
//{ //{
// var dashes = pen.DashStyle.Dashes; // var dashes = pen.DashStyle.Dashes;
@ -191,7 +192,7 @@ namespace Perspex.Skia
} }
else else
{ {
// DrawRRect is not accesible in SkiaSharp yet. We should add that // TODO: DrawRRect (ore DrawRoundedRect) is not accesible in SkiaSharp yet. We should add that
// to SkiaSharp and initiate a PR.... // to SkiaSharp and initiate a PR....
Canvas.DrawRect(rc, paint); Canvas.DrawRect(rc, paint);
//Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint); //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
@ -210,7 +211,7 @@ namespace Perspex.Skia
} }
else else
{ {
// this does not appear to exist in SkiaSharp? // TODO: this does not exist in SkiaSharp yet
//throw new NotImplementedException(); //throw new NotImplementedException();
//Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint); //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
Canvas.DrawRect(rc, paint); Canvas.DrawRect(rc, paint);
@ -271,22 +272,4 @@ namespace Perspex.Skia
} }
} }
} }
// not sure we need this yet
internal class WindowDrawingContextImpl : DrawingContextImpl
{
WindowRenderTarget _target;
public WindowDrawingContextImpl(WindowRenderTarget target)
: base(target.Surface.Canvas)
{
_target = target;
}
public override void Dispose()
{
base.Dispose();
_target.Present();
}
}
} }

72
src/Skia/Perspex.Skia/FormattedTextImpl.cs

@ -22,7 +22,7 @@ namespace Perspex.Skia
Paint.IsAntialias = true; Paint.IsAntialias = true;
LineOffset = 0; LineOffset = 0;
//Replace 0 characters with zero-width spaces (200B) // Replace 0 characters with zero-width spaces (200B)
_text = _text.Replace((char)0, (char)0x200B); _text = _text.Replace((char)0, (char)0x200B);
} }
@ -108,16 +108,9 @@ namespace Perspex.Skia
public void SetForegroundBrush(IBrush brush, int startIndex, int length) public void SetForegroundBrush(IBrush brush, int startIndex, int length)
{ {
// Is this method even relevant now??? // TODO: we need an implementation here to properly support FormattedText
//
//var scb = brush as SolidColorBrush;
//if (scb != null)
//{
// Layout.Attributes.Insert(brushAttr);
//}
} }
void Rebuild() void Rebuild()
{ {
var length = _text.Length; var length = _text.Length;
@ -164,20 +157,13 @@ namespace Perspex.Skia
subString = _text.Substring(curOff); subString = _text.Substring(curOff);
// TODO: This method is not linking into SkiaSharp so we must use the RAW buffer version // TODO: This method is not linking into SkiaSharp so we must use the RAW buffer version for now
//measured = (int)Paint.BreakText(subString, constraint, out lineWidth) / 2; //measured = (int)Paint.BreakText(subString, constraint, out lineWidth) / 2;
bytes = Encoding.UTF8.GetBytes(subString); bytes = Encoding.UTF8.GetBytes(subString);
pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned); pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
pointer = pinnedArray.AddrOfPinnedObject(); pointer = pinnedArray.AddrOfPinnedObject();
// for some reason I have to pass nBytes * 2 // for some reason I have to pass nBytes * 2. I assume under the hood it expects Unicode/WChar??
measured = (int)Paint.BreakText(pointer, (IntPtr)(bytes.Length * 2), constraint, out lineWidth) / 2; measured = (int)Paint.BreakText(pointer, (IntPtr)(bytes.Length * 2), constraint, out lineWidth) / 2;
// some weird unicode byte issue again
//if(subString.Length % 2 == 1)
//{
// measured -= 1;
//}
pinnedArray.Free(); pinnedArray.Free();
if (measured == 0) if (measured == 0)
@ -192,20 +178,17 @@ namespace Perspex.Skia
if (nextChar != ' ') if (nextChar != ' ')
{ {
//Perform scan for the last space and end the line there // Perform scan for the last space and end the line there
for (int si = curOff + measured - 1; si > curOff; si--) for (int si = curOff + measured - 1; si > curOff; si--)
{ {
if (_text[si] == ' ') if (_text[si] == ' ')
{ {
measured = si - curOff; measured = si - curOff;
extraSkip = 1; extraSkip = 1;
//Rects[si] = SkRect();
break; break;
} }
} }
} }
} }
PerspexFormattedTextLine line = new PerspexFormattedTextLine(); PerspexFormattedTextLine line = new PerspexFormattedTextLine();
@ -218,7 +201,7 @@ namespace Perspex.Skia
if (line.Width < 0) if (line.Width < 0)
line.Width = _skiaRects[line.Start + line.Length - 1].Right; line.Width = _skiaRects[line.Start + line.Length - 1].Right;
//Build character rects // Build character rects
for (int i = line.Start; i < line.Start + line.Length; i++) for (int i = line.Start; i < line.Start + line.Length; i++)
{ {
float prevRight = 0; float prevRight = 0;
@ -241,7 +224,13 @@ namespace Perspex.Skia
_skiaLines.Add(line); _skiaLines.Add(line);
curY += lineHeight; // + mLeading; curY += lineHeight;
// TODO: We may want to consider adding Leading to the vertical line spacing but for now
// it appears to make no difference. Revisit as part of FormattedText improvements.
//
//curY += mLeading;
curOff += measured + extraSkip; curOff += measured + extraSkip;
} }
@ -260,10 +249,14 @@ namespace Perspex.Skia
} }
for (var c = 0; c < _text.Length; c++) for (var c = 0; c < _text.Length; c++)
{
_rects.Add(_skiaRects[c].ToPerspexRect()); _rects.Add(_skiaRects[c].ToPerspexRect());
}
if (_skiaLines.Count == 0) if (_skiaLines.Count == 0)
{
_size = new Size(); _size = new Size();
}
else else
{ {
var lastLine = _skiaLines[_skiaLines.Count - 1]; var lastLine = _skiaLines[_skiaLines.Count - 1];
@ -275,38 +268,37 @@ namespace Perspex.Skia
{ {
SKPaint paint = Paint; SKPaint paint = Paint;
/* This originated from Native code, it might be useful /* TODO: This originated from Native code, it might be useful for debugging character positions as
//Debugging code for character positions * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when
* not needed anymore.
SkPaint dpaint; SkPaint dpaint;
ctx->Canvas->save(); ctx->Canvas->save();
ctx->Canvas->translate(origin.fX, origin.fY); ctx->Canvas->translate(origin.fX, origin.fY);
for (int c = 0; c < Lines.size(); c++) for (int c = 0; c < Lines.size(); c++)
{ {
dpaint.setARGB(255, 0, 0, 0); dpaint.setARGB(255, 0, 0, 0);
SkRect rc; SkRect rc;
rc.fLeft = 0; rc.fLeft = 0;
rc.fTop = Lines[c].Top; rc.fTop = Lines[c].Top;
rc.fRight = Lines[c].Width; rc.fRight = Lines[c].Width;
rc.fBottom = rc.fTop + LineOffset; rc.fBottom = rc.fTop + LineOffset;
ctx->Canvas->drawRect(rc, dpaint); ctx->Canvas->drawRect(rc, dpaint);
} }
for (int c = 0; c < Length; c++) for (int c = 0; c < Length; c++)
{ {
dpaint.setARGB(255, c % 10 * 125 / 10 + 125, (c * 7) % 10 * 250 / 10, (c * 13) % 10 * 250 / 10); dpaint.setARGB(255, c % 10 * 125 / 10 + 125, (c * 7) % 10 * 250 / 10, (c * 13) % 10 * 250 / 10);
dpaint.setStyle(SkPaint::kFill_Style); dpaint.setStyle(SkPaint::kFill_Style);
ctx->Canvas->drawRect(Rects[c], dpaint); ctx->Canvas->drawRect(Rects[c], dpaint);
} }
ctx->Canvas->restore(); ctx->Canvas->restore();
*/ */
// These seems to vertically align the text properly
var yOffset = (LineOffset); // + 1) / 2;
for (int c = 0; c < _skiaLines.Count; c++) for (int c = 0; c < _skiaLines.Count; c++)
{ {
PerspexFormattedTextLine line = _skiaLines[c]; PerspexFormattedTextLine line = _skiaLines[c];
var subString = _text.Substring(line.Start, line.Length); var subString = _text.Substring(line.Start, line.Length);
canvas.DrawText(subString, origin.X, origin.Y + line.Top + yOffset, paint); canvas.DrawText(subString, origin.X, origin.Y + line.Top + LineOffset, paint);
} }
} }

240
src/Skia/Perspex.Skia/MethodTable.cs

@ -1,240 +0,0 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Perspex.Media;
// ReSharper disable InconsistentNaming
namespace Perspex.Skia
{
/* No longer needed with SkiaSharp
unsafe abstract class MethodTable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _CreateWindowRenderTarget(IntPtr nativeHandle);
public _CreateWindowRenderTarget CreateWindowRenderTarget;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _RenderTargetCreateRenderingContext(IntPtr target);
public _RenderTargetCreateRenderingContext RenderTargetCreateRenderingContext;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DisposeRenderTarget(IntPtr target);
public _DisposeRenderTarget DisposeRenderTarget;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DisposeRenderingContext(IntPtr ctx);
public _DisposeRenderingContext DisposeRenderingContext;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawRectangle(IntPtr ctx, void* brush, ref SkRect rect, float borderRadius);
public _DrawRectangle DrawRectangle;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _PushClip(IntPtr ctx, ref SkRect rect);
public _PushClip PushClip;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _PopClip(IntPtr ctx);
public _PopClip PopClip;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _SetTransform(IntPtr ctx, void* matrix6);
public _SetTransform SetTransformNative;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawLine(IntPtr ctx, void* brush, float x1, float y1, float x2, float y2);
public _DrawLine DrawLine;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _CreatePath(SkiaGeometryElement[] elements, int count, out SkRect bounds);
public _CreatePath CreatePath;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DisposePath(IntPtr handle);
public _DisposePath DisposePath;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _TransformPath(IntPtr path, void* matrix6);
public _TransformPath TransformPathNative;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawGeometry(IntPtr ctx, IntPtr path, void* fill, void* stroke, bool useEvenOdd);
public _DrawGeometry DrawGeometry;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DestroySkData(IntPtr handle);
public _DestroySkData DestroySkData;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool _LoadImage(byte[] data, int len, out IntPtr image, out int width, out int height);
public _LoadImage LoadImage;
public enum SkiaImageType
{
Png,Gif,Jpeg
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _SaveImage(IntPtr image, SkiaImageType type, int quality);
public _SaveImage SaveImage;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawImage(IntPtr ctx, IntPtr image, float opacity, ref SkRect srcRect, ref SkRect destRect);
public _DrawImage DrawImage;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _CreateRenderTargetBitmap(int width, int height);
public _CreateRenderTargetBitmap CreateRenderTargetBitmap;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DisposeImage(IntPtr image);
public _DisposeImage DisposeImage;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int _GetSkDataSize(IntPtr data);
public _GetSkDataSize GetSkDataSize;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _ReadSkData(IntPtr data, byte[] buffer, int count);
public _ReadSkData ReadSkData;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate NativeDrawingContextSettings* _GetDrawingContextSettingsPtr(IntPtr ctx);
public _GetDrawingContextSettingsPtr GetDrawingContextSettingsPtr;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _CreateTypeface(void* name, int style);
public _CreateTypeface CreateTypeface;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _CreateFormattedText(void*utf16, int len, IntPtr typeface, float fontSize, TextAlignment align, NativeFormattedText** shared);
public _CreateFormattedText CreateFormattedText;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _RebuildFormattedText(IntPtr handle);
public _RebuildFormattedText RebuildFormattedText;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DestroyFormattedText(IntPtr handle);
public _DestroyFormattedText DestroyFormattedText;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawFormattedText(IntPtr ctx, void* brush, IntPtr text, float x, float y);
public _DrawFormattedText DrawFormattedText;
public enum Option
{
ForceSoftware = 0
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _SetOption(Option option, IntPtr value);
public _SetOption SetOption;
private static readonly Type[] TableOrder = new Type[]
{
typeof (_CreateWindowRenderTarget),
typeof (_DisposeRenderTarget),
typeof (_RenderTargetCreateRenderingContext),
typeof (_DisposeRenderingContext),
typeof (_DrawRectangle),
typeof (_PushClip),
typeof (_PopClip),
typeof (_SetTransform),
typeof (_DrawLine),
typeof (_CreatePath),
typeof (_DisposePath),
typeof (_DrawGeometry),
typeof (_GetSkDataSize),
typeof (_ReadSkData),
typeof (_DestroySkData),
typeof (_LoadImage),
typeof (_SaveImage),
typeof (_DrawImage),
typeof (_CreateRenderTargetBitmap),
typeof (_DisposeImage),
typeof (_GetDrawingContextSettingsPtr),
typeof (_CreateTypeface),
typeof (_CreateFormattedText),
typeof (_RebuildFormattedText),
typeof (_DestroyFormattedText),
typeof (_DrawFormattedText),
typeof (_SetOption),
typeof (_TransformPath)
};
void ConvertMatrix(Matrix value, float* target)
{
target[0] = (float)value.M11;
target[1] = (float)value.M21;
target[2] = (float)value.M31;
target[3] = (float)value.M12;
target[4] = (float)value.M22;
target[5] = (float)value.M32;
}
public unsafe IntPtr TransformPath(IntPtr path, Matrix matrix)
{
var tmp = stackalloc float[6];
ConvertMatrix(matrix, tmp);
return TransformPathNative(path, tmp);
}
public unsafe void SetTransform(IntPtr ctx, Matrix matrix)
{
var tmp = stackalloc float[6];
ConvertMatrix(matrix, tmp);
SetTransformNative(ctx, tmp);
}
protected MethodTable(IntPtr methodTable)
{
var dic = typeof (MethodTable).GetFields().ToDictionary(f => f.FieldType, f => f);
for (var c = 0; c < TableOrder.Length; c++)
{
IntPtr pMethod = Marshal.ReadIntPtr(methodTable, IntPtr.Size*c);
var t = TableOrder[c];
dic[t].SetValue(this, Marshal.GetDelegateForFunctionPointer(pMethod, t));
}
}
public static readonly MethodTable Instance = new MethodTableImpl();
}
*/
}

115
src/Skia/Perspex.Skia/NativeBrush.cs

@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Perspex.Media;
namespace Perspex.Skia
{
/* No longer needed with SkiaSharp
internal enum NativeBrushType
{
Solid,
LinearGradient,
RadialGradient,
Image
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct NativeBrush
{
public const int MaxGradientStops = 1024;
public const int MaxDashCount = 1024;
public NativeBrushType Type;
public double Opacity;
public uint Color;
//Strokes
public bool Stroke;
public float StrokeThickness;
public PenLineJoin StrokeLineJoin;
public float StrokeMiterLimit;
public int StrokeDashCount;
public float StrokeDashOffset;
public PenLineCap StrokeLineCap;
//Gradients
public int GradientStopCount;
public GradientSpreadMethod GradientSpreadMethod;
public SkiaPoint GradientStartPoint, GradientEndPoint;
public float GradientRadius;
//Image Brush
public IntPtr Bitmap;
public TileMode BitmapTileMode;
public SkiaPoint BitmapTranslation;
//Blobs
public fixed uint GradientStopColors [MaxGradientStops];
public fixed float GradientStops [MaxGradientStops];
public fixed float StrokeDashes [MaxDashCount];
public void Reset()
{
Type = NativeBrushType.Solid;
Opacity = 1f;
Color = 0;
Stroke = false;
StrokeThickness = 1;
GradientStopCount = 0;
StrokeDashCount = 0;
StrokeLineCap = PenLineCap.Flat;
}
}
unsafe class NativeBrushContainer : IDisposable
{
private readonly NativeBrushPool _pool;
public NativeBrush* Brush;
readonly List<IDisposable> _disposables = new List<IDisposable>();
public NativeBrushContainer(NativeBrushPool pool)
{
_pool = pool;
Brush = (NativeBrush*) Marshal.AllocHGlobal(Marshal.SizeOf(typeof (NativeBrush))).ToPointer();
Brush->Reset();
}
public void AddDisposable(IDisposable disp)
{
_disposables.Add(disp);
}
public void Dispose()
{
foreach (var disp in _disposables)
disp.Dispose();
_disposables.Clear();
Brush->Reset();
_pool?.Return(this);
}
}
class NativeBrushPool
{
public static NativeBrushPool Instance { get; } = new NativeBrushPool();
readonly Stack<NativeBrushContainer> _pool = new Stack<NativeBrushContainer>();
public void Return(NativeBrushContainer c)
{
_pool.Push(c);
}
public NativeBrushContainer Get()
{
if (_pool.Count == 0)
return new NativeBrushContainer(this);
return _pool.Pop();
}
}
*/
}

12
src/Skia/Perspex.Skia/NativeDrawingContextSettings.cs

@ -1,12 +0,0 @@
using System.Runtime.InteropServices;
/* No longer needed with SkiaSharp
namespace Perspex.Skia
{
[StructLayout(LayoutKind.Sequential)]
struct NativeDrawingContextSettings
{
public double Opacity;
}
}
*/

27
src/Skia/Perspex.Skia/NativeFormattedText.cs

@ -1,27 +0,0 @@
using System.Runtime.InteropServices;
/* No longer needed with SkiaSharp
namespace Perspex.Skia
{
[StructLayout(LayoutKind.Sequential)]
unsafe struct NativeFormattedText
{
public float WidthConstraint;
public int LineCount;
public NativeFormattedTextLine* Lines;
public SkRect* Bounds;
};
[StructLayout(LayoutKind.Sequential)]
unsafe struct NativeFormattedTextLine
{
public float Top;
public int Start;
public int Length;
public float Height;
public float Width;
};
}
*/

1
src/Skia/Perspex.Skia/Perspex.Skia.projitems

@ -18,6 +18,7 @@
<Compile Include="$(MSBuildThisFileDirectory)SkiaSharpExtensions.cs" /> <Compile Include="$(MSBuildThisFileDirectory)SkiaSharpExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StreamGeometryImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)StreamGeometryImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TypefaceCache.cs" /> <Compile Include="$(MSBuildThisFileDirectory)TypefaceCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowDrawingContextImpl.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="$(MSBuildThisFileDirectory)readme.md" /> <None Include="$(MSBuildThisFileDirectory)readme.md" />

110
src/Skia/Perspex.Skia/PerspexHandleHolder.cs

@ -1,110 +0,0 @@
using System;
/* No longer needed with SkiaSharp
namespace Perspex.Skia
{
abstract class PerspexHandleHolder : IDisposable
{
private readonly IntPtr _handle;
public IntPtr Handle
{
get
{
CheckDisposed();
return _handle;
}
}
public bool IsDisposed { get; private set; }
public void CheckDisposed()
{
if (IsDisposed)
throw new ObjectDisposedException(GetType().FullName);
}
protected PerspexHandleHolder(IntPtr handle)
{
_handle = handle;
}
protected abstract void Delete(IntPtr handle);
public void Dispose()
{
if(IsDisposed)
return;
IsDisposed = true;
Delete(_handle);
GC.SuppressFinalize(this);
}
~PerspexHandleHolder()
{
Dispose();
}
}
class RefCountable<T> : IDisposable where T : PerspexHandleHolder
{
class Shared
{
public readonly T Target;
private int _refCount = 1;
public Shared(T target)
{
Target = target;
}
public void AddRef() => _refCount++;
public void Release()
{
_refCount--;
if (_refCount <= 0)
Target.Dispose();
}
}
public bool IsDisposed => _shared == null;
private Shared _shared;
public void CheckDisposed()
{
if (IsDisposed)
throw new ObjectDisposedException(GetType().FullName);
}
public IntPtr Handle
{
get
{
CheckDisposed();
return _shared.Target.Handle;
}
}
public RefCountable(T handle)
{
_shared = new Shared(handle);
}
public RefCountable(RefCountable<T> other)
{
other._shared.Target.CheckDisposed();
other._shared.AddRef();
_shared = other._shared;
}
public RefCountable<T> Clone() => new RefCountable<T>(this);
public void Dispose()
{
_shared?.Release();
_shared = null;
}
}
}
*/

24
src/Skia/Perspex.Skia/PlatformRenderInterface.cs

@ -30,16 +30,16 @@ namespace Perspex.Skia
IBitmapImpl LoadBitmap(byte[] data) IBitmapImpl LoadBitmap(byte[] data)
{ {
var bitmap = new SKBitmap(); var bitmap = new SKBitmap();
if(!SKImageDecoder.DecodeMemory(data, bitmap)) if (!SKImageDecoder.DecodeMemory(data, bitmap))
{ {
throw new ArgumentException("Unable to load bitmap from provided data"); throw new ArgumentException("Unable to load bitmap from provided data");
} }
return new BitmapImpl(bitmap); return new BitmapImpl(bitmap);
} }
public IBitmapImpl LoadBitmap(System.IO.Stream stream) public IBitmapImpl LoadBitmap(System.IO.Stream stream)
{ {
using (var sr = new BinaryReader(stream)) using (var sr = new BinaryReader(stream))
{ {
@ -62,9 +62,9 @@ namespace Perspex.Skia
return new BitmapImpl(width, height); return new BitmapImpl(width, height);
} }
public IRenderTarget CreateRenderer(IPlatformHandle handle) public IRenderTarget CreateRenderer(IPlatformHandle handle)
{ {
return new WindowRenderTarget(handle.Handle); return new WindowRenderTarget(handle.Handle);
} }
} }
} }

13
src/Skia/Perspex.Skia/RenderTarget.cs

@ -17,22 +17,20 @@ using Perspex.Win32.Interop;
namespace Perspex.Skia namespace Perspex.Skia
{ {
internal class RenderTarget : IRenderTarget internal partial class RenderTarget : IRenderTarget
{ {
public SKSurface Surface { get; protected set; } public SKSurface Surface { get; protected set; }
//protected override void Delete(IntPtr handle) => MethodTable.Instance.DisposeRenderTarget(handle);
public virtual DrawingContext CreateDrawingContext() public virtual DrawingContext CreateDrawingContext()
{ {
return return
new DrawingContext( new DrawingContext(
new DrawingContextImpl(Surface.Canvas)); // MethodTable.Instance.RenderTargetCreateRenderingContext(Handle))); new DrawingContextImpl(Surface.Canvas));
} }
public void Dispose() public void Dispose()
{ {
//throw new NotImplementedException(); // Nothing to do here.
} }
} }
@ -69,7 +67,7 @@ namespace Perspex.Skia
} }
#endif #endif
void FixSize() private void FixSize()
{ {
int width, height; int width, height;
GetPlatformWindowSize(_hwnd, out width, out height); GetPlatformWindowSize(_hwnd, out width, out height);
@ -91,7 +89,6 @@ namespace Perspex.Skia
_bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul); _bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul);
//bitmap.LockPixels();
IntPtr length; IntPtr length;
var pixels = _bitmap.GetPixels(out length); var pixels = _bitmap.GetPixels(out length);
@ -99,7 +96,7 @@ namespace Perspex.Skia
Surface = SKSurface.Create(_bitmap.Info, pixels, _bitmap.RowBytes); Surface = SKSurface.Create(_bitmap.Info, pixels, _bitmap.RowBytes);
} }
void GetPlatformWindowSize(IntPtr hwnd, out int w, out int h) private void GetPlatformWindowSize(IntPtr hwnd, out int w, out int h)
{ {
#if __IOS__ #if __IOS__
var bounds = GetApplicationFrame(); var bounds = GetApplicationFrame();

31
src/Skia/Perspex.Skia/SkRect.cs

@ -1,31 +0,0 @@
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
/* No longer needed with SkiaSharp
namespace Perspex.Skia
{
[StructLayout(LayoutKind.Sequential)]
struct SkRect
{
public float Left, Top, Right, Bottom;
public static SkRect FromRect(Rect rc)
{
return new SkRect()
{
Left = (float) rc.X,
Top = (float) rc.Y,
Right = (float) rc.Right,
Bottom = (float) rc.Bottom
};
}
public Rect ToRect() => new Rect(Left, Top, Right - Left, Bottom - Top);
}
}
*/

5
src/Skia/Perspex.Skia/SkiaPlatform.cs

@ -31,8 +31,9 @@ namespace Perspex.Skia
{ {
s_forceSoftwareRendering = value; s_forceSoftwareRendering = value;
// Do we still need this with SkiaSharp?? // TODO: I left this property here as place holder. Do we still need the ability to Force software rendering?
//MethodTable.Instance.SetOption(MethodTable.Option.ForceSoftware, new IntPtr(value ? 1 : 0)); // Is it even possible with SkiaSharp? Perhaps kekekes can answer as part of the HW accel work.
//
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

33
src/Skia/Perspex.Skia/SkiaPoint.cs

@ -1,33 +0,0 @@
using System.Runtime.InteropServices;
/* No longer needed with SkiaSharp
namespace Perspex.Skia
{
[StructLayout(LayoutKind.Sequential)]
struct SkiaPoint
{
public float X, Y;
public SkiaPoint(float x, float y)
{
X = x;
Y = y;
}
public SkiaPoint(double x, double y)
{
X = (float)x;
Y = (float)y;
}
public SkiaPoint(Point p) : this(p.X, p.Y)
{
}
public static implicit operator SkiaPoint(Point pt) => new SkiaPoint(pt);
}
}
*/

11
src/Skia/Perspex.Skia/StreamGeometryImpl.cs

@ -85,7 +85,6 @@ namespace Perspex.Skia
private readonly StreamGeometryImpl _geometryImpl; private readonly StreamGeometryImpl _geometryImpl;
private SKPath _path; private SKPath _path;
//readonly List<SkiaGeometryElement> _elements = new List<SkiaGeometryElement>();
Point _currentPoint; Point _currentPoint;
public StreamContext(StreamGeometryImpl geometryImpl) public StreamContext(StreamGeometryImpl geometryImpl)
{ {
@ -95,16 +94,13 @@ namespace Perspex.Skia
public void Dispose() public void Dispose()
{ {
// Not sure what we need to do here.... // TODO: Not sure what we need to do here. This code left here for reference.
//
// //throw new NotImplementedException();
// var arr = _elements.ToArray(); // var arr = _elements.ToArray();
// SkRect rc; // SkRect rc;
// _path?.Dispose(); // _path?.Dispose();
// _path = new SKPath(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc))); // _path = new SKPath(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc)));
// _geometryImpl.ApplyTransform(); // _geometryImpl.ApplyTransform();
// _geometryImpl.Bounds = rc.ToRect(); // _geometryImpl.Bounds = rc.ToRect();
SKRect rc; SKRect rc;
@ -116,9 +112,6 @@ namespace Perspex.Skia
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection) public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
//ArcToHelper.ArcTo(this, _currentPoint, point, size, rotationAngle, isLargeArc, sweepDirection);
//_currentPoint = point;
} }
public void BeginFigure(Point startPoint, bool isFilled) public void BeginFigure(Point startPoint, bool isFilled)

21
src/Skia/Perspex.Skia/WindowDrawingContextImpl.cs

@ -0,0 +1,21 @@

namespace Perspex.Skia
{
// not sure we need this yet
internal class WindowDrawingContextImpl : DrawingContextImpl
{
WindowRenderTarget _target;
public WindowDrawingContextImpl(WindowRenderTarget target)
: base(target.Surface.Canvas)
{
_target = target;
}
public override void Dispose()
{
base.Dispose();
_target.Present();
}
}
}

7
src/Skia/Perspex.Skia/readme.md

@ -35,7 +35,12 @@ Android
iOS iOS
- Get GLView working again. See HW above - Get GLView working again. See HW above
Win32
- Cleanup the unmanaged methods (BITMAPINFO) if possible
General General
- Cleanup/eliminate obsolete files - Cleanup/eliminate obsolete files
- Finish cleanup of the many Test Applications - Finish cleanup of the many Test Applications
- Get Skia Unit Tests passing - Get Skia Unit Tests passing

18
src/Windows/Perspex.Win32/SystemDialogImpl.cs

@ -40,23 +40,23 @@ namespace Perspex.Win32
var filterBuffer = new char[filters.Length]; var filterBuffer = new char[filters.Length];
filters.CopyTo(0, filterBuffer, 0, filterBuffer.Length); filters.CopyTo(0, filterBuffer, 0, filterBuffer.Length);
var defExt = (dialog as SaveFileDialog)?.DefaultExtension.ToArray(); var defExt = (dialog as SaveFileDialog)?.DefaultExtension.ToArray();
var fileBuffer = new char[256]; var fileBuffer = new char[256];
dialog.InitialFileName?.CopyTo(0, fileBuffer, 0, dialog.InitialFileName.Length); dialog.InitialFileName?.CopyTo(0, fileBuffer, 0, dialog.InitialFileName.Length);
string userSelectedExt = null; string userSelectedExt = null;
var title = dialog.Title.ToArray(); var title = dialog.Title.ToArray();
var initialDir = dialog.InitialDirectory.ToArray(); var initialDir = dialog.InitialDirectory.ToArray();
fixed (char* pFileBuffer = fileBuffer) fixed (char* pFileBuffer = fileBuffer)
fixed (char* pFilterBuffer = filterBuffer) fixed (char* pFilterBuffer = filterBuffer)
fixed (char* pDefExt = defExt) fixed (char* pDefExt = defExt)
fixed (char* pInitDir = initialDir) fixed (char* pInitDir = initialDir)
fixed (char* pTitle = title) fixed (char* pTitle = title)
{ {
var ofn = new UnmanagedMethods.OpenFileName() var ofn = new UnmanagedMethods.OpenFileName()
{ {
hwndOwner = hWnd, hwndOwner = hWnd,
hInstance = IntPtr.Zero, hInstance = IntPtr.Zero,
lCustData = IntPtr.Zero, lCustData = IntPtr.Zero,
@ -124,8 +124,8 @@ namespace Perspex.Win32
!userSelectedExt.Contains("*")) !userSelectedExt.Contains("*"))
dir = Path.ChangeExtension(dir, userSelectedExt); dir = Path.ChangeExtension(dir, userSelectedExt);
} }
return new[] {dir}; return new[] { dir };
} }
return files.Select(f => Path.Combine(dir, f)).ToArray(); return files.Select(f => Path.Combine(dir, f)).ToArray();
@ -133,7 +133,7 @@ namespace Perspex.Win32
} }
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
{ {
return Task.Factory.StartNew(() => return Task.Factory.StartNew(() =>
{ {
string result = string.Empty; string result = string.Empty;
@ -177,7 +177,7 @@ namespace Perspex.Win32
{ {
try try
{ {
result = Marshal.PtrToStringAuto(pszString); result = Marshal.PtrToStringAuto(pszString);
} }
finally finally
{ {

2
src/iOS/Perspex.iOS/Perspex.iOS.csproj

@ -39,11 +39,11 @@
<Compile Include="Extensions.cs" /> <Compile Include="Extensions.cs" />
<Compile Include="iOSPlatform.cs" /> <Compile Include="iOSPlatform.cs" />
<Compile Include="PerspexView.cs" /> <Compile Include="PerspexView.cs" />
<Compile Include="PerspexAppDelegate.cs" />
<Compile Include="PlatformSettings.cs" /> <Compile Include="PlatformSettings.cs" />
<Compile Include="PlatformThreadingInterface.cs" /> <Compile Include="PlatformThreadingInterface.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Specific\KeyboardEventsHelper.cs" /> <Compile Include="Specific\KeyboardEventsHelper.cs" />
<Compile Include="WindowingPlatformImpl.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Perspex.Animation\Perspex.Animation.csproj"> <ProjectReference Include="..\..\Perspex.Animation\Perspex.Animation.csproj">

77
src/iOS/Perspex.iOS/PerspexAppDelegate.cs

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Perspex.Controls.Platform;
using Perspex.Input;
using Perspex.Input.Platform;
using Perspex.Platform;
using Perspex.Shared.PlatformSupport;
using Perspex.Skia;
using UIKit;
/* No Longer needed
namespace Perspex.iOS
{
public class PerspexAppDelegate : UIApplicationDelegate
{
static bool _initialized = false;
internal static MouseDevice MouseDevice;
internal static KeyboardDevice KeyboardDevice;
protected void InitPerspex(Type appType)
{
if(_initialized)
return;
_initialized = true;
var window = new UIWindow(UIScreen.MainScreen.Bounds);
var controller = new PerspexViewController(window);
window.RootViewController = controller;
window.MakeKeyAndVisible();
Application.RegisterPlatformCallback(() =>
{
MouseDevice = new MouseDevice();
KeyboardDevice = new KeyboardDevice();
SharedPlatform.Register(appType.Assembly);
PerspexLocator.CurrentMutable
.Bind<IClipboard>().ToTransient<Clipboard>()
//.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<IStandardCursorFactory>().ToTransient<CursorFactory>()
.Bind<IKeyboardDevice>().ToConstant(KeyboardDevice)
.Bind<IMouseDevice>().ToConstant(MouseDevice)
.Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
.Bind<IPlatformThreadingInterface>().ToConstant(PlatformThreadingInterface.Instance)
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatform(controller.PerspexView));
SkiaPlatform.Initialize();
});
}
class WindowingPlatform : IWindowingPlatform
{
private readonly IWindowImpl _window;
public WindowingPlatform(IWindowImpl window)
{
_window = window;
}
public IWindowImpl CreateWindow()
{
return _window;
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
}
}
}
}
*/

30
src/iOS/Perspex.iOS/PerspexView.cs

@ -57,8 +57,8 @@ namespace Perspex.iOS
(_controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft (_controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft
|| _controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeRight); || _controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeRight);
// Bounds here (if top level) needs to correspond with the rendertarget // Bounds here (if top level) needs to correspond with the rendertarget
var frame = UIScreen.MainScreen.Bounds; var frame = UIScreen.MainScreen.Bounds;
if (needFlip) if (needFlip)
Frame = new CGRect(frame.Y, frame.X, frame.Height, frame.Width); Frame = new CGRect(frame.Y, frame.X, frame.Height, frame.Width);
else else
@ -76,14 +76,14 @@ namespace Perspex.iOS
public IPlatformHandle Handle => PerspexPlatformHandle; public IPlatformHandle Handle => PerspexPlatformHandle;
public double Scaling public double Scaling
{ {
get get
{ {
// This does not appear to make any difference, but on iOS we // This does not appear to make any difference, but on iOS we
// have Retina (x2) and we probably want this eventually // have Retina (x2) and we probably want this eventually
return 1; //UIScreen.MainScreen.Scale; return 1; //UIScreen.MainScreen.Scale;
} }
} }
public WindowState WindowState public WindowState WindowState
{ {
@ -169,7 +169,7 @@ namespace Perspex.iOS
Input?.Invoke(new RawMouseEventArgs( Input?.Invoke(new RawMouseEventArgs(
iOSPlatform.MouseDevice, iOSPlatform.MouseDevice,
(uint) touch.Timestamp, (uint)touch.Timestamp,
_inputRoot, _inputRoot,
RawMouseEventType.LeftButtonUp, RawMouseEventType.LeftButtonUp,
location, location,
@ -185,10 +185,10 @@ namespace Perspex.iOS
{ {
var location = touch.LocationInView(this).ToPerspex(); var location = touch.LocationInView(this).ToPerspex();
_touchLastPoint = location; _touchLastPoint = location;
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot, Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot,
RawMouseEventType.Move, location, InputModifiers.None)); RawMouseEventType.Move, location, InputModifiers.None));
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot, Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot,
RawMouseEventType.LeftButtonDown, location, InputModifiers.None)); RawMouseEventType.LeftButtonDown, location, InputModifiers.None));
} }
} }
@ -200,7 +200,7 @@ namespace Perspex.iOS
{ {
var location = touch.LocationInView(this).ToPerspex(); var location = touch.LocationInView(this).ToPerspex();
if (iOSPlatform.MouseDevice.Captured != null) if (iOSPlatform.MouseDevice.Captured != null)
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot, Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot,
RawMouseEventType.Move, location, InputModifiers.LeftMouseButton)); RawMouseEventType.Move, location, InputModifiers.LeftMouseButton));
else else
{ {
@ -208,7 +208,7 @@ namespace Perspex.iOS
double correction = 0.02; double correction = 0.02;
Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp,
_inputRoot, location, (location - _touchLastPoint)* correction, InputModifiers.LeftMouseButton)); _inputRoot, location, (location - _touchLastPoint) * correction, InputModifiers.LeftMouseButton));
} }
_touchLastPoint = location; _touchLastPoint = location;
} }

33
src/iOS/Perspex.iOS/WindowingPlatformImpl.cs

@ -0,0 +1,33 @@
using Perspex.Platform;
using System;
namespace Perspex.iOS
{
// This is somewhat generic, could probably put this elsewhere. But I don't think
// it should part of the iOS App Delegate
//
class WindowingPlatformImpl : IWindowingPlatform
{
private readonly IWindowImpl _window;
public WindowingPlatformImpl(IWindowImpl window)
{
_window = window;
}
public IWindowImpl CreateWindow()
{
return _window;
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
}
}
}

41
src/iOS/Perspex.iOS/iOSPlatform.cs

@ -18,8 +18,7 @@ namespace Perspex
return app; return app;
} }
// I wish I could merge this with the SkiaPlatform itself. Might be possible // TODO: Can we merge this with UseSkia somehow once HW/platform cleanup is done?
// once we switch to SkiaSharp
public static AppT UseSkiaViewHost<AppT>(this AppT app) where AppT : Application public static AppT UseSkiaViewHost<AppT>(this AppT app) where AppT : Application
{ {
var window = new UIWindow(UIScreen.MainScreen.Bounds); var window = new UIWindow(UIScreen.MainScreen.Bounds);
@ -28,7 +27,7 @@ namespace Perspex
window.MakeKeyAndVisible(); window.MakeKeyAndVisible();
PerspexLocator.CurrentMutable PerspexLocator.CurrentMutable
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatform(controller.PerspexView)); .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformImpl(controller.PerspexView));
SkiaPlatform.Initialize(); SkiaPlatform.Initialize();
@ -40,45 +39,15 @@ namespace Perspex
// Asset loading searches our own assembly? // Asset loading searches our own assembly?
var loader = new AssetLoader(assembly); var loader = new AssetLoader(assembly);
PerspexLocator.CurrentMutable.Bind<IAssetLoader>().ToConstant(loader); PerspexLocator.CurrentMutable.Bind<IAssetLoader>().ToConstant(loader);
return app; return app;
} }
// This is somewhat generic, could probably put this elsewhere. But I don't think
// it should part of the iOS App Delegate
//
class WindowingPlatform : IWindowingPlatform
{
private readonly IWindowImpl _window;
public WindowingPlatform(IWindowImpl window)
{
_window = window;
}
public IWindowImpl CreateWindow()
{
return _window;
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
}
}
} }
} }
namespace Perspex.iOS namespace Perspex.iOS
{ {
// TODO: Perhaps we should make this class handle all these interfaces directly, like we // TODO: Perhaps we should make this class handle all these interfaces directly, like we
// do for Win32 and Gtk // do for Win32 and Gtk platforms
// //
public class iOSPlatform //: IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform public class iOSPlatform //: IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
{ {
@ -90,12 +59,10 @@ namespace Perspex.iOS
MouseDevice = new MouseDevice(); MouseDevice = new MouseDevice();
KeyboardDevice = new KeyboardDevice(); KeyboardDevice = new KeyboardDevice();
// refactored
//SharedPlatform.Register(appType.Assembly);
PerspexLocator.CurrentMutable PerspexLocator.CurrentMutable
.Bind<IPclPlatformWrapper>().ToSingleton<PclPlatformWrapper>() .Bind<IPclPlatformWrapper>().ToSingleton<PclPlatformWrapper>()
.Bind<IClipboard>().ToTransient<Clipboard>() .Bind<IClipboard>().ToTransient<Clipboard>()
// TODO: what does this look like for iOS??
//.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>() //.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<IStandardCursorFactory>().ToTransient<CursorFactory>() .Bind<IStandardCursorFactory>().ToTransient<CursorFactory>()
.Bind<IKeyboardDevice>().ToConstant(KeyboardDevice) .Bind<IKeyboardDevice>().ToConstant(KeyboardDevice)

56
src/iOS/Perspex.iOSTestApplication/AppDelegate.cs

@ -27,65 +27,17 @@ namespace Perspex.iOSTestApplication
// //
public override bool FinishedLaunching(UIApplication uiapp, NSDictionary options) public override bool FinishedLaunching(UIApplication uiapp, NSDictionary options)
{ {
var app = new App(); var app = new App()
.UseiOS()
.UseSkiaViewHost()
.UseSkia();
app.UseiOS();
app.UseSkiaViewHost();
app.UseSkia();
// looking for this URI fails: "TestApplication.github_icon.png"
var asm = typeof(App).Assembly; var asm = typeof(App).Assembly;
app.UseAssetAssembly(asm); app.UseAssetAssembly(asm);
//MainWindow.RootNamespace = "Perspex.iOSTestApplication";
//var window = MainWindow.Create();
////var window = Create();
//window.Show();
//app.Run(window);
app.Run(); app.Run();
return true; return true;
} }
// This provides a simple UI tree for testing input handling
public static Window Create()
{
Window window = new Window
{
Title = "Perspex Test Application",
//Width = 900,
//Height = 480,
Background = Brushes.Red,
Content = new StackPanel
{
Margin = new Thickness(30),
Background = Brushes.Yellow,
Children = new Controls.Controls
{
new TextBlock
{
Text = "TEXT BLOCK",
Width = 300,
Height = 40,
Background = Brushes.White,
Foreground = Brushes.Black
},
new Button
{
Content = "BUTTON",
Width = 150,
Height = 40,
Background = Brushes.LightGreen,
Foreground = Brushes.Black
}
}
}
};
return window;
}
} }

Loading…
Cancel
Save