Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions csharp/Facebook.Yoga/Facebook.Yoga.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Native.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaAlign.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaBaselineFunc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaConstants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaDimension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaDirection.cs" />
Expand Down
16 changes: 16 additions & 0 deletions csharp/Facebook.Yoga/Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ public static extern void YGInteropSetLogger(
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int YGNodeGetInstanceCount();

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int YGConfigGetInstanceCount();

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigSetExperimentalFeatureEnabled(
YGConfigHandle config,
Expand All @@ -149,6 +152,19 @@ public static extern bool YGConfigIsExperimentalFeatureEnabled(
YGConfigHandle config,
YogaExperimentalFeature feature);

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigSetUseWebDefaults(
YGConfigHandle config,
bool useWebDefaults);

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern bool YGConfigGetUseWebDefaults(YGConfigHandle config);

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigSetPointScaleFactor(
YGConfigHandle config,
float pixelsInPoint);

[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeInsertChild(
YGNodeHandle node,
Expand Down
72 changes: 72 additions & 0 deletions csharp/Facebook.Yoga/YogaConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

using System;

namespace Facebook.Yoga
{
public class YogaConfig
{
private Native.YGConfigHandle _ygConfig;

public YogaConfig()
{
_ygConfig = Native.YGConfigNew();
if (_ygConfig.IsInvalid)
{
throw new InvalidOperationException("Failed to allocate native memory");
}
}

internal Native.YGConfigHandle Handle
{
get {
return _ygConfig;
}
}

public void SetExperimentalFeatureEnabled(
YogaExperimentalFeature feature,
bool enabled)
{
Native.YGConfigSetExperimentalFeatureEnabled(_ygConfig, feature, enabled);
}

public bool IsExperimentalFeatureEnabled(YogaExperimentalFeature feature)
{
return Native.YGConfigIsExperimentalFeatureEnabled(_ygConfig, feature);
}

public bool UseWebDefaults
{
get
{
return Native.YGConfigGetUseWebDefaults(_ygConfig);
}

set
{
Native.YGConfigSetUseWebDefaults(_ygConfig, value);
}
}

public float PointScaleFactor
{
set
{
Native.YGConfigSetPointScaleFactor(_ygConfig, value);
}
}

public static int GetInstanceCount()
{
return Native.YGConfigGetInstanceCount();
}
}
}
47 changes: 11 additions & 36 deletions csharp/Facebook.Yoga/YogaNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,10 @@

namespace Facebook.Yoga
{
public class YogaConfig
{

private Native.YGConfigHandle _ygConfig;

public YogaConfig()
{
_ygConfig = Native.YGConfigNew();
if (_ygConfig.IsInvalid)
{
throw new InvalidOperationException("Failed to allocate native memory");
}
}

internal Native.YGConfigHandle Handle {
get {
return _ygConfig;
}
}

public void SetExperimentalFeatureEnabled(
YogaExperimentalFeature feature,
bool enabled)
{
Native.YGConfigSetExperimentalFeatureEnabled(_ygConfig, feature, enabled);
}

public bool IsExperimentalFeatureEnabled(YogaExperimentalFeature feature)
{
return Native.YGConfigIsExperimentalFeatureEnabled(_ygConfig, feature);
}

}

public partial class YogaNode : IEnumerable<YogaNode>
{
private Native.YGNodeHandle _ygNode;
private YogaConfig _config;
private WeakReference _parent;
private List<YogaNode> _children;
private MeasureFunction _measureFunction;
Expand Down Expand Up @@ -89,15 +56,23 @@ public YogaNode(YogaConfig config)
{
YogaLogger.Initialize();

_ygNode = Native.YGNodeNewWithConfig(config.Handle);
if (config != null)
{
_config = config;
_ygNode = Native.YGNodeNewWithConfig(_config.Handle);
}
else
{
_ygNode = Native.YGNodeNew();
}
if (_ygNode.IsInvalid)
{
throw new InvalidOperationException("Failed to allocate native memory");
}
}

public YogaNode(YogaNode srcNode)
: this()
: this(srcNode._config)
{
CopyStyle(srcNode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<Compile Include="$(MSBuildThisFileDirectory)YGMinMaxDimensionTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YGPaddingTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YGRoundingTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaConfigTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaNodeSpacingTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)YogaNodeTest.cs" />
</ItemGroup>
Expand Down
136 changes: 136 additions & 0 deletions csharp/tests/Facebook.Yoga/YogaConfigTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

using NUnit.Framework;
using System;

/**
* Tests for {@link YogaConfig}.
*/
namespace Facebook.Yoga
{
[TestFixture]
public class YogaConfigTest
{
[Test]
public void TestUseWebDefaults()
{
YogaNode node0 = new YogaNode(new YogaConfig{UseWebDefaults = true});
Assert.AreEqual(YogaFlexDirection.Row, node0.FlexDirection);

node0.Reset();
Assert.AreEqual(YogaFlexDirection.Row, node0.FlexDirection);

YogaConfig config = new YogaConfig();
config.UseWebDefaults = true;
YogaNode node1 = new YogaNode(config);
Assert.AreEqual(YogaFlexDirection.Row, node1.FlexDirection);

node1.Reset();
Assert.AreEqual(YogaFlexDirection.Row, node1.FlexDirection);
}

[Test]
public void TestDefaultConfig()
{
YogaNode node0 = new YogaNode();
Assert.AreEqual(YogaFlexDirection.Column, node0.FlexDirection);

YogaNode node1 = new YogaNode(new YogaConfig());
Assert.AreEqual(YogaFlexDirection.Column, node1.FlexDirection);
}

[Test]
public void TestCopyConstructor()
{
YogaNode srcNode = new YogaNode(new YogaConfig{UseWebDefaults = true});
YogaNode node0 = new YogaNode(srcNode);
Assert.AreEqual(YogaFlexDirection.Row, node0.FlexDirection);

node0.FlexDirection = YogaFlexDirection.Column;
Assert.AreEqual(YogaFlexDirection.Column, node0.FlexDirection);

node0.Reset();
Assert.AreEqual(YogaFlexDirection.Row, node0.FlexDirection);

YogaNode node1 = new YogaNode(srcNode)
{
FlexDirection = YogaFlexDirection.Column
};
Assert.AreEqual(YogaFlexDirection.Column, node1.FlexDirection);

node1.Reset();
Assert.AreEqual(YogaFlexDirection.Row, node1.FlexDirection);
}

public static void ForceGC()
{
YogaNodeTest.ForceGC();
}

[Test]
public void TestDestructor()
{
ForceGC();
int instanceCount = YogaConfig.GetInstanceCount();
TestDestructorForGC(instanceCount);
ForceGC();
Assert.AreEqual(instanceCount, YogaConfig.GetInstanceCount());
}

private void TestDestructorForGC(int instanceCount)
{
YogaConfig config = new YogaConfig();
Assert.IsNotNull(config);
Assert.AreEqual(instanceCount + 1, YogaConfig.GetInstanceCount());
config = null;
}

[Test]
public void TestRetainConfig()
{
ForceGC();
int nodeInstanceCount = YogaNode.GetInstanceCount();
int configInstanceCount = YogaConfig.GetInstanceCount();
TestRetainConfigForGC(nodeInstanceCount, configInstanceCount);
ForceGC();

Assert.AreEqual(nodeInstanceCount, YogaNode.GetInstanceCount());
Assert.AreEqual(configInstanceCount, YogaConfig.GetInstanceCount());
}

private void TestRetainConfigForGC(int nodeInstanceCount, int configInstanceCount)
{
ForceGC();
Assert.AreEqual(nodeInstanceCount, YogaNode.GetInstanceCount());
Assert.AreEqual(configInstanceCount, YogaConfig.GetInstanceCount());
YogaNode node = TestRetainConfigForGC2(nodeInstanceCount, configInstanceCount);
ForceGC();
Assert.IsNotNull(node);
Assert.AreEqual(configInstanceCount + 1, YogaConfig.GetInstanceCount());
Assert.AreEqual(nodeInstanceCount + 1, YogaNode.GetInstanceCount());
node = null;
}

private YogaNode TestRetainConfigForGC2(int nodeInstanceCount, int configInstanceCount)
{
YogaConfig config = new YogaConfig();
Assert.IsNotNull(config);
Assert.AreEqual(configInstanceCount + 1, YogaConfig.GetInstanceCount());

YogaNode node = new YogaNode(config);
Assert.IsNotNull(node);
Assert.AreEqual(nodeInstanceCount + 1, YogaNode.GetInstanceCount());

config = null;

return node;
}
}
}
2 changes: 1 addition & 1 deletion csharp/tests/Facebook.Yoga/YogaNodeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public void TestCopyConstructor()
Assert.AreEqual(90.Pt(), node4.MaxHeight);
}

private void ForceGC()
public static void ForceGC()
{
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Expand Down
10 changes: 9 additions & 1 deletion yoga/Yoga.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ static inline float YGResolveValueMargin(const YGValue *const value, const float
}

int32_t gNodeInstanceCount = 0;
int32_t gConfigInstanceCount = 0;

WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
const YGNodeRef node = gYGMalloc(sizeof(YGNode));
Expand Down Expand Up @@ -373,15 +374,21 @@ int32_t YGNodeGetInstanceCount(void) {
return gNodeInstanceCount;
}

int32_t YGConfigGetInstanceCount(void) {
return gConfigInstanceCount;
}

YGConfigRef YGConfigNew(void) {
const YGConfigRef config = gYGMalloc(sizeof(YGConfig));
YG_ASSERT(config, "Could not allocate memory for config");
gConfigInstanceCount++;
memcpy(config, &gYGConfigDefaults, sizeof(YGConfig));
return config;
}

void YGConfigFree(const YGConfigRef config) {
gYGFree(config);
gConfigInstanceCount--;
}

static void YGNodeMarkDirtyInternal(const YGNodeRef node) {
Expand Down Expand Up @@ -3468,7 +3475,8 @@ bool YGConfigGetUseWebDefaults(const YGConfigRef config) {
}

void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree) {
YG_ASSERT(gNodeInstanceCount == 0, "Cannot set memory functions: all node must be freed first");
YG_ASSERT(gNodeInstanceCount == 0 && gConfigInstanceCount == 0,
"Cannot set memory functions: all node must be freed first");
YG_ASSERT((ygmalloc == NULL && yccalloc == NULL && ygrealloc == NULL && ygfree == NULL) ||
(ygmalloc != NULL && yccalloc != NULL && ygrealloc != NULL && ygfree != NULL),
"Cannot set memory functions: functions must be all NULL or Non-NULL");
Expand Down