From b0f2d2343decd0198a383035a5cc4725185fa571 Mon Sep 17 00:00:00 2001 From: Bill Holmes Date: Fri, 20 Nov 2015 22:17:33 -0500 Subject: [PATCH] Adding Android Skia binding - Android binding project created - Using the system skia. Need to build the Android version. The system skia is not working on all devices. Guessing you need Android M. - Android Forms sample hooked up - Moved the upper left matrix change to the iOS native view. Otherwise Android has to apply it twice. --- .../Resources/AboutResources.txt | 44 +++++++++++++ .../Resources/Resource.designer.cs | 57 +++++++++++++++++ .../Resources/values/Strings.xml | 4 ++ .../SkiaSharp.Android.csproj | 63 +++++++++++++++++++ samples/Skia.Forms.Demo/DrawHelpers.cs | 4 -- .../Skia.Forms.Demo/Droid/NativeSkiaView.cs | 45 +++++++++++++ .../Droid/Resources/Resource.designer.cs | 17 +++++ .../Droid/Skia.Forms.Demo.Droid.csproj | 6 ++ .../Skia.Forms.Demo/Droid/SkiaViewRenderer.cs | 28 +++++++++ samples/Skia.Forms.Demo/Skia.Forms.Demo.sln | 14 +++++ samples/Skia.Forms.Demo/iOS/NativeSkiaView.cs | 8 ++- 11 files changed, 284 insertions(+), 6 deletions(-) create mode 100644 binding/SkiaSharp.Android/Resources/AboutResources.txt create mode 100644 binding/SkiaSharp.Android/Resources/Resource.designer.cs create mode 100644 binding/SkiaSharp.Android/Resources/values/Strings.xml create mode 100644 binding/SkiaSharp.Android/SkiaSharp.Android.csproj create mode 100644 samples/Skia.Forms.Demo/Droid/NativeSkiaView.cs create mode 100644 samples/Skia.Forms.Demo/Droid/SkiaViewRenderer.cs diff --git a/binding/SkiaSharp.Android/Resources/AboutResources.txt b/binding/SkiaSharp.Android/Resources/AboutResources.txt new file mode 100644 index 00000000..10f52d46 --- /dev/null +++ b/binding/SkiaSharp.Android/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/binding/SkiaSharp.Android/Resources/Resource.designer.cs b/binding/SkiaSharp.Android/Resources/Resource.designer.cs new file mode 100644 index 00000000..27ac064a --- /dev/null +++ b/binding/SkiaSharp.Android/Resources/Resource.designer.cs @@ -0,0 +1,57 @@ +#pragma warning disable 1591 +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.17020 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +[assembly: Android.Runtime.ResourceDesignerAttribute("SkiaSharp.Android.Resource", IsApplication=false)] + +namespace SkiaSharp.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f020000 + public static int library_name = 2130837504; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/binding/SkiaSharp.Android/Resources/values/Strings.xml b/binding/SkiaSharp.Android/Resources/values/Strings.xml new file mode 100644 index 00000000..63d6df8d --- /dev/null +++ b/binding/SkiaSharp.Android/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + + SkiaSharp.Android + diff --git a/binding/SkiaSharp.Android/SkiaSharp.Android.csproj b/binding/SkiaSharp.Android/SkiaSharp.Android.csproj new file mode 100644 index 00000000..892ae71e --- /dev/null +++ b/binding/SkiaSharp.Android/SkiaSharp.Android.csproj @@ -0,0 +1,63 @@ + + + + Debug + AnyCPU + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {C737DC80-5B71-4B26-A2DC-DA30421788B0} + Library + SkiaSharp.Android + Assets + Resources + Resource + Resources\Resource.designer.cs + False + SkiaSharp + v4.3 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + None + false + true + + + full + true + bin\Release + prompt + 4 + false + false + true + + + + + + + + + + + Properties\SkiaSharpAssemblyInfo.cs + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/Skia.Forms.Demo/DrawHelpers.cs b/samples/Skia.Forms.Demo/DrawHelpers.cs index a29e7c85..77e6f77a 100644 --- a/samples/Skia.Forms.Demo/DrawHelpers.cs +++ b/samples/Skia.Forms.Demo/DrawHelpers.cs @@ -14,10 +14,6 @@ namespace Skia.Forms.Demo public static void DrawXamagon (SKCanvas canvas, int width, int height) { - // Set the origin to the top left - canvas.Scale (1, -1); - canvas.Translate (0, -height); - // Width 41.6587026 => 144.34135 // Height 56 => 147 diff --git a/samples/Skia.Forms.Demo/Droid/NativeSkiaView.cs b/samples/Skia.Forms.Demo/Droid/NativeSkiaView.cs new file mode 100644 index 00000000..9c8955c0 --- /dev/null +++ b/samples/Skia.Forms.Demo/Droid/NativeSkiaView.cs @@ -0,0 +1,45 @@ +using System; +using Android.Views; +using Android.Graphics; +using SkiaSharp; + +namespace Skia.Forms.Demo.Droid +{ + public class NativeSkiaView : View + { + private Bitmap bitmap; + SkiaView skiaView; + + public NativeSkiaView (Android.Content.Context context, SkiaView skiaView) : base (context) + { + this.skiaView = skiaView; + } + + protected override void OnDraw (Android.Graphics.Canvas canvas) + { + base.OnDraw (canvas); + + if (bitmap == null || bitmap.Width != canvas.Width || bitmap.Height != canvas.Height) { + if (bitmap != null) + bitmap.Dispose (); + + bitmap = Bitmap.CreateBitmap (canvas.Width, canvas.Height, Bitmap.Config.Argb8888); + } + + try + { + using (var surface = SKSurface.Create (canvas.Width, canvas.Height, SKColorType.Rgba_8888, SKAlphaType.Premul, bitmap.LockPixels (), canvas.Width * 4)) { + var skcanvas = surface.Canvas; + skcanvas.Scale (((float)canvas.Width)/(float)skiaView.Width, ((float)canvas.Height)/(float)skiaView.Height); + (skiaView as ISkiaViewController).SendDraw (skcanvas); + } + } + finally { + bitmap.UnlockPixels (); + } + + canvas.DrawBitmap (bitmap, 0, 0, null); + } + } +} + diff --git a/samples/Skia.Forms.Demo/Droid/Resources/Resource.designer.cs b/samples/Skia.Forms.Demo/Droid/Resources/Resource.designer.cs index 1879f4e1..134553fd 100644 --- a/samples/Skia.Forms.Demo/Droid/Resources/Resource.designer.cs +++ b/samples/Skia.Forms.Demo/Droid/Resources/Resource.designer.cs @@ -26,6 +26,7 @@ namespace Skia.Forms.Demo.Droid public static void UpdateIdValues() { + global::SkiaSharp.Android.Resource.String.library_name = global::Skia.Forms.Demo.Droid.Resource.String.library_name; } public partial class Attribute @@ -56,6 +57,22 @@ namespace Skia.Forms.Demo.Droid { } } + + public partial class String + { + + // aapt resource value: 0x7f030000 + public const int library_name = 2130903040; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } } } #pragma warning restore 1591 diff --git a/samples/Skia.Forms.Demo/Droid/Skia.Forms.Demo.Droid.csproj b/samples/Skia.Forms.Demo/Droid/Skia.Forms.Demo.Droid.csproj index f043b775..59344d99 100644 --- a/samples/Skia.Forms.Demo/Droid/Skia.Forms.Demo.Droid.csproj +++ b/samples/Skia.Forms.Demo/Droid/Skia.Forms.Demo.Droid.csproj @@ -63,11 +63,17 @@ {F750563C-EF08-4BCB-AF58-C98C307B01B5} Skia.Forms.Demo + + {C737DC80-5B71-4B26-A2DC-DA30421788B0} + SkiaSharp.Android + + + diff --git a/samples/Skia.Forms.Demo/Droid/SkiaViewRenderer.cs b/samples/Skia.Forms.Demo/Droid/SkiaViewRenderer.cs new file mode 100644 index 00000000..013f1334 --- /dev/null +++ b/samples/Skia.Forms.Demo/Droid/SkiaViewRenderer.cs @@ -0,0 +1,28 @@ +using System; +using Xamarin.Forms; +using Xamarin.Forms.Platform.Android; + +[assembly: ExportRenderer (typeof(Skia.Forms.Demo.SkiaView), typeof(Skia.Forms.Demo.Droid.SkiaViewRenderer))] + +namespace Skia.Forms.Demo.Droid +{ + public class SkiaViewRenderer : ViewRenderer + { + NativeSkiaView view; + + public SkiaViewRenderer () + { + } + + protected override void OnElementChanged (ElementChangedEventArgs e) + { + base.OnElementChanged (e); + + if (Control == null) { + view = new NativeSkiaView (Context, Element); + SetNativeControl (view); + } + } + } +} + diff --git a/samples/Skia.Forms.Demo/Skia.Forms.Demo.sln b/samples/Skia.Forms.Demo/Skia.Forms.Demo.sln index dc11f919..26c211c5 100644 --- a/samples/Skia.Forms.Demo/Skia.Forms.Demo.sln +++ b/samples/Skia.Forms.Demo/Skia.Forms.Demo.sln @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.iOS", "..\..\bind EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Portable", "..\..\binding\SkiaSharp.Portable\SkiaSharp.Portable.csproj", "{7AA90628-2FDD-4585-AF2F-CC51CFA8B52A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Android", "..\..\binding\SkiaSharp.Android\SkiaSharp.Android.csproj", "{C737DC80-5B71-4B26-A2DC-DA30421788B0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -59,6 +61,18 @@ Global {7AA90628-2FDD-4585-AF2F-CC51CFA8B52A}.Release|iPhone.Build.0 = Release|Any CPU {7AA90628-2FDD-4585-AF2F-CC51CFA8B52A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {7AA90628-2FDD-4585-AF2F-CC51CFA8B52A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|iPhone.Build.0 = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|Any CPU.Build.0 = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|iPhone.ActiveCfg = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|iPhone.Build.0 = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C737DC80-5B71-4B26-A2DC-DA30421788B0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {E2A02581-8F55-400F-951C-691EADFD7D3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2A02581-8F55-400F-951C-691EADFD7D3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2A02581-8F55-400F-951C-691EADFD7D3A}.Debug|iPhone.ActiveCfg = Debug|Any CPU diff --git a/samples/Skia.Forms.Demo/iOS/NativeSkiaView.cs b/samples/Skia.Forms.Demo/iOS/NativeSkiaView.cs index d9b7d4cb..77bea4e9 100644 --- a/samples/Skia.Forms.Demo/iOS/NativeSkiaView.cs +++ b/samples/Skia.Forms.Demo/iOS/NativeSkiaView.cs @@ -27,8 +27,12 @@ namespace Skia.Forms.Demo.iOS try { using (var surface = SKSurface.Create (width, height, SKColorType.Rgba_8888, SKAlphaType.Premul, buff, width * 4)) { - surface.Canvas.Scale (screenScale, screenScale); - skiaView.SendDraw (surface.Canvas); + var skcanvas = surface.Canvas; + + // 2 for one here. Scaling to the pixel size + moving the origin to the top left + skcanvas.Scale (screenScale, -screenScale); + skcanvas.Translate (0, (float)-Frame.Height); + skiaView.SendDraw (skcanvas); } using (var colorSpace = CoreGraphics.CGColorSpace.CreateDeviceRGB ()) {