diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 36238efc7c..590230e7a2 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -211,6 +211,10 @@
{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
Perspex.Themes.Default
+
+ {925dd807-b651-475f-9f7c-cbeb974ce43d}
+ Perspex.Skia.Desktop
+
{3e908f67-5543-4879-a1dc-08eace79b3cd}
Perspex.Direct2D1
diff --git a/samples/ControlCatalog/Program.cs b/samples/ControlCatalog/Program.cs
index d01a6aa11b..e1118d2c11 100644
--- a/samples/ControlCatalog/Program.cs
+++ b/samples/ControlCatalog/Program.cs
@@ -110,12 +110,11 @@ namespace ControlCatalog
{
app.UseWin32();
- // not available until we do the SkiaSharp merge
- //if (args.Contains("--skia") || DefaultRenderSystem() == RenderSystem.Skia)
- //{
- // app.UseSkia();
- //}
- //else
+ if (args.Contains("--skia") || DefaultRenderSystem() == RenderSystem.Skia)
+ {
+ app.UseSkia();
+ }
+ else
{
app.UseDirect2D();
}
diff --git a/samples/TestApplicationShared/App.cs b/samples/TestApplicationShared/App.cs
index 83987d26df..0812f535f3 100644
--- a/samples/TestApplicationShared/App.cs
+++ b/samples/TestApplicationShared/App.cs
@@ -18,35 +18,35 @@ namespace TestApplication
{
public App()
{
- // TODO: I believe this has to happen before we select sub systems. Can we
- // move this safely into Application itself? Is there anything in here
- // that is platform specific??
- //
+ // TODO: I believe this has to happen before we select sub systems. Can we
+ // move this safely into Application itself? Is there anything in here
+ // that is platform specific??
+ //
RegisterServices();
}
- public void Run()
- {
- Styles.Add(new DefaultTheme());
+ public void Run()
+ {
+ Styles.Add(new DefaultTheme());
- var loader = new PerspexXamlLoader();
- var baseLight = (IStyle)loader.Load(
- new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default"));
- Styles.Add(baseLight);
+ var loader = new PerspexXamlLoader();
+ var baseLight = (IStyle)loader.Load(
+ new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default"));
+ Styles.Add(baseLight);
- Styles.Add(new SampleTabStyle());
- DataTemplates = new DataTemplates
- {
- new FuncTreeDataTemplate(
- x => new TextBlock {Text = x.Name},
- x => x.Children),
- };
+ Styles.Add(new SampleTabStyle());
+ DataTemplates = new DataTemplates
+ {
+ new FuncTreeDataTemplate(
+ x => new TextBlock {Text = x.Name},
+ x => x.Children),
+ };
- MainWindow.RootNamespace = "TestApplication";
- var wnd = MainWindow.Create();
- DevTools.Attach(wnd);
+ MainWindow.RootNamespace = "TestApplication";
+ var wnd = MainWindow.Create();
+ wnd.AttachDevTools();
- Run(wnd);
- }
- }
+ Run(wnd);
+ }
+ }
}
diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs
index 5b747ae666..c70133efaf 100644
--- a/src/Shared/PlatformSupport/AssetLoader.cs
+++ b/src/Shared/PlatformSupport/AssetLoader.cs
@@ -105,7 +105,20 @@ namespace Perspex.Shared.PlatformSupport
"No defaultAssembly, entry assembly or explicit assembly specified, don't know where to look up for the resource, try specifiyng assembly explicitly");
IAssetDescriptor rv;
- asm.Resources.TryGetValue(uri.AbsolutePath, out rv);
+
+ var resourceKey = uri.AbsolutePath;
+
+#if __IOS__
+ // TODO: HACK: to get iOS up and running. Using Shared projects for resources
+ // is flawed as this alters the reource key locations across platforms
+ // I think we need to use Portable libraries from now on to avoid that.
+ if(asm.Name.Contains("iOS"))
+ {
+ resourceKey = resourceKey.Replace("TestApplication", "Perspex.iOSTestApplication");
+ }
+#endif
+
+ asm.Resources.TryGetValue(resourceKey, out rv);
return rv;
}
throw new ArgumentException($"Invalid uri, see https://github.com/Perspex/Perspex/issues/282#issuecomment-166982104", nameof(uri));
diff --git a/src/Skia/Perspex.Skia.Desktop.TestApp/Program.cs b/src/Skia/Perspex.Skia.Desktop.TestApp/Program.cs
index 022306bbe9..98e79c8a8d 100644
--- a/src/Skia/Perspex.Skia.Desktop.TestApp/Program.cs
+++ b/src/Skia/Perspex.Skia.Desktop.TestApp/Program.cs
@@ -26,66 +26,60 @@ using ReactiveUI;
namespace Perspex.Skia.Desktop.TestApp
{
- internal class Program
- {
- private static void Main(string[] args)
- {
- // The version of ReactiveUI currently included is for WPF and so expects a WPF
- // dispatcher. This makes sure it's initialized.
- System.Windows.Threading.Dispatcher foo = System.Windows.Threading.Dispatcher.CurrentDispatcher;
- new SkiaApp();
+ internal class Program
+ {
+ private static void Main(string[] args)
+ {
+ // The version of ReactiveUI currently included is for WPF and so expects a WPF
+ // dispatcher. This makes sure it's initialized.
+ System.Windows.Threading.Dispatcher foo = System.Windows.Threading.Dispatcher.CurrentDispatcher;
- //RendererMixin.DrawFpsCounter = true;
+ new App()
+ .UseWin32()
+ .UseSkia();
- MainWindow.RootNamespace = "Perspex.Skia.Desktop.TestApp";
- var wnd = MainWindow.Create();
+ //RendererMixin.DrawFpsCounter = true;
- // let's start small :)
- //var wnd = SimpleWindow.Create();
+ MainWindow.RootNamespace = "Perspex.Skia.Desktop.TestApp";
+ var wnd = MainWindow.Create();
- DevTools.Attach(wnd);
- Application.Current.Run(wnd);
- }
- }
+ // let's start small :)
+ //var wnd = SimpleWindow.Create();
- internal class SkiaApp : App
- {
- protected override void PlatformInitialization()
- {
- SkiaPlatform.Initialize();
- InitializeSubsystem("Perspex.Win32");
- }
- }
+ DevTools.Attach(wnd);
+ Application.Current.Run(wnd);
+ }
+ }
- internal class SimpleWindow
- {
- public static Window Create()
- {
- Border container;
+ internal class SimpleWindow
+ {
+ public static Window Create()
+ {
+ Border container;
- Window window = new Window
- {
- Title = "Perspex Test Application",
- Content = (container = new Border
- {
- Background = Brushes.Green,
- BorderBrush = Brushes.Yellow,
- BorderThickness = 12,
- Padding = new Thickness(5),
- Child = new Rectangle
- {
- Fill = Brushes.Blue,
- Width = 200,
- Height = 200,
- Margin = new Thickness(50)
- }
- })
+ Window window = new Window
+ {
+ Title = "Perspex Test Application",
+ Content = (container = new Border
+ {
+ Background = Brushes.Green,
+ BorderBrush = Brushes.Yellow,
+ BorderThickness = 12,
+ Padding = new Thickness(5),
+ Child = new Rectangle
+ {
+ Fill = Brushes.Blue,
+ Width = 200,
+ Height = 200,
+ Margin = new Thickness(50)
+ }
+ })
- };
+ };
- window.Show();
- return window;
- }
+ window.Show();
+ return window;
+ }
- }
+ }
}
diff --git a/src/Skia/Perspex.Skia.Desktop/MethodTableImpl.cs b/src/Skia/Perspex.Skia.Desktop/MethodTableImpl.cs
deleted file mode 100644
index bdd8b21821..0000000000
--- a/src/Skia/Perspex.Skia.Desktop/MethodTableImpl.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-
-/* OBSOLETE
-
-//Library loaders were taken from https://github.com/kekekeks/evhttp-sharp/tree/master/EvHttpSharp/Interop (MIT licensed)
-
-namespace Perspex.Skia
-{
- class MethodTableImpl : MethodTable
- {
- public MethodTableImpl() : base(GetMethodTable())
- {
- }
-
- class DetectedPlatformInfo
- {
- public DetectedPlatformInfo(IDynLoader loader, string name, string cpuArch, string dllExtension)
- {
- Loader = loader;
- Name = name;
- CpuArch = cpuArch;
- DllExtension = dllExtension;
- }
-
- public IDynLoader Loader { get; }
- public string Name { get; }
- public string CpuArch { get;}
- public string DllExtension { get; }
- }
-
- static DetectedPlatformInfo DetectPlatform()
- {
- var macInfo = new DetectedPlatformInfo(new OsxLoader(), "Darwin", IntPtr.Size == 4 ? "i686" : "x86_64", ".dylib");
- switch (Environment.OSVersion.Platform)
- {
- case PlatformID.Unix:
- // Well, there are chances MacOSX is reported as Unix instead of MacOSX.
- // Instead of platform check, we'll do a feature checks (Mac specific root folders)
- if (Directory.Exists("/Applications")
- & Directory.Exists("/System")
- & Directory.Exists("/Users")
- & Directory.Exists("/Volumes"))
- return macInfo;
- else
- {
- string cpuArch;
- using (var proc =
- Process.Start(
- (new ProcessStartInfo("uname", "-p")
- {
- UseShellExecute = false,
- RedirectStandardOutput = true
- })))
- {
- proc.WaitForExit();
- cpuArch = proc.StandardOutput.ReadToEnd().Trim();
- }
- return new DetectedPlatformInfo(new LinuxLoader(), "Linux", cpuArch, ".so");
- }
-
- case PlatformID.MacOSX:
- return macInfo;
-
- default:
- return new DetectedPlatformInfo(new Win32Loader(), "Windows", IntPtr.Size == 4 ? "i686" : "x86_64", ".dll");
- }
- }
-
- static IEnumerable GeneratePossiblePaths()
- {
- foreach (
- var basePath in
- new[] {Assembly.GetEntryAssembly(), typeof (MethodTable).Assembly}.Select(
- a => Path.GetDirectoryName(a?.GetModules()?[0]?.FullyQualifiedName))
- .Concat(new[] { Directory.GetCurrentDirectory()}))
- {
- if(basePath == null)
- continue;
- yield return Path.Combine(basePath);
- yield return Path.Combine(basePath, "native");
- yield return Path.Combine(basePath, "lib");
- yield return Path.Combine(basePath, "lib", "native");
- }
- }
-
- static IntPtr GetMethodTable()
- {
- var plat = DetectPlatform();
-
- var name = "libperspesk" + plat.DllExtension;
- var paths = GeneratePossiblePaths().Select(p => Path.Combine(p, plat.Name, plat.CpuArch, name)).ToList();
- var dll = paths.FirstOrDefault(File.Exists);
- var msg = "Unable to find native library in following paths: '" +
- string.Join("', '", paths) + "'";
- Console.Error.WriteLine(msg);
- if (dll == null)
- throw new FileNotFoundException(msg);
- IntPtr hLib = plat.Loader.LoadLibrary(dll);
- IntPtr pGetMethodTable = plat.Loader.GetProcAddress(hLib, "GetPerspexMethodTable");
- var getTable = (GetPerspexMethodTableDelegate)
- Marshal.GetDelegateForFunctionPointer(pGetMethodTable, typeof (GetPerspexMethodTableDelegate));
- return getTable();
- }
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- delegate IntPtr GetPerspexMethodTableDelegate();
-
-
- internal interface IDynLoader
- {
- IntPtr LoadLibrary(string dll);
- IntPtr GetProcAddress(IntPtr dll, string proc);
-
- }
-
- class LinuxLoader : IDynLoader
- {
- // ReSharper disable InconsistentNaming
- [DllImport("libdl.so.2")]
- private static extern IntPtr dlopen(string path, int flags);
-
- [DllImport("libdl.so.2")]
- private static extern IntPtr dlsym(IntPtr handle, string symbol);
-
- [DllImport("libdl.so.2")]
- private static extern IntPtr dlerror();
-
- // ReSharper restore InconsistentNaming
-
- static string DlError()
- {
- return Marshal.PtrToStringAuto(dlerror());
- }
-
- public IntPtr LoadLibrary(string dll)
- {
- var handle = dlopen(dll, 1);
- if (handle == IntPtr.Zero)
- throw new Win32Exception(DlError());
- return handle;
- }
-
- public IntPtr GetProcAddress(IntPtr dll, string proc)
- {
- var ptr = dlsym(dll, proc);
- if (ptr == IntPtr.Zero)
- throw new Win32Exception(DlError());
- return ptr;
- }
- }
-
- internal class Win32Loader : IDynLoader
- {
- [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
- private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
-
- [DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
- private static extern IntPtr LoadLibrary(string lpszLib);
-
- [DllImport("kernel32", EntryPoint = "SetDllDirectoryW", SetLastError = true, CharSet = CharSet.Unicode)]
- extern static bool SetDllDirectory(string lpPathName);
-
- [DllImport("kernel32", EntryPoint = "GetDllDirectoryW", SetLastError = true, CharSet = CharSet.Unicode)]
- extern static int GetDllDirectory(int nBufferLength, char[] lpBuffer);
-
- IntPtr IDynLoader.LoadLibrary(string dll)
- {
- var buffer = new char[2048];
- int oldLen = GetDllDirectory(buffer.Length, buffer);
- var oldDir = new string(buffer, 0, oldLen);
-
- SetDllDirectory(Path.GetDirectoryName(dll));
-
- var handle = LoadLibrary(dll);
- if (handle == IntPtr.Zero)
- throw new Win32Exception(Marshal.GetLastWin32Error());
- SetDllDirectory(oldDir);
-
- return handle;
- }
-
- IntPtr IDynLoader.GetProcAddress(IntPtr dll, string proc)
- {
- var ptr = GetProcAddress(dll, proc);
- if (ptr == IntPtr.Zero)
- throw new Win32Exception(Marshal.GetLastWin32Error());
- return ptr;
- }
- }
-
- class OsxLoader : IDynLoader
- {
- // ReSharper disable InconsistentNaming
- [DllImport("/usr/lib/libSystem.dylib")]
- public static extern IntPtr dlopen(string path, int mode);
-
- [DllImport("/usr/lib/libSystem.dylib")]
- private static extern IntPtr dlsym(IntPtr handle, string symbol);
-
- [DllImport("/usr/lib/libSystem.dylib")]
- private static extern IntPtr dlerror();
-
- // ReSharper restore InconsistentNaming
-
- static string DlError()
- {
- return Marshal.PtrToStringAuto(dlerror());
- }
-
- public IntPtr LoadLibrary(string dll)
- {
- var handle = dlopen(dll, 1);
- if (handle == IntPtr.Zero)
- throw new Win32Exception(DlError());
- return handle;
- }
-
- public IntPtr GetProcAddress(IntPtr dll, string proc)
- {
- var ptr = dlsym(dll, proc);
- if (ptr == IntPtr.Zero)
- throw new Win32Exception(DlError());
- return ptr;
- }
- }
- }
-}
-
- */
\ No newline at end of file
diff --git a/src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj b/src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj
index 3b520fd408..6f5baf1afe 100644
--- a/src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj
+++ b/src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj
@@ -70,7 +70,6 @@
-
UnmanagedMethods.cs
@@ -111,23 +110,6 @@
-
- native\Windows\i686\libEGL.dll
- Always
-
-
- native\Windows\i686\libGLESv2.dll
- Always
-
-
- native\Windows\i686\libperspesk.dll
- Always
-
-
-
-
- native\Linux\x86_64\libperspesk.so
-
diff --git a/src/Skia/Perspex.Skia.iOS/SkiaView.cs b/src/Skia/Perspex.Skia.iOS/SkiaView.cs
index 7542a18afe..01283d6625 100644
--- a/src/Skia/Perspex.Skia.iOS/SkiaView.cs
+++ b/src/Skia/Perspex.Skia.iOS/SkiaView.cs
@@ -15,8 +15,8 @@ using UIKit;
namespace Perspex.Skia.iOS
{
- public abstract class SkiaView : UIView //GLKView
- {
+ public abstract class SkiaView : UIView //GLKView
+ {
//[DllImport("__Internal")]
//static extern IntPtr GetPerspexEAGLContext();
@@ -24,15 +24,15 @@ namespace Perspex.Skia.iOS
//CADisplayLink _link;
static EAGLContext GetContext()
{
- /* No longer needed with SkiaSharp
- //Ensure initialization
- MethodTable.Instance.SetOption((MethodTable.Option)0x10009999, IntPtr.Zero);
- var ctx = GetPerspexEAGLContext();
- var rv = Runtime.GetNSObject(ctx);
- rv.DangerousRetain();
- return rv;
- */
- return null;
+ /* 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(ctx);
+ rv.DangerousRetain();
+ return rv;
+ */
+ return null;
}
@@ -52,10 +52,10 @@ namespace Perspex.Skia.iOS
{
_drawQueued = false;
- // GLKView
- //Display();
+ // GLKView
+ //Display();
- this.SetNeedsDisplay();
+ this.SetNeedsDisplay();
}
}
@@ -64,9 +64,9 @@ namespace Perspex.Skia.iOS
_drawQueued = true;
}
- protected IPlatformHandle PerspexPlatformHandle { get; }
+ protected IPlatformHandle PerspexPlatformHandle { get; }
= new PlatformHandle(IntPtr.Zero, "Null (iOS-specific)");
-
+
protected abstract void Draw();
diff --git a/src/Skia/Perspex.Skia/BitmapImpl.cs b/src/Skia/Perspex.Skia/BitmapImpl.cs
index 02642082bd..f9b9ffa68a 100644
--- a/src/Skia/Perspex.Skia/BitmapImpl.cs
+++ b/src/Skia/Perspex.Skia/BitmapImpl.cs
@@ -11,28 +11,28 @@ namespace Perspex.Skia
{
class BitmapImpl : IRenderTargetBitmapImpl
{
- public SKBitmap Bitmap { get; private set; }
+ public SKBitmap Bitmap { get; private set; }
- public BitmapImpl(SKBitmap bm)
- {
- Bitmap = bm;
- PixelHeight = bm.Width;
- PixelWidth = bm.Height;
- }
+ public BitmapImpl(SKBitmap bm)
+ {
+ Bitmap = bm;
+ PixelHeight = bm.Width;
+ PixelWidth = bm.Height;
+ }
- public BitmapImpl(int width, int height)
- {
- throw new NotImplementedException();
- }
+ public BitmapImpl(int width, int height)
+ {
+ throw new NotImplementedException();
+ }
- public void Dispose()
- {
- }
+ public void Dispose()
+ {
+ }
- public void Save(string fileName)
+ public void Save(string fileName)
{
- // TODO: Implement this for SkiaSharp
- throw new NotImplementedException();
+ // TODO: Implement this for SkiaSharp
+ throw new NotImplementedException();
//var ext = Path.GetExtension(fileName)?.ToLower();
//var type = MethodTable.SkiaImageType.Png;
@@ -49,12 +49,12 @@ namespace Perspex.Skia
public int PixelWidth { get; private set; }
public int PixelHeight { get; private set; }
-
+
public DrawingContext CreateDrawingContext()
{
- return
- new DrawingContext(
- new DrawingContextImpl(null)); // MethodTable.Instance.RenderTargetCreateRenderingContext(Handle)));
+ return
+ new DrawingContext(
+ new DrawingContextImpl(null)); // MethodTable.Instance.RenderTargetCreateRenderingContext(Handle)));
}
}
diff --git a/src/Skia/Perspex.Skia/DrawingContextImpl.cs b/src/Skia/Perspex.Skia/DrawingContextImpl.cs
index 3ed5e384a2..730da6380a 100644
--- a/src/Skia/Perspex.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Perspex.Skia/DrawingContextImpl.cs
@@ -10,250 +10,251 @@ namespace Perspex.Skia
{
unsafe class DrawingContextImpl : IDrawingContextImpl
{
- public SKCanvas Canvas { get; private set; }
+ public SKCanvas Canvas { get; private set; }
public DrawingContextImpl(SKCanvas canvas)
{
- Canvas = canvas;
+ Canvas = canvas;
}
public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect)
{
- var impl = (BitmapImpl)source.PlatformImpl;
- var s = sourceRect.ToSKRect();
- var d = destRect.ToSKRect();
- Canvas.DrawBitmap(impl.Bitmap, s, d);
+ var impl = (BitmapImpl)source.PlatformImpl;
+ var s = sourceRect.ToSKRect();
+ var d = destRect.ToSKRect();
+ Canvas.DrawBitmap(impl.Bitmap, s, d);
}
public void DrawLine(Pen pen, Point p1, Point p2)
{
- using (var paint = CreatePaint(pen, new Size(Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y))))
- {
- Canvas.DrawLine((float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y, paint);
+ using (var paint = CreatePaint(pen, new Size(Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y))))
+ {
+ Canvas.DrawLine((float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y, paint);
+ }
}
- }
public void DrawGeometry(IBrush brush, Pen pen, Geometry geometry)
{
- var impl = ((StreamGeometryImpl)geometry.PlatformImpl);
+ var impl = ((StreamGeometryImpl)geometry.PlatformImpl);
var size = geometry.Bounds.Size;
- using (var fill = brush != null ? CreatePaint(brush, size) : null)
- using (var stroke = pen?.Brush != null ? CreatePaint(pen, size) : null)
+ using (var fill = brush != null ? CreatePaint(brush, size) : null)
+ using (var stroke = pen?.Brush != null ? CreatePaint(pen, size) : null)
{
- if (fill != null)
- {
- Canvas.DrawPath(impl.EffectivePath, fill);
- }
- if (stroke != null)
- {
- Canvas.DrawPath(impl.EffectivePath, stroke);
- }
- }
- }
-
- private SKPaint CreatePaint(IBrush brush, Size targetSize)
+ if (fill != null)
+ {
+ Canvas.DrawPath(impl.EffectivePath, fill);
+ }
+ if (stroke != null)
+ {
+ Canvas.DrawPath(impl.EffectivePath, stroke);
+ }
+ }
+ }
+
+ private SKPaint CreatePaint(IBrush brush, Size targetSize)
{
- SKPaint paint = new SKPaint();
+ SKPaint paint = new SKPaint();
- paint.IsStroke = false;
+ paint.IsStroke = false;
- // TODO: SkiaSharp does not contain alpha yet!
- //double opacity = brush.Opacity * _currentOpacity;
- //paint.SetAlpha(paint.GetAlpha() * opacity);
- paint.IsAntialias = true;
+ // TODO: SkiaSharp does not contain alpha yet!
+ //double opacity = brush.Opacity * _currentOpacity;
+ //paint.SetAlpha(paint.GetAlpha() * opacity);
+ paint.IsAntialias = true;
var solid = brush as SolidColorBrush;
if (solid != null)
{
- paint.Color = solid.Color.ToSKColor();
- return paint;
+ paint.Color = solid.Color.ToSKColor();
+ return paint;
}
var gradient = brush as GradientBrush;
if (gradient != null)
{
- var tileMode = gradient.SpreadMethod.ToSKShaderTileMode();
- var stopColors = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
- var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();
+ var tileMode = gradient.SpreadMethod.ToSKShaderTileMode();
+ var stopColors = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
+ var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();
- var linearGradient = brush as LinearGradientBrush;
- if (linearGradient != null)
+ var linearGradient = brush as LinearGradientBrush;
+ if (linearGradient != null)
{
- var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
- var end = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint();
-
- // would be nice to cache these shaders possibly?
- var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode);
- paint.Shader = shader;
- }
- else
- {
- var radialGradient = brush as RadialGradientBrush;
- if (radialGradient != null)
- {
- var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
- var radius = (float)radialGradient.Radius;
-
- // TODO: There is no SetAlpha in SkiaSharp
- //paint.setAlpha(128);
-
- // would be nice to cache these shaders possibly?
- var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode);
- paint.Shader = shader;
+ var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
+ var end = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint();
+
+ // would be nice to cache these shaders possibly?
+ var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode);
+ paint.Shader = shader;
+ }
+ else
+ {
+ var radialGradient = brush as RadialGradientBrush;
+ if (radialGradient != null)
+ {
+ var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
+ var radius = (float)radialGradient.Radius;
+
+ // TODO: There is no SetAlpha in SkiaSharp
+ //paint.setAlpha(128);
+
+ // would be nice to cache these shaders possibly?
+ var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode);
+ paint.Shader = shader;
+ }
+ }
+
+ return paint;
}
- }
-
- return paint;
- }
var tileBrush = brush as TileBrush;
if (tileBrush != null)
{
- // TODO: Get Tile Brushes working!!!
- //
- throw new NotImplementedException();
-
- // rv.Brush->Type = NativeBrushType.Image;
- // var helper = new TileBrushImplHelper(tileBrush, targetSize);
- // var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height);
- // rv.AddDisposable(bitmap);
- // using (var ctx = bitmap.CreateDrawingContext())
- // helper.DrawIntermediate(ctx);
- // rv.Brush->Bitmap = bitmap.Handle;
- // rv.Brush->BitmapTileMode = tileBrush.TileMode;
- // rv.Brush->BitmapTranslation = new SkiaPoint(-helper.DestinationRect.X, -helper.DestinationRect.Y);
-
- // SkMatrix matrix;
- // matrix.setTranslate(brush->BitmapTranslation);
- // SkShader::TileMode tileX = brush->BitmapTileMode == ptmNone ? SkShader::kClamp_TileMode
- // : (brush->BitmapTileMode == ptmFlipX || brush->BitmapTileMode == ptmFlipXY) ? SkShader::kMirror_TileMode : SkShader::kRepeat_TileMode;
- // SkShader::TileMode tileY = brush->BitmapTileMode == ptmNone ? SkShader::kClamp_TileMode
- // : (brush->BitmapTileMode == ptmFlipY || brush->BitmapTileMode == ptmFlipXY) ? SkShader::kMirror_TileMode : SkShader::kRepeat_TileMode;
-
- // paint.setShader(SkShader::CreateBitmapShader(brush->Bitmap->Bitmap, tileX, tileY, &matrix))->unref();
+ // TODO: Get Tile Brushes working!!!
+ //
+ //throw new NotImplementedException();
+
+ // rv.Brush->Type = NativeBrushType.Image;
+ // var helper = new TileBrushImplHelper(tileBrush, targetSize);
+ // var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height);
+ // rv.AddDisposable(bitmap);
+ // using (var ctx = bitmap.CreateDrawingContext())
+ // helper.DrawIntermediate(ctx);
+ // rv.Brush->Bitmap = bitmap.Handle;
+ // rv.Brush->BitmapTileMode = tileBrush.TileMode;
+ // rv.Brush->BitmapTranslation = new SkiaPoint(-helper.DestinationRect.X, -helper.DestinationRect.Y);
+
+ // SkMatrix matrix;
+ // matrix.setTranslate(brush->BitmapTranslation);
+ // SkShader::TileMode tileX = brush->BitmapTileMode == ptmNone ? SkShader::kClamp_TileMode
+ // : (brush->BitmapTileMode == ptmFlipX || brush->BitmapTileMode == ptmFlipXY) ? SkShader::kMirror_TileMode : SkShader::kRepeat_TileMode;
+ // SkShader::TileMode tileY = brush->BitmapTileMode == ptmNone ? SkShader::kClamp_TileMode
+ // : (brush->BitmapTileMode == ptmFlipY || brush->BitmapTileMode == ptmFlipXY) ? SkShader::kMirror_TileMode : SkShader::kRepeat_TileMode;
+
+ // paint.setShader(SkShader::CreateBitmapShader(brush->Bitmap->Bitmap, tileX, tileY, &matrix))->unref();
}
- return paint;
+ return paint;
}
- private SKPaint CreatePaint(Pen pen, Size targetSize)
+ private SKPaint CreatePaint(Pen pen, Size targetSize)
{
- var paint = CreatePaint(pen.Brush, targetSize);
-
- paint.IsStroke = true;
- paint.StrokeWidth = (float) pen.Thickness;
-
- if (pen.StartLineCap == PenLineCap.Round)
- paint.StrokeCap = SKStrokeCap.Round;
- else if (pen.StartLineCap == PenLineCap.Square)
- paint.StrokeCap = SKStrokeCap.Square;
- else
- paint.StrokeCap = SKStrokeCap.Butt;
-
- if (pen.LineJoin == PenLineJoin.Miter)
- paint.StrokeJoin = SKStrokeJoin.Mitter;
- else if (pen.LineJoin == PenLineJoin.Round)
- paint.StrokeJoin = SKStrokeJoin.Round;
- else
- paint.StrokeJoin = SKStrokeJoin.Bevel;
-
- paint.StrokeMiter = (float) pen.MiterLimit;
-
- //if (pen.DashStyle?.Dashes != null)
- //{
- // var dashes = pen.DashStyle.Dashes;
- // if (dashes.Count > NativeBrush.MaxDashCount)
- // throw new NotSupportedException("Maximum supported dash count is " + NativeBrush.MaxDashCount);
- // brush.Brush->StrokeDashCount = dashes.Count;
- // for (int c = 0; c < dashes.Count; c++)
- // brush.Brush->StrokeDashes[c] = (float)dashes[c];
- // brush.Brush->StrokeDashOffset = (float)pen.DashStyle.Offset;
-
- //}
-
- //if (brush->StrokeDashCount != 0)
- //{
- // paint.setPathEffect(SkDashPathEffect::Create(brush->StrokeDashes, brush->StrokeDashCount, brush->StrokeDashOffset))->unref();
- //}
-
- return paint;
+ var paint = CreatePaint(pen.Brush, targetSize);
+
+ paint.IsStroke = true;
+ paint.StrokeWidth = (float)pen.Thickness;
+
+ if (pen.StartLineCap == PenLineCap.Round)
+ paint.StrokeCap = SKStrokeCap.Round;
+ else if (pen.StartLineCap == PenLineCap.Square)
+ paint.StrokeCap = SKStrokeCap.Square;
+ else
+ paint.StrokeCap = SKStrokeCap.Butt;
+
+ if (pen.LineJoin == PenLineJoin.Miter)
+ paint.StrokeJoin = SKStrokeJoin.Mitter;
+ else if (pen.LineJoin == PenLineJoin.Round)
+ paint.StrokeJoin = SKStrokeJoin.Round;
+ else
+ paint.StrokeJoin = SKStrokeJoin.Bevel;
+
+ paint.StrokeMiter = (float)pen.MiterLimit;
+
+ //if (pen.DashStyle?.Dashes != null)
+ //{
+ // var dashes = pen.DashStyle.Dashes;
+ // if (dashes.Count > NativeBrush.MaxDashCount)
+ // throw new NotSupportedException("Maximum supported dash count is " + NativeBrush.MaxDashCount);
+ // brush.Brush->StrokeDashCount = dashes.Count;
+ // for (int c = 0; c < dashes.Count; c++)
+ // brush.Brush->StrokeDashes[c] = (float)dashes[c];
+ // brush.Brush->StrokeDashOffset = (float)pen.DashStyle.Offset;
+
+ //}
+
+ //if (brush->StrokeDashCount != 0)
+ //{
+ // paint.setPathEffect(SkDashPathEffect::Create(brush->StrokeDashes, brush->StrokeDashCount, brush->StrokeDashOffset))->unref();
+ //}
+
+ return paint;
}
public void DrawRectangle(Pen pen, Rect rect, float cornerRadius = 0)
{
- using (var paint = CreatePaint(pen, rect.Size))
+ using (var paint = CreatePaint(pen, rect.Size))
{
- var rc = rect.ToSKRect();
- if (cornerRadius == 0)
- {
- Canvas.DrawRect(rc, paint);
+ var rc = rect.ToSKRect();
+ if (cornerRadius == 0)
+ {
+ Canvas.DrawRect(rc, paint);
+ }
+ else
+ {
+ // DrawRRect is not accesible in SkiaSharp yet. We should add that
+ // to SkiaSharp and initiate a PR....
+ Canvas.DrawRect(rc, paint);
+ //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
+ }
}
- else
- {
- // this does not appear to exist in SkiaSharp?
- throw new NotImplementedException();
- //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
}
- }
- }
- public void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0)
+ public void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0)
{
- using (var paint = CreatePaint(brush, rect.Size))
+ using (var paint = CreatePaint(brush, rect.Size))
{
- var rc = rect.ToSKRect();
- if (cornerRadius == 0)
- {
- Canvas.DrawRect(rc, paint);
+ var rc = rect.ToSKRect();
+ if (cornerRadius == 0)
+ {
+ Canvas.DrawRect(rc, paint);
+ }
+ else
+ {
+ // this does not appear to exist in SkiaSharp?
+ //throw new NotImplementedException();
+ //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
+ Canvas.DrawRect(rc, paint);
+ }
}
- else
- {
- // this does not appear to exist in SkiaSharp?
- //throw new NotImplementedException();
- //Canvas.DrawRoundedRect(rc, cornerRadius, cornerRadius, paint);
- Canvas.DrawRect(rc, paint);
}
- }
- }
public void DrawText(IBrush foreground, Point origin, FormattedText text)
{
- using (var paint = CreatePaint(foreground, text.Measure()))
- {
- var textImpl = text.PlatformImpl as FormattedTextImpl;
- textImpl.Draw(this.Canvas, origin.ToSKPoint());
+ using (var paint = CreatePaint(foreground, text.Measure()))
+ {
+ var textImpl = text.PlatformImpl as FormattedTextImpl;
+ textImpl.Draw(this.Canvas, origin.ToSKPoint());
+ }
}
- }
public void PushClip(Rect clip)
{
- Canvas.Save();
- Canvas.ClipRect(clip.ToSKRect());
+ Canvas.Save();
+ Canvas.ClipRect(clip.ToSKRect());
}
public void PopClip()
{
- Canvas.Restore();
+ Canvas.Restore();
}
- double _currentOpacity = 1.0f;
+ double _currentOpacity = 1.0f;
private readonly Stack _opacityStack = new Stack();
public void PushOpacity(double opacity)
{
- _opacityStack.Push(_currentOpacity);
- _currentOpacity *= opacity;
+ _opacityStack.Push(_currentOpacity);
+ _currentOpacity *= opacity;
}
- public void PopOpacity()
- {
- _currentOpacity = _opacityStack.Pop();
- }
+ public void PopOpacity()
+ {
+ _currentOpacity = _opacityStack.Pop();
+ }
- public virtual void Dispose()
- {
- }
+ public virtual void Dispose()
+ {
+ }
private Matrix _currentTransform = Matrix.Identity;
@@ -262,30 +263,30 @@ namespace Perspex.Skia
get { return _currentTransform; }
set
{
- if(_currentTransform == value)
+ if (_currentTransform == value)
return;
_currentTransform = value;
- Canvas.SetMatrix(value.ToSKMatrix());
+ Canvas.SetMatrix(value.ToSKMatrix());
+ }
}
- }
}
- // 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();
- }
- }
+ // 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();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Skia/Perspex.Skia/FormattedTextImpl.cs b/src/Skia/Perspex.Skia/FormattedTextImpl.cs
index 08a688b7ea..493831dc26 100644
--- a/src/Skia/Perspex.Skia/FormattedTextImpl.cs
+++ b/src/Skia/Perspex.Skia/FormattedTextImpl.cs
@@ -10,59 +10,59 @@ namespace Perspex.Skia
{
unsafe class FormattedTextImpl : IFormattedTextImpl
{
- public SKPaint Paint { get; private set; }
+ public SKPaint Paint { get; private set; }
- public FormattedTextImpl(string text)
- {
- _text = text;
- Paint = new SKPaint();
+ public FormattedTextImpl(string text)
+ {
+ _text = text;
+ Paint = new SKPaint();
- Paint.TextEncoding = SKTextEncoding.Utf16;
- Paint.IsStroke = false;
- Paint.IsAntialias = true;
- LineOffset = 0;
+ Paint.TextEncoding = SKTextEncoding.Utf16;
+ Paint.IsStroke = false;
+ Paint.IsAntialias = true;
+ LineOffset = 0;
- //Replace 0 characters with zero-width spaces (200B)
- _text = _text.Replace((char)0, (char) 0x200B);
- }
+ //Replace 0 characters with zero-width spaces (200B)
+ _text = _text.Replace((char)0, (char)0x200B);
+ }
- public static FormattedTextImpl Create(string text, string fontFamilyName, double fontSize, FontStyle fontStyle,
+ public static FormattedTextImpl Create(string text, string fontFamilyName, double fontSize, FontStyle fontStyle,
TextAlignment textAlignment, FontWeight fontWeight)
{
- var typeface = TypefaceCache.GetTypeface(fontFamilyName, fontStyle, fontWeight);
-
- FormattedTextImpl instance = new FormattedTextImpl(text);
- instance.Paint.Typeface = typeface;
- instance.Paint.TextSize = (float) fontSize;
- instance.Paint.TextAlign = textAlignment.ToSKTextAlign();
- instance.Rebuild();
- return instance;
- }
+ var typeface = TypefaceCache.GetTypeface(fontFamilyName, fontStyle, fontWeight);
+
+ FormattedTextImpl instance = new FormattedTextImpl(text);
+ instance.Paint.Typeface = typeface;
+ instance.Paint.TextSize = (float)fontSize;
+ instance.Paint.TextAlign = textAlignment.ToSKTextAlign();
+ instance.Rebuild();
+ return instance;
+ }
- private readonly string _text;
+ private readonly string _text;
- readonly List _lines = new List();
+ readonly List _lines = new List();
readonly List _rects = new List();
- List _skiaLines;
- SKRect[] _skiaRects;
+ List _skiaLines;
+ SKRect[] _skiaRects;
- Size _size;
+ Size _size;
- const float MAX_LINE_WIDTH = 10000;
- float LineOffset;
- float WidthConstraint = -1;
+ const float MAX_LINE_WIDTH = 10000;
+ float LineOffset;
+ float WidthConstraint = -1;
- struct PerspexFormattedTextLine
- {
- public float Top;
- public int Start;
- public int Length;
- public float Height;
- public float Width;
- };
-
- public IEnumerable GetLines()
+ struct PerspexFormattedTextLine
+ {
+ public float Top;
+ public int Start;
+ public int Length;
+ public float Height;
+ public float Width;
+ };
+
+ public IEnumerable GetLines()
{
return _lines;
}
@@ -79,13 +79,13 @@ namespace Perspex.Skia
{
IsInside = true,
TextPosition = c,
- IsTrailing = (point.X - rc.X) > rc.Width/2
+ IsTrailing = (point.X - rc.X) > rc.Width / 2
};
}
}
bool end = point.X > _size.Width || point.Y > _size.Height;
- return new TextHitTestResult() {IsTrailing = end, TextPosition = end ? _text.Length - 1 : 0};
+ return new TextHitTestResult() { IsTrailing = end, TextPosition = end ? _text.Length - 1 : 0 };
}
public Rect HitTestTextPosition(int index)
@@ -108,224 +108,224 @@ namespace Perspex.Skia
public void SetForegroundBrush(IBrush brush, int startIndex, int length)
{
- // Is this method even relevant now???
- //
- //var scb = brush as SolidColorBrush;
- //if (scb != null)
- //{
- // Layout.Attributes.Insert(brushAttr);
- //}
+ // Is this method even relevant now???
+ //
+ //var scb = brush as SolidColorBrush;
+ //if (scb != null)
+ //{
+ // Layout.Attributes.Insert(brushAttr);
+ //}
}
- void Rebuild()
+ void Rebuild()
+ {
+ var length = _text.Length;
+
+ _lines.Clear();
+
+ _skiaRects = new SKRect[length];
+ _skiaLines = new List();
+
+ int curOff = 0;
+ float curY = 0;
+
+ var metrics = Paint.FontMetrics;
+ var mTop = metrics.Top; // The greatest distance above the baseline for any glyph (will be <= 0).
+ var mBottom = metrics.Bottom; // The greatest distance below the baseline for any glyph (will be >= 0).
+ var mLeading = metrics.Leading; // The recommended distance to add between lines of text (will be >= 0).
+
+ // This seems like the best measure of full vertical extent
+ float lineHeight = mBottom - mTop;
+
+ // Rendering is relative to baseline
+ LineOffset = -metrics.Top;
+
+ string subString;
+
+ byte[] bytes;
+ GCHandle pinnedArray;
+ IntPtr pointer;
+
+ for (int c = 0; curOff < length; c++)
+ {
+ float lineWidth = -1;
+ int measured;
+ int extraSkip = 0;
+ if (WidthConstraint <= 0)
+ {
+ measured = length;
+ }
+ else
+ {
+ float constraint = WidthConstraint;
+ if (constraint > MAX_LINE_WIDTH)
+ constraint = MAX_LINE_WIDTH;
+
+ subString = _text.Substring(curOff);
+
+ // TODO: This method is not linking into SkiaSharp so we must use the RAW buffer version
+ //measured = (int)Paint.BreakText(subString, constraint, out lineWidth) / 2;
+ bytes = Encoding.UTF8.GetBytes(subString);
+ pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
+ pointer = pinnedArray.AddrOfPinnedObject();
+ // for some reason I have to pass nBytes * 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();
+
+ if (measured == 0)
+ {
+ measured = 1;
+ lineWidth = -1;
+ }
+
+ char nextChar = ' ';
+ if (curOff + measured < length)
+ nextChar = _text[curOff + measured];
+
+ if (nextChar != ' ')
+ {
+ //Perform scan for the last space and end the line there
+ for (int si = curOff + measured - 1; si > curOff; si--)
+ {
+ if (_text[si] == ' ')
+ {
+ measured = si - curOff;
+ extraSkip = 1;
+ //Rects[si] = SkRect();
+ break;
+ }
+ }
+ }
+
+
+ }
+
+ PerspexFormattedTextLine line = new PerspexFormattedTextLine();
+ line.Start = curOff;
+ line.Length = measured;
+ line.Width = lineWidth;
+ line.Height = lineHeight;
+ line.Top = curY;
+
+ if (line.Width < 0)
+ line.Width = _skiaRects[line.Start + line.Length - 1].Right;
+
+ //Build character rects
+ for (int i = line.Start; i < line.Start + line.Length; i++)
+ {
+ float prevRight = 0;
+ if (i != line.Start)
+ prevRight = _skiaRects[i - 1].Right;
+
+ subString = _text.Substring(line.Start, i - line.Start + 1);
+ float w = Paint.MeasureText(subString);
+
+ SKRect rc;
+ rc.Left = prevRight;
+ rc.Right = w;
+ rc.Top = line.Top;
+ rc.Bottom = line.Top + line.Height;
+ _skiaRects[i] = rc;
+ }
+
+ subString = _text.Substring(line.Start, line.Length);
+ line.Width = Paint.MeasureText(subString);
+
+ _skiaLines.Add(line);
+
+ curY += lineHeight; // + mLeading;
+ curOff += measured + extraSkip;
+ }
+
+ // Now convert to Perspex data formats
+ _lines.Clear();
+ _rects.Clear();
+ float maxX = 0;
+
+ for (var c = 0; c < _skiaLines.Count; c++)
+ {
+ var w = _skiaLines[c].Width;
+ if (maxX < w)
+ maxX = w;
+
+ _lines.Add(new FormattedTextLine(_skiaLines[c].Length, _skiaLines[c].Height));
+ }
+
+ for (var c = 0; c < _text.Length; c++)
+ _rects.Add(_skiaRects[c].ToPerspexRect());
+
+ if (_skiaLines.Count == 0)
+ _size = new Size();
+ else
+ {
+ var lastLine = _skiaLines[_skiaLines.Count - 1];
+ _size = new Size(maxX, lastLine.Top + lastLine.Height);
+ }
+ }
+
+ internal void Draw(SKCanvas canvas, SKPoint origin)
{
- var length = _text.Length;
-
- _lines.Clear();
-
- _skiaRects = new SKRect[length];
- _skiaLines = new List();
-
- int curOff = 0;
- float curY = 0;
-
- var metrics = Paint.FontMetrics;
- var mTop = metrics.Top; // The greatest distance above the baseline for any glyph (will be <= 0).
- var mBottom = metrics.Bottom; // The greatest distance below the baseline for any glyph (will be >= 0).
- var mLeading = metrics.Leading; // The recommended distance to add between lines of text (will be >= 0).
-
- // This seems like the best measure of full vertical extent
- float lineHeight = mBottom - mTop;
-
- // Rendering is relative to baseline
- LineOffset = -metrics.Top;
-
- string subString;
-
- byte[] bytes;
- GCHandle pinnedArray;
- IntPtr pointer;
-
- for (int c = 0; curOff < length; c++)
- {
- float lineWidth = -1;
- int measured;
- int extraSkip = 0;
- if (WidthConstraint <= 0)
- {
- measured = length;
- }
- else
- {
- float constraint = WidthConstraint;
- if (constraint > MAX_LINE_WIDTH)
- constraint = MAX_LINE_WIDTH;
-
- subString = _text.Substring(curOff);
-
- // TODO: This method is not linking into SkiaSharp so we must use the RAW buffer version
- //measured = (int)Paint.BreakText(subString, constraint, out lineWidth) / 2;
- bytes = Encoding.UTF8.GetBytes(subString);
- pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- pointer = pinnedArray.AddrOfPinnedObject();
- // for some reason I have to pass nBytes * 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();
-
- if (measured == 0)
- {
- measured = 1;
- lineWidth = -1;
- }
-
- char nextChar = ' ';
- if (curOff + measured < length)
- nextChar = _text[curOff + measured];
-
- if (nextChar != ' ')
- {
- //Perform scan for the last space and end the line there
- for (int si = curOff + measured - 1; si > curOff; si--)
- {
- if (_text[si] == ' ')
- {
- measured = si - curOff;
- extraSkip = 1;
- //Rects[si] = SkRect();
- break;
- }
- }
- }
-
-
- }
-
- PerspexFormattedTextLine line = new PerspexFormattedTextLine();
- line.Start = curOff;
- line.Length = measured;
- line.Width = lineWidth;
- line.Height = lineHeight;
- line.Top = curY;
-
- if (line.Width < 0)
- line.Width = _skiaRects[line.Start + line.Length - 1].Right;
-
- //Build character rects
- for (int i = line.Start; i < line.Start + line.Length; i++)
- {
- float prevRight = 0;
- if (i != line.Start)
- prevRight = _skiaRects[i - 1].Right;
-
- subString = _text.Substring(line.Start, i - line.Start + 1);
- float w = Paint.MeasureText(subString);
-
- SKRect rc;
- rc.Left = prevRight;
- rc.Right = w;
- rc.Top = line.Top;
- rc.Bottom = line.Top + line.Height;
- _skiaRects[i] = rc;
- }
-
- subString = _text.Substring(line.Start, line.Length);
- line.Width = Paint.MeasureText(subString);
-
- _skiaLines.Add(line);
-
- curY += lineHeight; // + mLeading;
- curOff += measured + extraSkip;
- }
-
- // Now convert to Perspex data formats
- _lines.Clear();
- _rects.Clear();
- float maxX = 0;
-
- for (var c = 0; c < _skiaLines.Count; c++)
- {
- var w = _skiaLines[c].Width;
- if (maxX < w)
- maxX = w;
-
- _lines.Add(new FormattedTextLine(_skiaLines[c].Length, _skiaLines[c].Height));
- }
-
- for (var c = 0; c < _text.Length; c++)
- _rects.Add(_skiaRects[c].ToPerspexRect());
-
- if (_skiaLines.Count == 0)
- _size = new Size();
- else
- {
- var lastLine = _skiaLines[_skiaLines.Count - 1];
- _size = new Size(maxX, lastLine.Top + lastLine.Height);
- }
- }
-
- internal void Draw(SKCanvas canvas, SKPoint origin)
- {
- SKPaint paint = Paint;
-
- /* This originated from Native code, it might be useful
- //Debugging code for character positions
- SkPaint dpaint;
- ctx->Canvas->save();
- ctx->Canvas->translate(origin.fX, origin.fY);
- for (int c = 0; c < Lines.size(); c++)
- {
- dpaint.setARGB(255, 0, 0, 0);
- SkRect rc;
- rc.fLeft = 0;
- rc.fTop = Lines[c].Top;
- rc.fRight = Lines[c].Width;
- rc.fBottom = rc.fTop + LineOffset;
- ctx->Canvas->drawRect(rc, dpaint);
- }
- 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.setStyle(SkPaint::kFill_Style);
- ctx->Canvas->drawRect(Rects[c], dpaint);
- }
- ctx->Canvas->restore();
- */
-
- // These seems to vertically align the text properly
- var yOffset = (LineOffset); // + 1) / 2;
-
- for (int c = 0; c < _skiaLines.Count; c++)
- {
- PerspexFormattedTextLine line = _skiaLines[c];
- var subString = _text.Substring(line.Start, line.Length);
- canvas.DrawText(subString, origin.X, origin.Y + line.Top + yOffset, paint);
- }
- }
-
- Size _constraint = new Size(double.PositiveInfinity, double.PositiveInfinity);
+ SKPaint paint = Paint;
+
+ /* This originated from Native code, it might be useful
+ //Debugging code for character positions
+ SkPaint dpaint;
+ ctx->Canvas->save();
+ ctx->Canvas->translate(origin.fX, origin.fY);
+ for (int c = 0; c < Lines.size(); c++)
+ {
+ dpaint.setARGB(255, 0, 0, 0);
+ SkRect rc;
+ rc.fLeft = 0;
+ rc.fTop = Lines[c].Top;
+ rc.fRight = Lines[c].Width;
+ rc.fBottom = rc.fTop + LineOffset;
+ ctx->Canvas->drawRect(rc, dpaint);
+ }
+ 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.setStyle(SkPaint::kFill_Style);
+ ctx->Canvas->drawRect(Rects[c], dpaint);
+ }
+ ctx->Canvas->restore();
+ */
+
+ // These seems to vertically align the text properly
+ var yOffset = (LineOffset); // + 1) / 2;
+
+ for (int c = 0; c < _skiaLines.Count; c++)
+ {
+ PerspexFormattedTextLine line = _skiaLines[c];
+ var subString = _text.Substring(line.Start, line.Length);
+ canvas.DrawText(subString, origin.X, origin.Y + line.Top + yOffset, paint);
+ }
+ }
+
+ Size _constraint = new Size(double.PositiveInfinity, double.PositiveInfinity);
public Size Constraint
{
get { return _constraint; }
set
{
- if(_constraint == value)
+ if (_constraint == value)
return;
_constraint = value;
- WidthConstraint = (_constraint.Width != double.PositiveInfinity)
- ? (float)_constraint.Width
- : -1;
+ WidthConstraint = (_constraint.Width != double.PositiveInfinity)
+ ? (float)_constraint.Width
+ : -1;
- Rebuild();
+ Rebuild();
}
}
@@ -334,8 +334,8 @@ namespace Perspex.Skia
return _text;
}
- public void Dispose()
- {
- }
- }
+ public void Dispose()
+ {
+ }
+ }
}
diff --git a/src/Skia/Perspex.Skia/RenderTarget.cs b/src/Skia/Perspex.Skia/RenderTarget.cs
index 941e46d08c..7304b4bf7f 100644
--- a/src/Skia/Perspex.Skia/RenderTarget.cs
+++ b/src/Skia/Perspex.Skia/RenderTarget.cs
@@ -17,174 +17,174 @@ using Perspex.Win32.Interop;
namespace Perspex.Skia
{
- internal class RenderTarget : IRenderTarget
+ internal 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);
+ //protected override void Delete(IntPtr handle) => MethodTable.Instance.DisposeRenderTarget(handle);
- public virtual DrawingContext CreateDrawingContext()
+ public virtual DrawingContext CreateDrawingContext()
{
- return
- new DrawingContext(
- new DrawingContextImpl(Surface.Canvas)); // MethodTable.Instance.RenderTargetCreateRenderingContext(Handle)));
+ return
+ new DrawingContext(
+ new DrawingContextImpl(Surface.Canvas)); // MethodTable.Instance.RenderTargetCreateRenderingContext(Handle)));
}
- public void Dispose()
- {
- //throw new NotImplementedException();
- }
- }
+ public void Dispose()
+ {
+ //throw new NotImplementedException();
+ }
+ }
- internal class WindowRenderTarget : RenderTarget
- {
- private readonly IntPtr _hwnd;
- SKBitmap _bitmap;
+ internal class WindowRenderTarget : RenderTarget
+ {
+ private readonly IntPtr _hwnd;
+ SKBitmap _bitmap;
- int Width { get; set; }
- int Height { get; set; }
+ int Width { get; set; }
+ int Height { get; set; }
- public WindowRenderTarget(IntPtr hwnd)
- {
- _hwnd = hwnd;
- FixSize();
- }
+ public WindowRenderTarget(IntPtr hwnd)
+ {
+ _hwnd = hwnd;
+ FixSize();
+ }
#if __IOS__
- private CGRect GetApplicationFrame()
- {
- // if we are excluding Status Bar then we use ApplicationFrame
- // otherwise we use full screen bounds. Note that this must also match
- // the Skia/PerspexView!!!
- //
- bool excludeStatusArea = false; // TODO: make this configurable later
- if (excludeStatusArea)
- {
- return UIScreen.MainScreen.ApplicationFrame;
- }
- else
- {
- return UIScreen.MainScreen.Bounds;
- }
- }
+ private CGRect GetApplicationFrame()
+ {
+ // if we are excluding Status Bar then we use ApplicationFrame
+ // otherwise we use full screen bounds. Note that this must also match
+ // the Skia/PerspexView!!!
+ //
+ bool excludeStatusArea = false; // TODO: make this configurable later
+ if (excludeStatusArea)
+ {
+ return UIScreen.MainScreen.ApplicationFrame;
+ }
+ else
+ {
+ return UIScreen.MainScreen.Bounds;
+ }
+ }
#endif
- void FixSize()
- {
- int width, height;
- GetPlatformWindowSize(_hwnd, out width, out height);
- if (Width == width && Height == height)
- return;
+ void FixSize()
+ {
+ int width, height;
+ GetPlatformWindowSize(_hwnd, out width, out height);
+ if (Width == width && Height == height)
+ return;
- Width = width;
- Height = height;
+ Width = width;
+ Height = height;
- if(Surface != null)
- {
- Surface.Dispose();
- }
+ if (Surface != null)
+ {
+ Surface.Dispose();
+ }
- if(_bitmap != null)
- {
- _bitmap.Dispose();
- }
+ if (_bitmap != null)
+ {
+ _bitmap.Dispose();
+ }
- _bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul);
+ _bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul);
- //bitmap.LockPixels();
- IntPtr length;
- var pixels = _bitmap.GetPixels(out length);
+ //bitmap.LockPixels();
+ IntPtr length;
+ var pixels = _bitmap.GetPixels(out length);
- // Wrap the bitmap in a Surface and keep it cached
- Surface = SKSurface.Create(_bitmap.Info, pixels, _bitmap.RowBytes);
- }
+ // Wrap the bitmap in a Surface and keep it cached
+ Surface = SKSurface.Create(_bitmap.Info, pixels, _bitmap.RowBytes);
+ }
- void GetPlatformWindowSize(IntPtr hwnd, out int w, out int h)
- {
+ void GetPlatformWindowSize(IntPtr hwnd, out int w, out int h)
+ {
#if __IOS__
- var bounds = GetApplicationFrame();
- w = (int) bounds.Width;
- h = (int)bounds.Height;
+ var bounds = GetApplicationFrame();
+ w = (int)bounds.Width;
+ h = (int)bounds.Height;
#elif WIN32
- UnmanagedMethods.RECT rc;
- UnmanagedMethods.GetClientRect(_hwnd, out rc);
- w = rc.right - rc.left;
- h = rc.bottom - rc.top;
+ UnmanagedMethods.RECT rc;
+ UnmanagedMethods.GetClientRect(_hwnd, out rc);
+ w = rc.right - rc.left;
+ h = rc.bottom - rc.top;
#else
throw new NotImplementedException();
#endif
- }
+ }
- public override DrawingContext CreateDrawingContext()
- {
- FixSize();
+ public override DrawingContext CreateDrawingContext()
+ {
+ FixSize();
- var canvas = Surface.Canvas;
- canvas.RestoreToCount(0);
- canvas.Save();
+ var canvas = Surface.Canvas;
+ canvas.RestoreToCount(0);
+ canvas.Save();
#if __IOS__
- var screenScale = UIScreen.MainScreen.Scale;
- canvas.Scale((float)screenScale, (float)screenScale);
+ var screenScale = UIScreen.MainScreen.Scale;
+ canvas.Scale((float)screenScale, (float)screenScale);
#endif
- canvas.Clear(SKColors.Red);
- canvas.ResetMatrix();
+ canvas.Clear(SKColors.Red);
+ canvas.ResetMatrix();
- return
- new DrawingContext(
- new WindowDrawingContextImpl(this));
- }
+ return
+ new DrawingContext(
+ new WindowDrawingContextImpl(this));
+ }
- public void Present()
- {
- _bitmap.LockPixels();
- IntPtr length;
- var pixels = _bitmap.GetPixels(out length);
+ public void Present()
+ {
+ _bitmap.LockPixels();
+ IntPtr length;
+ var pixels = _bitmap.GetPixels(out length);
#if __IOS__
- const int bitmapInfo = ((int)CGBitmapFlags.ByteOrder32Big) | ((int)CGImageAlphaInfo.PremultipliedLast);
- var bounds = GetApplicationFrame();
- var statusBarOffset = UIScreen.MainScreen.Bounds.Height - bounds.Height;
-
- using (var colorSpace = CGColorSpace.CreateDeviceRGB())
- using (var bContext = new CGBitmapContext(pixels, _bitmap.Width, _bitmap.Height, 8, _bitmap.Width * 4, colorSpace, (CGImageAlphaInfo)bitmapInfo))
- using (var image = bContext.ToImage())
- using (var context = UIGraphics.GetCurrentContext())
- {
- // flip the image for CGContext.DrawImage
- context.TranslateCTM(0, bounds.Height + statusBarOffset);
- context.ScaleCTM(1, -1);
- context.DrawImage(bounds, image);
- }
+ const int bitmapInfo = ((int)CGBitmapFlags.ByteOrder32Big) | ((int)CGImageAlphaInfo.PremultipliedLast);
+ var bounds = GetApplicationFrame();
+ var statusBarOffset = UIScreen.MainScreen.Bounds.Height - bounds.Height;
+
+ using (var colorSpace = CGColorSpace.CreateDeviceRGB())
+ using (var bContext = new CGBitmapContext(pixels, _bitmap.Width, _bitmap.Height, 8, _bitmap.Width * 4, colorSpace, (CGImageAlphaInfo)bitmapInfo))
+ using (var image = bContext.ToImage())
+ using (var context = UIGraphics.GetCurrentContext())
+ {
+ // flip the image for CGContext.DrawImage
+ context.TranslateCTM(0, bounds.Height + statusBarOffset);
+ context.ScaleCTM(1, -1);
+ context.DrawImage(bounds, image);
+ }
#elif WIN32
- UnmanagedMethods.BITMAPINFO bmi = new UnmanagedMethods.BITMAPINFO();
- bmi.biSize = UnmanagedMethods.SizeOf_BITMAPINFOHEADER;
- bmi.biWidth = _bitmap.Width;
- bmi.biHeight = -_bitmap.Height; // top-down image
- bmi.biPlanes = 1;
- bmi.biBitCount = 32;
- bmi.biCompression = (uint)UnmanagedMethods.BitmapCompressionMode.BI_RGB;
- bmi.biSizeImage = 0;
-
- IntPtr hdc = UnmanagedMethods.GetDC(_hwnd);
-
- int ret = UnmanagedMethods.SetDIBitsToDevice(hdc,
- 0, 0,
- (uint) _bitmap.Width, (uint) _bitmap.Height,
- 0, 0,
- 0, (uint) _bitmap.Height,
- pixels,
- ref bmi,
- (uint)UnmanagedMethods.DIBColorTable.DIB_RGB_COLORS);
-
- UnmanagedMethods.ReleaseDC(_hwnd, hdc);
+ UnmanagedMethods.BITMAPINFO bmi = new UnmanagedMethods.BITMAPINFO();
+ bmi.biSize = UnmanagedMethods.SizeOf_BITMAPINFOHEADER;
+ bmi.biWidth = _bitmap.Width;
+ bmi.biHeight = -_bitmap.Height; // top-down image
+ bmi.biPlanes = 1;
+ bmi.biBitCount = 32;
+ bmi.biCompression = (uint)UnmanagedMethods.BitmapCompressionMode.BI_RGB;
+ bmi.biSizeImage = 0;
+
+ IntPtr hdc = UnmanagedMethods.GetDC(_hwnd);
+
+ int ret = UnmanagedMethods.SetDIBitsToDevice(hdc,
+ 0, 0,
+ (uint)_bitmap.Width, (uint)_bitmap.Height,
+ 0, 0,
+ 0, (uint)_bitmap.Height,
+ pixels,
+ ref bmi,
+ (uint)UnmanagedMethods.DIBColorTable.DIB_RGB_COLORS);
+
+ UnmanagedMethods.ReleaseDC(_hwnd, hdc);
#endif
- _bitmap.UnlockPixels();
- }
+ _bitmap.UnlockPixels();
+ }
- }
+ }
}
diff --git a/src/Skia/Perspex.Skia/SkiaPlatform.cs b/src/Skia/Perspex.Skia/SkiaPlatform.cs
index d9c5728a04..b05096b84b 100644
--- a/src/Skia/Perspex.Skia/SkiaPlatform.cs
+++ b/src/Skia/Perspex.Skia/SkiaPlatform.cs
@@ -24,17 +24,17 @@ namespace Perspex.Skia
public static void Initialize()
=> PerspexLocator.CurrentMutable.Bind().ToConstant(new PlatformRenderInterface());
- public static bool ForceSoftwareRendering
+ public static bool ForceSoftwareRendering
{
get { return s_forceSoftwareRendering; }
set
{
s_forceSoftwareRendering = value;
- // Do we still need this with SkiaSharp??
- //MethodTable.Instance.SetOption(MethodTable.Option.ForceSoftware, new IntPtr(value ? 1 : 0));
- throw new NotImplementedException();
- }
- }
+ // Do we still need this with SkiaSharp??
+ //MethodTable.Instance.SetOption(MethodTable.Option.ForceSoftware, new IntPtr(value ? 1 : 0));
+ throw new NotImplementedException();
+ }
+ }
}
}
diff --git a/src/Skia/Perspex.Skia/SkiaSharpExtensions.cs b/src/Skia/Perspex.Skia/SkiaSharpExtensions.cs
index 2f20eb3012..a46f37f6ab 100644
--- a/src/Skia/Perspex.Skia/SkiaSharpExtensions.cs
+++ b/src/Skia/Perspex.Skia/SkiaSharpExtensions.cs
@@ -4,66 +4,66 @@ using SkiaSharp;
namespace Perspex.Skia
{
- public static class SkiaSharpExtensions
- {
- public static SKPoint ToSKPoint(this Point p)
- {
- return new SKPoint((float)p.X, (float)p.Y);
- }
+ public static class SkiaSharpExtensions
+ {
+ public static SKPoint ToSKPoint(this Point p)
+ {
+ return new SKPoint((float)p.X, (float)p.Y);
+ }
- public static SKRect ToSKRect(this Rect r)
- {
- return new SKRect((float)r.X, (float)r.Y, (float)r.Right, (float)r.Bottom);
- }
+ public static SKRect ToSKRect(this Rect r)
+ {
+ return new SKRect((float)r.X, (float)r.Y, (float)r.Right, (float)r.Bottom);
+ }
- public static Rect ToPerspexRect(this SKRect r)
- {
- return new Rect(r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top);
- }
+ public static Rect ToPerspexRect(this SKRect r)
+ {
+ return new Rect(r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top);
+ }
- public static SKMatrix ToSKMatrix(this Matrix m)
- {
- var sm = new SKMatrix
- {
- ScaleX = (float)m.M11,
- SkewX = (float)m.M21,
- TransX = (float)m.M31,
- SkewY = (float)m.M12,
- ScaleY = (float)m.M22,
- TransY = (float)m.M32,
- Persp0 = 0,
- Persp1 = 0,
- Persp2 = 1
- };
+ public static SKMatrix ToSKMatrix(this Matrix m)
+ {
+ var sm = new SKMatrix
+ {
+ ScaleX = (float)m.M11,
+ SkewX = (float)m.M21,
+ TransX = (float)m.M31,
+ SkewY = (float)m.M12,
+ ScaleY = (float)m.M22,
+ TransY = (float)m.M32,
+ Persp0 = 0,
+ Persp1 = 0,
+ Persp2 = 1
+ };
- return sm;
- }
+ return sm;
+ }
- public static SKColor ToSKColor(this Media.Color c)
- {
- return new SKColor(c.R, c.G, c.B, c.A);
- }
+ public static SKColor ToSKColor(this Media.Color c)
+ {
+ return new SKColor(c.R, c.G, c.B, c.A);
+ }
- public static SKShaderTileMode ToSKShaderTileMode(this Media.GradientSpreadMethod m)
- {
- switch (m)
- {
- default:
- case Media.GradientSpreadMethod.Pad: return SKShaderTileMode.Clamp;
- case Media.GradientSpreadMethod.Reflect: return SKShaderTileMode.Mirror;
- case Media.GradientSpreadMethod.Repeat: return SKShaderTileMode.Repeat;
- }
- }
+ public static SKShaderTileMode ToSKShaderTileMode(this Media.GradientSpreadMethod m)
+ {
+ switch (m)
+ {
+ default:
+ case Media.GradientSpreadMethod.Pad: return SKShaderTileMode.Clamp;
+ case Media.GradientSpreadMethod.Reflect: return SKShaderTileMode.Mirror;
+ case Media.GradientSpreadMethod.Repeat: return SKShaderTileMode.Repeat;
+ }
+ }
- public static SKTextAlign ToSKTextAlign(this TextAlignment a)
- {
- switch (a)
- {
- default:
- case TextAlignment.Left: return SKTextAlign.Left;
- case TextAlignment.Center: return SKTextAlign.Center;
- case TextAlignment.Right: return SKTextAlign.Right;
- }
- }
- }
+ public static SKTextAlign ToSKTextAlign(this TextAlignment a)
+ {
+ switch (a)
+ {
+ default:
+ case TextAlignment.Left: return SKTextAlign.Left;
+ case TextAlignment.Center: return SKTextAlign.Center;
+ case TextAlignment.Right: return SKTextAlign.Right;
+ }
+ }
+ }
}
diff --git a/src/Skia/Perspex.Skia/StreamGeometryImpl.cs b/src/Skia/Perspex.Skia/StreamGeometryImpl.cs
index c6443f107d..ecf1e03779 100644
--- a/src/Skia/Perspex.Skia/StreamGeometryImpl.cs
+++ b/src/Skia/Perspex.Skia/StreamGeometryImpl.cs
@@ -12,11 +12,11 @@ namespace Perspex.Skia
{
class StreamGeometryImpl : IStreamGeometryImpl
{
- SKPath _path;
- SKPath _transformedPath;
+ SKPath _path;
+ SKPath _transformedPath;
+
+ private Matrix _transform = Matrix.Identity;
- private Matrix _transform = Matrix.Identity;
-
public SKPath EffectivePath => (_transformedPath ?? _path);
public Rect GetRenderBounds(double strokeThickness)
@@ -32,7 +32,7 @@ namespace Perspex.Skia
get { return _transform; }
set
{
- if(_transform == value)
+ if (_transform == value)
return;
_transform = value;
@@ -42,80 +42,80 @@ namespace Perspex.Skia
void ApplyTransform()
{
- if (_path == null)
- return;
-
- if (_transformedPath != null)
- {
- _transformedPath.Dispose();
- _transformedPath = null;
- }
-
- // TODO: SkiaSharp does not expose Transform yet!!!
- //if (!Transform.IsIdentity)
- //{
- // _transformedPath = new SKPath();
- // _path.Transform(Transform.ToSKMatrix(), _transformedPath);
- //}
- }
-
- public IStreamGeometryImpl Clone()
- {
- // TODO: there is no SKPath.Clone yet!!!!!!!!!!!!!
- //
- //return new StreamGeometryImpl
- //{
- // _path = _path?.Clone(),
- // _transformedPath = _transformedPath?.Clone(),
- // _transform = Transform,
- // Bounds = Bounds
- //};
-
- return this; // this will probably end bad!!
- }
+ if (_path == null)
+ return;
+
+ if (_transformedPath != null)
+ {
+ _transformedPath.Dispose();
+ _transformedPath = null;
+ }
+
+ // TODO: SkiaSharp does not expose Transform yet!!!
+ //if (!Transform.IsIdentity)
+ //{
+ // _transformedPath = new SKPath();
+ // _path.Transform(Transform.ToSKMatrix(), _transformedPath);
+ //}
+ }
+
+ public IStreamGeometryImpl Clone()
+ {
+ // TODO: there is no SKPath.Clone yet!!!!!!!!!!!!!
+ //
+ //return new StreamGeometryImpl
+ //{
+ // _path = _path?.Clone(),
+ // _transformedPath = _transformedPath?.Clone(),
+ // _transform = Transform,
+ // Bounds = Bounds
+ //};
+
+ return this; // this will probably end bad!!
+ }
public IStreamGeometryContextImpl Open()
{
- _path = new SKPath();
+ _path = new SKPath();
return new StreamContext(this);
}
class StreamContext : IStreamGeometryContextImpl
{
private readonly StreamGeometryImpl _geometryImpl;
- private SKPath _path;
+ private SKPath _path;
//readonly List _elements = new List();
Point _currentPoint;
public StreamContext(StreamGeometryImpl geometryImpl)
{
_geometryImpl = geometryImpl;
- _path = _geometryImpl._path;
- }
+ _path = _geometryImpl._path;
+ }
- public void Dispose()
- {
- // Not sure what we need to do here....
+ public void Dispose()
+ {
+ // Not sure what we need to do here....
- // //throw new NotImplementedException();
+ // //throw new NotImplementedException();
- // var arr = _elements.ToArray();
- // SkRect rc;
- // _path?.Dispose();
- // _path = new SKPath(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc)));
- // _geometryImpl.ApplyTransform();
+ // var arr = _elements.ToArray();
+ // SkRect rc;
+ // _path?.Dispose();
+ // _path = new SKPath(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc)));
+ // _geometryImpl.ApplyTransform();
- // _geometryImpl.Bounds = rc.ToRect();
+ // _geometryImpl.Bounds = rc.ToRect();
- SKRect rc;
- _path.GetBounds(out rc);
- _geometryImpl.ApplyTransform();
- _geometryImpl.Bounds = rc.ToPerspexRect();
- }
+ SKRect rc;
+ _path.GetBounds(out rc);
+ _geometryImpl.ApplyTransform();
+ _geometryImpl.Bounds = rc.ToPerspexRect();
+ }
- 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;
@@ -123,34 +123,34 @@ namespace Perspex.Skia
public void BeginFigure(Point startPoint, bool isFilled)
{
- _path.MoveTo((float)startPoint.X, (float)startPoint.Y);
- _currentPoint = startPoint;
+ _path.MoveTo((float)startPoint.X, (float)startPoint.Y);
+ _currentPoint = startPoint;
}
public void CubicBezierTo(Point point1, Point point2, Point point3)
{
- _path.CubicTo((float)point1.X, (float)point1.Y, (float)point2.X, (float)point2.Y, (float)point3.X, (float)point3.Y);
- _currentPoint = point3;
+ _path.CubicTo((float)point1.X, (float)point1.Y, (float)point2.X, (float)point2.Y, (float)point3.X, (float)point3.Y);
+ _currentPoint = point3;
}
public void QuadraticBezierTo(Point point1, Point point2)
{
- _path.QuadTo((float)point1.X, (float)point1.Y, (float)point2.X, (float)point2.Y);
- _currentPoint = point2;
+ _path.QuadTo((float)point1.X, (float)point1.Y, (float)point2.X, (float)point2.Y);
+ _currentPoint = point2;
}
public void LineTo(Point point)
{
- _path.LineTo((float)point.X, (float)point.Y);
- _currentPoint = point;
+ _path.LineTo((float)point.X, (float)point.Y);
+ _currentPoint = point;
}
public void EndFigure(bool isClosed)
{
- if(isClosed)
- {
- _path.Close();
- }
+ if (isClosed)
+ {
+ _path.Close();
+ }
}
public void SetFillRule(FillRule fillRule)
diff --git a/src/Skia/Perspex.Skia/TypefaceCache.cs b/src/Skia/Perspex.Skia/TypefaceCache.cs
index 4d51980802..bd1edf1abe 100644
--- a/src/Skia/Perspex.Skia/TypefaceCache.cs
+++ b/src/Skia/Perspex.Skia/TypefaceCache.cs
@@ -22,13 +22,13 @@ namespace Perspex.Skia
SKTypeface typeface = null;
if (!entry.TryGetValue(style, out typeface))
{
- typeface = SKTypeface.FromFamilyName(name, style);
- if(typeface == null)
- {
- typeface = SKTypeface.FromFamilyName(null, style);
- }
- entry[style] = typeface;
- }
+ typeface = SKTypeface.FromFamilyName(name, style);
+ if (typeface == null)
+ {
+ typeface = SKTypeface.FromFamilyName(null, style);
+ }
+ entry[style] = typeface;
+ }
return typeface;
}
@@ -38,8 +38,8 @@ namespace Perspex.Skia
if (style != FontStyle.Normal)
sstyle |= SKTypefaceStyle.Italic;
- if(weight>FontWeight.Normal)
- sstyle |= SKTypefaceStyle.Bold;
+ if (weight > FontWeight.Normal)
+ sstyle |= SKTypefaceStyle.Bold;
return GetTypeface(name, sstyle);
}
diff --git a/src/Skia/Perspex.Skia/readme.md b/src/Skia/Perspex.Skia/readme.md
index 7f8a459eb4..698739415d 100644
--- a/src/Skia/Perspex.Skia/readme.md
+++ b/src/Skia/Perspex.Skia/readme.md
@@ -5,18 +5,18 @@ BitmapImpl
- Save
DrawingContextImpl
-- DrawRoundRect is not properly implemented due to lack of support in Skia
+- DrawRoundRect is not properly implemented due to lack of support in SkiaSharp
- Alpha support missing as SkiaSharp does not expose this
- Gradient Shader caching?
- TileBrushes
- Pen Dash styles
Formatted Text Rendering
-- still needs a lot of work once SkiaSharp implementation is better
+- minor polish
RenderTarget
- Figure out a cleaner implementation across all platforms
-- HW accelerated working?
+- HW acceleration
StreamGeometry
- Paths within Paths may not work right
@@ -30,13 +30,12 @@ App Bootstrapping
- ie. app.UseDirect2D() (via platform specific extension methods)
Android
-- Testing & fixes
+- Not tested at all yet
iOS
-- Get GLView working again?
-
+- Get GLView working again. See HW above
General
- Cleanup/eliminate obsolete files
-- Cleanup the many Test Applications
+- Finish cleanup of the many Test Applications
- Get Skia Unit Tests passing
\ No newline at end of file
diff --git a/src/iOS/Perspex.iOS/Perspex.iOS.csproj b/src/iOS/Perspex.iOS/Perspex.iOS.csproj
index b0ce948a3c..097c3f9bbd 100644
--- a/src/iOS/Perspex.iOS/Perspex.iOS.csproj
+++ b/src/iOS/Perspex.iOS/Perspex.iOS.csproj
@@ -37,6 +37,7 @@
+
diff --git a/src/iOS/Perspex.iOS/PerspexAppDelegate.cs b/src/iOS/Perspex.iOS/PerspexAppDelegate.cs
index 3a8c2e00df..3dd82d59ae 100644
--- a/src/iOS/Perspex.iOS/PerspexAppDelegate.cs
+++ b/src/iOS/Perspex.iOS/PerspexAppDelegate.cs
@@ -10,6 +10,7 @@ using Perspex.Shared.PlatformSupport;
using Perspex.Skia;
using UIKit;
+/* No Longer needed
namespace Perspex.iOS
{
public class PerspexAppDelegate : UIApplicationDelegate
@@ -73,3 +74,4 @@ namespace Perspex.iOS
}
}
}
+*/
\ No newline at end of file
diff --git a/src/iOS/Perspex.iOS/PerspexView.cs b/src/iOS/Perspex.iOS/PerspexView.cs
index 38314e0f82..385e6d3293 100644
--- a/src/iOS/Perspex.iOS/PerspexView.cs
+++ b/src/iOS/Perspex.iOS/PerspexView.cs
@@ -168,7 +168,7 @@ namespace Perspex.iOS
var location = touch.LocationInView(this).ToPerspex();
Input?.Invoke(new RawMouseEventArgs(
- PerspexAppDelegate.MouseDevice,
+ iOSPlatform.MouseDevice,
(uint) touch.Timestamp,
_inputRoot,
RawMouseEventType.LeftButtonUp,
@@ -185,10 +185,10 @@ namespace Perspex.iOS
{
var location = touch.LocationInView(this).ToPerspex();
_touchLastPoint = location;
- Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot,
+ Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot,
RawMouseEventType.Move, location, InputModifiers.None));
- Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot,
+ Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot,
RawMouseEventType.LeftButtonDown, location, InputModifiers.None));
}
}
@@ -199,15 +199,15 @@ namespace Perspex.iOS
if (touch != null)
{
var location = touch.LocationInView(this).ToPerspex();
- if (PerspexAppDelegate.MouseDevice.Captured != null)
- Input?.Invoke(new RawMouseEventArgs(PerspexAppDelegate.MouseDevice, (uint) touch.Timestamp, _inputRoot,
+ if (iOSPlatform.MouseDevice.Captured != null)
+ Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint) touch.Timestamp, _inputRoot,
RawMouseEventType.Move, location, InputModifiers.LeftMouseButton));
else
{
//magic number based on test - correction of 0.02 is working perfect
double correction = 0.02;
- Input?.Invoke(new RawMouseWheelEventArgs(PerspexAppDelegate.MouseDevice, (uint)touch.Timestamp,
+ Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp,
_inputRoot, location, (location - _touchLastPoint)* correction, InputModifiers.LeftMouseButton));
}
_touchLastPoint = location;
diff --git a/src/iOS/Perspex.iOS/iOSPlatform.cs b/src/iOS/Perspex.iOS/iOSPlatform.cs
new file mode 100644
index 0000000000..8f608de13b
--- /dev/null
+++ b/src/iOS/Perspex.iOS/iOSPlatform.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Reflection;
+using Perspex.Input;
+using Perspex.Input.Platform;
+using Perspex.iOS;
+using Perspex.Platform;
+using Perspex.Shared.PlatformSupport;
+using Perspex.Skia;
+using UIKit;
+
+namespace Perspex
+{
+ public static class iOSApplicationExtensions
+ {
+ public static AppT UseiOS(this AppT app) where AppT : Application
+ {
+ Perspex.iOS.iOSPlatform.Initialize();
+ return app;
+ }
+
+ // I wish I could merge this with the SkiaPlatform itself. Might be possible
+ // once we switch to SkiaSharp
+ public static AppT UseSkiaViewHost(this AppT app) where AppT : Application
+ {
+ var window = new UIWindow(UIScreen.MainScreen.Bounds);
+ var controller = new PerspexViewController(window);
+ window.RootViewController = controller;
+ window.MakeKeyAndVisible();
+
+ PerspexLocator.CurrentMutable
+ .Bind().ToConstant(new WindowingPlatform(controller.PerspexView));
+
+ SkiaPlatform.Initialize();
+
+ return app;
+ }
+
+ public static AppT UseAssetAssembly(this AppT app, Assembly assembly) where AppT : Application
+ {
+ // Asset loading searches our own assembly?
+ var loader = new AssetLoader(assembly);
+ PerspexLocator.CurrentMutable.Bind().ToConstant(loader);
+
+ 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
+{
+ // TODO: Perhaps we should make this class handle all these interfaces directly, like we
+ // do for Win32 and Gtk
+ //
+ public class iOSPlatform //: IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
+ {
+ internal static MouseDevice MouseDevice;
+ internal static KeyboardDevice KeyboardDevice;
+
+ public static void Initialize()
+ {
+ MouseDevice = new MouseDevice();
+ KeyboardDevice = new KeyboardDevice();
+
+ // refactored
+ //SharedPlatform.Register(appType.Assembly);
+
+ PerspexLocator.CurrentMutable
+ .Bind().ToSingleton()
+ .Bind().ToTransient()
+ //.Bind().ToTransient()
+ .Bind().ToTransient()
+ .Bind().ToConstant(KeyboardDevice)
+ .Bind().ToConstant(MouseDevice)
+ .Bind().ToSingleton()
+ .Bind().ToConstant(PlatformThreadingInterface.Instance);
+ }
+ }
+}
diff --git a/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs b/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs
index 0a1b353fb1..fcec8f01c5 100644
--- a/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs
+++ b/src/iOS/Perspex.iOSTestApplication/AppDelegate.cs
@@ -16,7 +16,7 @@ namespace Perspex.iOSTestApplication
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
- public partial class AppDelegate : PerspexAppDelegate
+ public partial class AppDelegate : UIApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
@@ -27,58 +27,65 @@ namespace Perspex.iOSTestApplication
//
public override bool FinishedLaunching(UIApplication uiapp, NSDictionary options)
{
- InitPerspex (typeof (App));
-
var app = new App();
- MainWindow.RootNamespace = "Perspex.iOSTestApplication";
- var window = MainWindow.Create();
- //var window = Create();
- window.Show();
- app.Run(window);
+ app.UseiOS();
+ app.UseSkiaViewHost();
+ app.UseSkia();
+
+ // looking for this URI fails: "TestApplication.github_icon.png"
+ var asm = typeof(App).Assembly;
+ app.UseAssetAssembly(asm);
+
+ //MainWindow.RootNamespace = "Perspex.iOSTestApplication";
+ //var window = MainWindow.Create();
+ ////var window = Create();
+ //window.Show();
+ //app.Run(window);
+ app.Run();
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
- },
+ // 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
- }
+ new Button
+ {
+ Content = "BUTTON",
+ Width = 150,
+ Height = 40,
+ Background = Brushes.LightGreen,
+ Foreground = Brushes.Black
+ }
- }
- }
- };
+ }
+ }
+ };
- return window;
- }
+ return window;
+ }
}
diff --git a/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj b/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj
index 412712bc28..03f4a78aa7 100644
--- a/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj
+++ b/src/iOS/Perspex.iOSTestApplication/Perspex.iOSTestApplication.csproj
@@ -147,6 +147,10 @@
{d2221c82-4a25-4583-9b43-d791e3f6820c}
Perspex.Controls
+
+ {7062ae20-5dcc-4442-9645-8195bdece63e}
+ Perspex.Diagnostics
+
{5fb2b005-0a7f-4dad-add4-3ed01444e63d}
Perspex.HtmlRenderer