From 1a6f37c20c4def847b21ee22f4ffb9f2e79e7c52 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Thu, 9 Feb 2017 17:01:41 +0000 Subject: [PATCH 1/3] [csharp] Add YogaDisplay to shared project --- csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems b/csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems index 1a641829..3b51cd94 100644 --- a/csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems +++ b/csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems @@ -18,6 +18,7 @@ + @@ -37,4 +38,4 @@ - + \ No newline at end of file -- 2.50.1.windows.1 From f90633cec59e07de19344e5f51a4ea9ecda957c9 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Fri, 10 Feb 2017 15:45:15 +0000 Subject: [PATCH 2/3] [csharp] Implement static methods for callbacks so they work on aot on iOS, use YogaRef to store pointer to managed YogaNode --- csharp/Facebook.Yoga/Native.cs | 7 +++++ csharp/Facebook.Yoga/YogaLogger.cs | 22 +++++++++++++++ csharp/Facebook.Yoga/YogaNode.cs | 45 ++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/csharp/Facebook.Yoga/Native.cs b/csharp/Facebook.Yoga/Native.cs index 2c0d25ac..d00679bc 100644 --- a/csharp/Facebook.Yoga/Native.cs +++ b/csharp/Facebook.Yoga/Native.cs @@ -111,6 +111,13 @@ namespace Facebook.Yoga [return: MarshalAs(UnmanagedType.I1)] public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node); + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern void YGNodeSetContext(YGNodeHandle node, IntPtr context); + + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr YGNodeGetContext(IntPtr node); + + #endregion #region YG_NODE_STYLE_PROPERTY diff --git a/csharp/Facebook.Yoga/YogaLogger.cs b/csharp/Facebook.Yoga/YogaLogger.cs index e5d79b79..52731af7 100644 --- a/csharp/Facebook.Yoga/YogaLogger.cs +++ b/csharp/Facebook.Yoga/YogaLogger.cs @@ -37,9 +37,31 @@ namespace Facebook.Yoga throw new InvalidOperationException(message); } }; +#if __IOS__ + Native.YGInteropSetLogger(ManagedLogger); +#else Native.YGInteropSetLogger(_managedLogger); +#endif _initialized = true; } } + +#if __IOS__ + delegate void ManagedLoggerCallback(YogaLogLevel level, string message); + + [ObjCRuntime.MonoPInvokeCallback(typeof(ManagedLoggerCallback))] + public static void ManagedLogger(YogaLogLevel level, string message) + { + if (Logger != null) + { + Logger(level, message); + } + + if (level == YogaLogLevel.Error) + { + throw new InvalidOperationException(message); + } + } +#endif } } diff --git a/csharp/Facebook.Yoga/YogaNode.cs b/csharp/Facebook.Yoga/YogaNode.cs index 59b6ae08..02d51c28 100644 --- a/csharp/Facebook.Yoga/YogaNode.cs +++ b/csharp/Facebook.Yoga/YogaNode.cs @@ -10,6 +10,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Text; namespace Facebook.Yoga @@ -532,7 +533,7 @@ namespace Facebook.Yoga { while (_children.Count > 0) { - RemoveAt(_children.Count-1); + RemoveAt(_children.Count - 1); } } } @@ -546,6 +547,10 @@ namespace Facebook.Yoga { _measureFunction = measureFunction; _ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null; + + var handle = GCHandle.Alloc(this); + Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle)); + Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc); } @@ -553,6 +558,10 @@ namespace Facebook.Yoga { _baselineFunction = baselineFunction; _ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null; + + var handle = GCHandle.Alloc(this); + Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle)); + Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc); } @@ -565,37 +574,55 @@ namespace Facebook.Yoga Native.YGNodeStyleGetDirection(_ygNode)); } - private YogaSize MeasureInternal( +#if __IOS__ + [ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))] +#endif + private static YogaSize MeasureInternal( IntPtr node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { - if (_measureFunction == null) + + var yogaNodePointer = Native.YGNodeGetContext(node); + + YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode; + + var measureFunction = yogaNode._measureFunction; + if (measureFunction == null) { throw new InvalidOperationException("Measure function is not defined."); } - return _measureFunction(this, width, widthMode, height, heightMode); + return measureFunction(yogaNode, width, widthMode, height, heightMode); } - private float BaselineInternal(IntPtr node, float width, float height) + +#if __IOS__ + [ObjCRuntime.MonoPInvokeCallback(typeof(YogaBaselineFunc))] +#endif + private static float BaselineInternal(IntPtr node, float width, float height) { - if (_baselineFunction == null) + var yogaNodePointer = Native.YGNodeGetContext(node); + + YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode; + + var baselineFunction = yogaNode._baselineFunction; + if (baselineFunction == null) { throw new InvalidOperationException("Baseline function is not defined."); } - return _baselineFunction(this, width, height); + return baselineFunction(yogaNode, width, height); } public string Print(YogaPrintOptions options = - YogaPrintOptions.Layout|YogaPrintOptions.Style|YogaPrintOptions.Children) + YogaPrintOptions.Layout | YogaPrintOptions.Style | YogaPrintOptions.Children) { StringBuilder sb = new StringBuilder(); YogaLogger.Func orig = YogaLogger.Logger; - YogaLogger.Logger = (level, message) => {sb.Append(message);}; + YogaLogger.Logger = (level, message) => { sb.Append(message); }; Native.YGNodePrint(_ygNode, options); YogaLogger.Logger = orig; return sb.ToString(); -- 2.50.1.windows.1 From 7cbfecd6a9c63a9f95a08b12cfac9bd682ba2299 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Fri, 10 Feb 2017 22:12:24 +0000 Subject: [PATCH 3/3] [csharp]Cleaner implementation on YogaLogger --- csharp/Facebook.Yoga/YogaLogger.cs | 48 ++++++++++-------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/csharp/Facebook.Yoga/YogaLogger.cs b/csharp/Facebook.Yoga/YogaLogger.cs index 52731af7..68d946e6 100644 --- a/csharp/Facebook.Yoga/YogaLogger.cs +++ b/csharp/Facebook.Yoga/YogaLogger.cs @@ -8,17 +8,14 @@ */ using System; -using System.Runtime.InteropServices; namespace Facebook.Yoga { internal static class YogaLogger { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Func(YogaLogLevel level, string message); private static bool _initialized; - private static Func _managedLogger = null; public static Func Logger = null; @@ -26,42 +23,27 @@ namespace Facebook.Yoga { if (!_initialized) { - _managedLogger = (level, message) => { - if (Logger != null) - { - Logger(level, message); - } - if (level == YogaLogLevel.Error) - { - throw new InvalidOperationException(message); - } - }; -#if __IOS__ - Native.YGInteropSetLogger(ManagedLogger); -#else - Native.YGInteropSetLogger(_managedLogger); -#endif + Native.YGInteropSetLogger(LoggerInternal); _initialized = true; } } #if __IOS__ - delegate void ManagedLoggerCallback(YogaLogLevel level, string message); - - [ObjCRuntime.MonoPInvokeCallback(typeof(ManagedLoggerCallback))] - public static void ManagedLogger(YogaLogLevel level, string message) - { - if (Logger != null) - { - Logger(level, message); - } - - if (level == YogaLogLevel.Error) - { - throw new InvalidOperationException(message); - } - } + [ObjCRuntime.MonoPInvokeCallback(typeof(Func))] #endif + public static void LoggerInternal(YogaLogLevel level, string message) + { + if (Logger != null) + { + Logger(level, message); + } + + if (level == YogaLogLevel.Error) + { + throw new InvalidOperationException(message); + } + } + } } -- 2.50.1.windows.1