Compare commits

...

25 Commits

Author SHA1 Message Date
Pascal Hartig
adb1b11055 1.8.0
Summary: New release.

Reviewed By: marco-cova

Differential Revision: D7550852

fbshipit-source-id: eac5662179daa88d9d62c55566b3a31428c4117a
2018-04-09 02:41:21 -07:00
David Vacca
2e234473ca [yoga re-add assertion to check for owner reference before adding child.
Summary: this diff re-add the assertion to check for owner reference before adding child that was removed by mistake in previous diff

Reviewed By: emilsjolander

Differential Revision: D7495417

fbshipit-source-id: b81174aeea3f2796d76ccdae4a8eddd0beace0aa
2018-04-04 10:57:52 -07:00
Lukas Wöhrl
6b08db68bb Fix compilation on MSVC by moving YGConfig to C++
Summary:
This PR fixes the compilation on MSVC. I moved the `YGConfig` creation to a C++ constructor.

Addionally it removes the "dot" notation on `YGValue`, I didn't want to change that type to a C++ constructor, because I think this will break the ABI.
Closes https://github.com/facebook/yoga/pull/746

Differential Revision: D7498141

Pulled By: emilsjolander

fbshipit-source-id: 5f5308ff838dcd803065785ddc08b2404524acb9
2018-04-04 09:55:45 -07:00
Pritesh Nandgaonkar
9550126f76 clean up experimental setup and keep using ffast-math flag
Summary: Remove experimental setup of fast-math and add `-ffast-math` as a compiler flag for yoga.

Reviewed By: emilsjolander

Differential Revision: D7414228

fbshipit-source-id: 320e1b1953f6af867b13e617af7872eb8999160e
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
bad262b961 Change the return type of getMarginForAxis to YGFloatOptional
Summary: Change the return type of getMarginForAxis to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7350337

fbshipit-source-id: dd1ee2fcd295ccd14f7d414ab0c24090b24e91e0
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
3c6c10075a Change the return type of getTrailingMargin to YGFloatOptional
Summary: Change the return type of getTrailingMargin to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7350221

fbshipit-source-id: 61a67364c1975ec6dd1883bc2cb4968b830c73df
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
6a77a6939e Changed the return type of getLeadingMargin to YGFloatOptional
Summary: Changed the return type of getLeadingMargin to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7349907

fbshipit-source-id: b20894fbc33fd5b29a28f3c9174d1b5f406774ab
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
b725a4a140 Refactored relativePosition private method to YGFloatOptional return type
Summary: Refactored relativePosition private method to YGFloatOptional return type

Reviewed By: emilsjolander

Differential Revision: D7344939

fbshipit-source-id: 72443d38426a211d3e84be814e6a61baf4d26703
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
2b714a5b5d Change the type of getTrailingPosition to YGFloatOptional
Summary: Change the type of getTrailingPosition to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7344710

fbshipit-source-id: eb4c422b6e0f55d90b083221aa8ff1ab797d58a8
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
572546088f Changed the type of return value of getLeadingPosition to YGFloatOptional
Summary: Changed the type of return value of getLeadingPosition to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7344367

fbshipit-source-id: 0f5a667ca357b2ce056c86763aa3e9e4c54b82f0
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
5b109578d3 Changed the type of computedFlexBasis to YGFloatOptional in YGLayout
Summary: Changed the type of computedFlexBasis to YGFloatOptional in YGLayout

Reviewed By: emilsjolander

Differential Revision: D7340413

fbshipit-source-id: 39247b2b582a682e602f49f58b4bbd2bf0c995af
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
77b720f9a5 Fixed types of getLeadingPaddingAndBorder and getTrailingPaddingAndBorder to YGFloatOptional
Summary: Fixed types of getLeadingPaddingAndBorder and getTrailingPaddingAndBorder to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7339998

fbshipit-source-id: aa24335c2db1cd895b9711214b72195add718c32
2018-04-04 08:29:43 -07:00
Pritesh Nandgaonkar
de954eb9cc Changed the return type of trailing padding to YGFloatOptional
Summary: Changed the return type of trailing padding to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7339712

fbshipit-source-id: 483c5886838c14b17cb731c81abb9fc80f519956
2018-04-04 08:29:42 -07:00
Pritesh Nandgaonkar
3e322e60e4 Updated the implementation of leading padding
Summary: Changed the arguments for the getter of leading padding to avoid copies. Added an assetion in getter of leading padding, as padding would always be defined even in the case when the user has not explicitly defined the value. In these cases it would take the default value of 0. So changing the type of `getLayoutPadding` to `YGFloatOptional`, doesn't make sense.

Reviewed By: emilsjolander

Differential Revision: D7336690

fbshipit-source-id: b2a2f010026f26fc2cc9fb35ad921da8f7017c9f
2018-04-04 08:29:42 -07:00
Pritesh Nandgaonkar
a3642541d0 Make the return type of YGNodeBoundAxisWithinMinAndMax to YGFloatOptional
Summary: Make the return type of YGNodeBoundAxisWithinMinAndMax to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7323382

fbshipit-source-id: 8e3eb4f3744b5f3f9e2b353f56184905f7557191
2018-04-04 08:29:42 -07:00
Pritesh Nandgaonkar
bb139d3f91 Remove the use of YGUnwrapOptional from YGConstrainedMaxSizeForMode
Summary: Remove the use of YGUnwrapOptional from YGConstrainedMaxSizeForMode

Reviewed By: emilsjolander

Differential Revision: D7322743

fbshipit-source-id: d825c60bcdc9ecdc0c784a215dc6b1b8a7a7860e
2018-04-04 08:29:42 -07:00
Pritesh Nandgaonkar
08743a42e2 Made the acccessors method to return const references
Summary: Made the acccessors method to return const references

Reviewed By: emilsjolander

Differential Revision: D7321801

fbshipit-source-id: 9fc4da724bc2f58a0d95824ca3c0b5bf1690bccf
2018-04-04 08:29:42 -07:00
Lukas Wöhrl
cb6e76973d Fix float type mismatch on endOfLineIndex and inside rounding
Summary:
This PR fixes a type mismatch on `endOfLineIndex` where it should be of type `uint32_t` while it is of type `float`

Additonally it fixes some `double` casting in the rounding methods.
Closes https://github.com/facebook/yoga/pull/745

Differential Revision: D7494519

Pulled By: emilsjolander

fbshipit-source-id: 30a86574ce163458a6888f61a902d0640c1874fb
2018-04-04 07:04:23 -07:00
Pritesh Nandgaonkar
4b760fa9bc Changed the return type of YGResolveValueMargin to YGFloatOptional
Summary: Changed the return type of YGResolveValueMargin to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7304090

fbshipit-source-id: cbec03a9367cf34976d083ad475d4da0b736e6d2
2018-04-03 15:12:07 -07:00
Pritesh Nandgaonkar
5730be093e Move equaltiy function from utils to an operator on YGFloatOptional
Summary: Move equaltiy function from utils to an operator on YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7303460

fbshipit-source-id: 41ec0076ace621ec1a5bdbab00b72eea57780fff
2018-04-03 15:12:05 -07:00
Pritesh Nandgaonkar
d85e2ee9c3 Change the type of aspect Ratio to YGFloatOptional
Summary: Change the type of aspect Ratio to YGFloatOptional

Reviewed By: emilsjolander

Differential Revision: D7302651

fbshipit-source-id: 53e3b4c9627207a379f927b1f3485e36a9c70601
2018-04-03 15:12:02 -07:00
Pritesh Nandgaonkar
fe433b012f Remove the usage of YGUndefined for kYGValueAuto and fix setter and getter of dimensions
Summary: Removes the use of YGUndefined from kYGValueAuto. Also fixed the setter and getter of dimensions. This diff also fixes a typo

Reviewed By: emilsjolander

Differential Revision: D7302453

fbshipit-source-id: e002a1ddd75bfc6fe142a7275e7913c064972e16
2018-04-03 15:11:58 -07:00
David Vacca
5e3ffb39a2 Extend Yoga to be able clone Yoga Node with new children
Summary:
This diff includes the following changes:

1 ) I extended the Java implementation of YogaNode to be able to get a full copy of a YogaNode object without copying the List of children of the original YogaNode. In other words, the new copy of the YogaNode will have the same data of the original YogaNode, but with an empty list of children.

2 ) We created a new method in Yoga.cpp called YGNodeInsertSharedChild. This new method is going to be used by Fabric in order to temporarily share a YogaNode between two "Yoga Trees" (the "current Yoga" tree and a partial "clone of the current Yoga tree"). We exposed this new functionality in the java implementation of Yoga (method addSharedChildAt)

I'm including sebmarkbage for more context.

Reviewed By: emilsjolander

Differential Revision: D7245421

fbshipit-source-id: 72578c8261f29e4a12fc6c72a91f2f891cd58d48
2018-04-01 18:35:13 -07:00
David Vacca
f0edefdbb7 Rename YogaNode.parent -> YogaNode.owner
Summary:
In the persistent version of Yoga, a YogaNode can be shared between two YogaTrees, that means that a YogaNode could have more than one Parent at one point in time. That's why the concept of Parent of a YogaNode is not a 1-1 relationship anymore.
This diff changes the semantic of Parent of a YogaNode to Owner of a Yoga Node. CC sebmarkbage and priteshrnandgaonkar for more context.

Technically this diff renames the field YogaNode.parent to YogaNode.owner (and every internal field, Getter and Setter that is related to parent)

Note that as part of this diff I also modified the CSSLayoutDEPRECATED version of Yoga in order to keep compatibility with the C++ implementation.

Reviewed By: priteshrnandgaonkar

Differential Revision: D7352778

fbshipit-source-id: dcf1af5e72bfc3063b5c4bda197d7952a9194768
2018-04-01 18:35:13 -07:00
David Vacca
17901ea5c2 Refactor cloning of YogaNode
Summary: see Test Plan

Reviewed By: priteshrnandgaonkar

Differential Revision: D7339832

fbshipit-source-id: 2de6f47ae7601ac083d3b9fbe10ffaf6307ae760
2018-04-01 18:35:13 -07:00
29 changed files with 1267 additions and 891 deletions

14
BUCK
View File

@@ -32,20 +32,6 @@ cxx_library(
],
)
cxx_library(
name = "yogafastmath",
srcs = glob(["yoga/*.cpp"]),
header_namespace = "",
exported_headers = subdir_glob([("", "yoga/*.h")]),
compiler_flags = COMPILER_FLAGS + ["-ffast-math"],
soname = "libyogafastmathcore.$(ext)",
tests = [":YogaTests"],
visibility = ["PUBLIC"],
deps = [
yoga_dep("lib/fb:ndklog"),
],
)
cxx_test(
name = "YogaTests",
srcs = glob(["tests/*.cpp"]),

View File

@@ -46,14 +46,14 @@ import java.util.Map;
* <YogaLayout
* xmlns:android="http://schemas.android.com/apk/res/android"
* xmlns:yoga="http://schemas.android.com/apk/com.facebook.yoga.android"
* android:layout_width="match_parent"
* android:layout_height="match_parent"
* android:layout_width="match_owner"
* android:layout_height="match_owner"
* yoga:flex_direction="row"
* yoga:padding_all="10dp"
* >
* <TextView
* android:layout_width="match_parent"
* android:layout_height="match_parent"
* android:layout_width="match_owner"
* android:layout_height="match_owner"
* android:text="Hello, World!"
* yoga:flex="1"
* />
@@ -262,11 +262,11 @@ public class YogaLayout extends ViewGroup {
return;
}
final YogaNode parent = node.getParent();
final YogaNode owner = node.getOwner();
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i).equals(node)) {
parent.removeChildAt(i);
for (int i = 0; i < owner.getChildCount(); i++) {
if (owner.getChildAt(i).equals(node)) {
owner.removeChildAt(i);
break;
}
}
@@ -315,7 +315,7 @@ public class YogaLayout extends ViewGroup {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Either we are a root of a tree, or this function is called by our parent's onLayout, in which
// Either we are a root of a tree, or this function is called by our owner's onLayout, in which
// case our r-l and b-t are the size of our node.
if (!(getParent() instanceof YogaLayout)) {
createLayout(
@@ -699,7 +699,7 @@ public class YogaLayout extends ViewGroup {
/**
* Constructs a set of layout params, given width and height specs. In this case, we can set
* the {@code yoga:width} and {@code yoga:height} if we are given them explicitly. If other
* options (such as {@code match_parent} or {@code wrap_content} are given, then the parent
* options (such as {@code match_owner} or {@code wrap_content} are given, then the owner
* LayoutParams will store them, and we deal with them during layout. (see
* {@link YogaLayout#createLayout})
*
@@ -773,9 +773,9 @@ public class YogaLayout extends ViewGroup {
* {@code View}'s measure function.
*
* @param node The yoga node to measure
* @param width The suggested width from the parent
* @param width The suggested width from the owner
* @param widthMode The type of suggestion for the width
* @param height The suggested height from the parent
* @param height The suggested height from the owner
* @param heightMode The type of suggestion for the height
* @return A measurement output ({@code YogaMeasureOutput}) for the node
*/

View File

@@ -227,19 +227,31 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\yoga\Yoga.h" />
<ClInclude Include="..\..\yoga\Utils.h" />
<ClInclude Include="..\..\yoga\YGConfig.h" />
<ClInclude Include="..\..\yoga\YGEnums.h" />
<ClInclude Include="..\..\yoga\YGFloatOptional.h" />
<ClInclude Include="..\..\yoga\YGLayout.h" />
<ClInclude Include="..\..\yoga\YGMacros.h" />
<ClInclude Include="..\..\yoga\YGNodeList.h" />
<ClInclude Include="..\..\yoga\YGNode.h" />
<ClInclude Include="..\..\yoga\YGNodePrint.h" />
<ClInclude Include="..\..\yoga\YGStyle.h" />
<ClInclude Include="..\..\yoga\Yoga-internal.h" />
<ClInclude Include="..\..\yoga\Yoga.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="YGInterop.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\yoga\Yoga.c" />
<ClCompile Include="..\..\yoga\YGEnums.c" />
<ClCompile Include="..\..\yoga\YGNodeList.c" />
<ClCompile Include="..\..\yoga\Utils.cpp" />
<ClCompile Include="..\..\yoga\YGConfig.cpp" />
<ClCompile Include="..\..\yoga\YGEnums.cpp" />
<ClCompile Include="..\..\yoga\YGFloatOptional.cpp" />
<ClCompile Include="..\..\yoga\YGLayout.cpp" />
<ClCompile Include="..\..\yoga\YGNode.cpp" />
<ClCompile Include="..\..\yoga\YGNodePrint.cpp" />
<ClCompile Include="..\..\yoga\YGStyle.cpp" />
<ClCompile Include="..\..\yoga\Yoga.cpp" />
<ClCompile Include="YGInterop.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>

View File

@@ -21,19 +21,40 @@
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\Yoga.h">
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGEnums.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGFloatOptional.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGLayout.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGMacros.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGNodeList.h">
<ClInclude Include="..\..\yoga\YGNode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YGInterop.h">
<ClInclude Include="..\..\yoga\YGNodePrint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<ClInclude Include="..\..\yoga\YGStyle.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\Yoga.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\Yoga-internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\yoga\YGConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@@ -44,15 +65,36 @@
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\Yoga.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGNodeList.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YGInterop.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGEnums.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGFloatOptional.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGLayout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGNodePrint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGStyle.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\Yoga.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\yoga\YGConfig.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Yoga.rc">

View File

@@ -2,7 +2,7 @@
org.gradle.jvmargs=-Xmx1536M
VERSION_NAME=1.7.1-SNAPSHOT
VERSION_NAME=1.8.0
POM_URL=https://github.com/facebook/yoga
POM_SCM_URL=https://github.com/facebook/yoga.git
POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git

View File

@@ -28,29 +28,6 @@ cxx_library(
],
)
cxx_library(
name = "jniFastMath",
srcs = glob(["jni/*.cpp"]),
header_namespace = "",
compiler_flags = [
"-fno-omit-frame-pointer",
"-fexceptions",
"-fPIC",
"-Wall",
"-Werror",
"-O3",
"-std=c++11",
],
platforms = ANDROID,
soname = "libyogafastmath.$(ext)",
visibility = ["PUBLIC"],
deps = [
FBJNI_TARGET,
JNI_TARGET,
yoga_dep(":yogafastmath"),
],
)
java_library(
name = "java",
srcs = glob(["com/facebook/yoga/*.java"]),
@@ -63,7 +40,6 @@ java_library(
visibility = ["PUBLIC"],
deps = [
":jni",
":jniFastMath",
INFER_ANNOTATIONS_TARGET,
JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET,

View File

@@ -16,16 +16,12 @@ public class YogaConfig {
public static int SPACING_TYPE = 1;
static {
if (YogaConstants.shouldUseFastMath) {
SoLoader.loadLibrary("yogafastmath");
} else {
SoLoader.loadLibrary("yoga");
}
}
long mNativePointer;
private YogaLogger mLogger;
private YogaNodeClonedFunction mNodeClonedFunction;
private YogaNodeCloneFunction mYogaNodeCloneFunction;
private native long jni_YGConfigNew();
public YogaConfig() {
@@ -97,16 +93,15 @@ public class YogaConfig {
return mLogger;
}
private native void jni_YGConfigSetHasNodeClonedFunc(long nativePointer, boolean hasClonedFunc);
private native void jni_YGConfigSetHasCloneNodeFunc(long nativePointer, boolean hasClonedFunc);
public void setOnNodeCloned(YogaNodeClonedFunction nodeClonedFunction) {
mNodeClonedFunction = nodeClonedFunction;
jni_YGConfigSetHasNodeClonedFunc(mNativePointer, nodeClonedFunction != null);
public void setOnCloneNode(YogaNodeCloneFunction cloneYogaNodeFunction) {
mYogaNodeCloneFunction = cloneYogaNodeFunction;
jni_YGConfigSetHasCloneNodeFunc(mNativePointer, cloneYogaNodeFunction != null);
}
@DoNotStrip
public final void onNodeCloned(
YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex) {
mNodeClonedFunction.onNodeCloned(oldNode, newNode, parent, childIndex);
private final YogaNode cloneNode(YogaNode oldNode, YogaNode parent, int childIndex) {
return mYogaNodeCloneFunction.cloneNode(oldNode, parent, childIndex);
}
}

View File

@@ -18,8 +18,6 @@ public class YogaConstants {
*/
public static final float UNDEFINED = (float) (10E20);
public static boolean shouldUseFastMath = false;
public static boolean isUndefined(float value) {
// Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN,
// the benefit of which

View File

@@ -17,11 +17,7 @@ import javax.annotation.Nullable;
public class YogaNode implements Cloneable {
static {
if (YogaConstants.shouldUseFastMath) {
SoLoader.loadLibrary("yogafastmath");
} else {
SoLoader.loadLibrary("yoga");
}
}
/**
@@ -29,8 +25,8 @@ public class YogaNode implements Cloneable {
*/
static native int jni_YGNodeGetInstanceCount();
private YogaNode mParent;
private List<YogaNode> mChildren;
private YogaNode mOwner;
@Nullable private List<YogaNode> mChildren;
private YogaMeasureFunction mMeasureFunction;
private YogaBaselineFunction mBaselineFunction;
private long mNativePointer;
@@ -147,12 +143,15 @@ public class YogaNode implements Cloneable {
}
public YogaNode getChildAt(int i) {
if (mChildren == null) {
throw new IllegalStateException("YogaNode does not have children");
}
return mChildren.get(i);
}
private native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index);
public void addChildAt(YogaNode child, int i) {
if (child.mParent != null) {
if (child.mOwner != null) {
throw new IllegalStateException("Child already has a parent, it must be removed first.");
}
@@ -160,35 +159,84 @@ public class YogaNode implements Cloneable {
mChildren = new ArrayList<>(4);
}
mChildren.add(i, child);
child.mParent = this;
child.mOwner = this;
jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i);
}
private native void jni_YGNodeInsertSharedChild(long nativePointer, long childPointer, int index);
public void addSharedChildAt(YogaNode child, int i) {
if (mChildren == null) {
mChildren = new ArrayList<>(4);
}
mChildren.add(i, child);
child.mOwner = null;
jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i);
}
private native long jni_YGNodeClone(long nativePointer, Object newNode);
@Override
public YogaNode clone() throws CloneNotSupportedException {
YogaNode clonedYogaNode = (YogaNode) super.clone();
long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode);
clonedYogaNode.mNativePointer = clonedNativePointer;
clonedYogaNode.mChildren =
mChildren != null ? (List<YogaNode>) ((ArrayList) mChildren).clone() : null;
return clonedYogaNode;
public YogaNode clone() {
try {
YogaNode clonedYogaNode = (YogaNode) super.clone();
long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode);
clonedYogaNode.mNativePointer = clonedNativePointer;
clonedYogaNode.mOwner = null;
clonedYogaNode.mChildren =
mChildren != null ? (List<YogaNode>) ((ArrayList) mChildren).clone() : null;
return clonedYogaNode;
} catch (CloneNotSupportedException ex) {
// This class implements Cloneable, this should not happen
throw new RuntimeException(ex);
}
}
public YogaNode cloneWithNewChildren() {
try {
YogaNode clonedYogaNode = (YogaNode) super.clone();
long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode);
clonedYogaNode.mOwner = null;
clonedYogaNode.mNativePointer = clonedNativePointer;
clonedYogaNode.clearChildren();
return clonedYogaNode;
} catch (CloneNotSupportedException ex) {
// This class implements Cloneable, this should not happen
throw new RuntimeException(ex);
}
}
private native void jni_YGNodeClearChildren(long nativePointer);
private void clearChildren() {
mChildren = null;
jni_YGNodeClearChildren(mNativePointer);
}
private native void jni_YGNodeRemoveChild(long nativePointer, long childPointer);
public YogaNode removeChildAt(int i) {
if (mChildren == null) {
throw new IllegalStateException(
"Trying to remove a child of a YogaNode that does not have children");
}
final YogaNode child = mChildren.remove(i);
child.mParent = null;
child.mOwner = null;
jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer);
return child;
}
/**
* @returns the {@link YogaNode} that owns this {@link YogaNode}.
* The owner is used to identify the YogaTree that a {@link YogaNode} belongs
* to.
* This method will return the parent of the {@link YogaNode} when the
* {@link YogaNode} only belongs to one YogaTree or null when the
* {@link YogaNode} is shared between two or more YogaTrees.
*/
@Nullable
public
YogaNode getParent() {
return mParent;
YogaNode getOwner() {
return mOwner;
}
public int indexOf(YogaNode child) {
@@ -697,4 +745,22 @@ public class YogaNode implements Cloneable {
public void print() {
jni_YGNodePrint(mNativePointer);
}
/**
* This method replaces the child at childIndex position with the newNode received by parameter.
* This is different than calling removeChildAt and addChildAt because this method ONLY replaces
* the child in the mChildren datastructure. @DoNotStrip: called from JNI
*
* @return the nativePointer of the newNode {@linl YogaNode}
*/
@DoNotStrip
private final long replaceChild(YogaNode newNode, int childIndex) {
if (mChildren == null) {
throw new IllegalStateException("Cannot replace child. YogaNode does not have children");
}
mChildren.remove(childIndex);
mChildren.add(childIndex, newNode);
newNode.mOwner = this;
return newNode.mNativePointer;
}
}

View File

@@ -10,8 +10,8 @@ package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public interface YogaNodeClonedFunction {
public interface YogaNodeCloneFunction {
@DoNotStrip
void onNodeCloned(YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex);
YogaNode cloneNode(YogaNode oldNode, YogaNode parent, int childIndex);
}

View File

@@ -142,31 +142,49 @@ static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) {
}
}
static void YGJNIOnNodeClonedFunc(
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
}
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
}
static YGNodeRef YGJNIOnNodeClonedFunc(
YGNodeRef oldNode,
YGNodeRef newNode,
YGNodeRef parent,
YGNodeRef owner,
int childIndex) {
auto config = oldNode->getConfig();
if (!config) {
return;
return nullptr;
}
static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig")
->getMethod<void(
->getMethod<alias_ref<JYogaNode>(
local_ref<JYogaNode>,
local_ref<JYogaNode>,
local_ref<JYogaNode>,
jint)>("onNodeCloned");
jint)>("cloneNode");
auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config));
auto javaConfig = context->config;
onNodeClonedFunc(
auto newNode = onNodeClonedFunc(
javaConfig->get(),
YGNodeJobject(oldNode)->lockLocal(),
YGNodeJobject(newNode)->lockLocal(),
YGNodeJobject(parent)->lockLocal(),
YGNodeJobject(owner)->lockLocal(),
childIndex);
static auto replaceChild = findClassStatic("com/facebook/yoga/YogaNode")
->getMethod<jlong(
local_ref<JYogaNode>,
jint)>("replaceChild");
jlong newNodeNativePointer = replaceChild(
YGNodeJobject(owner)->lockLocal(),
newNode,
childIndex);
return _jlong2YGNodeRef(newNodeNativePointer);
}
static YGSize YGJNIMeasureFunc(
@@ -234,14 +252,6 @@ static int YGJNILogFunc(const YGConfigRef config,
return result;
}
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
}
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
}
jlong jni_YGNodeNew(alias_ref<jobject> thiz) {
const YGNodeRef node = YGNodeNew();
node->setContext(new weak_ref<jobject>(make_weak(thiz)));
@@ -274,6 +284,11 @@ void jni_YGNodeFree(alias_ref<jobject> thiz, jlong nativePointer) {
YGNodeFree(node);
}
void jni_YGNodeClearChildren(alias_ref<jobject> thiz, jlong nativePointer) {
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
node->clearChildren();
}
void jni_YGNodeReset(alias_ref<jobject> thiz, jlong nativePointer) {
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
void* context = node->getContext();
@@ -293,6 +308,15 @@ void jni_YGNodeInsertChild(alias_ref<jobject>, jlong nativePointer, jlong childP
YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
}
void jni_YGNodeInsertSharedChild(
alias_ref<jobject>,
jlong nativePointer,
jlong childPointer,
jint index) {
YGNodeInsertSharedChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
}
void jni_YGNodeRemoveChild(alias_ref<jobject>, jlong nativePointer, jlong childPointer) {
YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
}
@@ -506,10 +530,10 @@ void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref<jobject>,
YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour);
}
void jni_YGConfigSetHasNodeClonedFunc(
void jni_YGConfigSetHasCloneNodeFunc(
alias_ref<jobject> thiz,
jlong nativePointer,
jboolean hasNodeClonedFunc) {
jboolean hasCloneNodeFunc) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config));
if (context && context->config) {
@@ -517,15 +541,15 @@ void jni_YGConfigSetHasNodeClonedFunc(
context->config = nullptr;
}
if (hasNodeClonedFunc) {
if (hasCloneNodeFunc) {
if (!context) {
context = new YGConfigContext();
YGConfigSetContext(config, context);
}
context->config = new global_ref<jobject>(make_global(thiz));
YGConfigSetNodeClonedFunc(config, YGJNIOnNodeClonedFunc);
YGConfigSetCloneNodeFunc(config, YGJNIOnNodeClonedFunc);
} else {
YGConfigSetNodeClonedFunc(config, nullptr);
YGConfigSetCloneNodeFunc(config, nullptr);
}
}
@@ -567,7 +591,9 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
YGMakeNativeMethod(jni_YGNodeNewWithConfig),
YGMakeNativeMethod(jni_YGNodeFree),
YGMakeNativeMethod(jni_YGNodeReset),
YGMakeNativeMethod(jni_YGNodeClearChildren),
YGMakeNativeMethod(jni_YGNodeInsertChild),
YGMakeNativeMethod(jni_YGNodeInsertSharedChild),
YGMakeNativeMethod(jni_YGNodeRemoveChild),
YGMakeNativeMethod(jni_YGNodeCalculateLayout),
YGMakeNativeMethod(jni_YGNodeMarkDirty),
@@ -652,7 +678,7 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor),
YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour),
YGMakeNativeMethod(jni_YGConfigSetLogger),
YGMakeNativeMethod(jni_YGConfigSetHasNodeClonedFunc),
YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc),
YGMakeNativeMethod(
jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour),
});

View File

@@ -10,6 +10,7 @@ package com.facebook.yoga;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -251,16 +252,58 @@ public class YogaNodeTest {
assertEquals(1, clonedChild.getChildCount());
}
@Test
public void testCloneWithNewChildren() throws Exception {
YogaConfig config = new YogaConfig();
YogaNode root = new YogaNode(config);
YogaNode child = new YogaNode(config);
YogaNode grandChild = new YogaNode(config);
root.addChildAt(child, 0);
child.addChildAt(grandChild, 0);
child.setFlexDirection(YogaFlexDirection.ROW);
YogaNode clonedChild = child.cloneWithNewChildren();
assertNotSame(clonedChild, child);
assertEquals(YogaFlexDirection.ROW, clonedChild.getFlexDirection());
assertEquals(child.getFlexDirection(), clonedChild.getFlexDirection());
assertEquals(0, clonedChild.getChildCount());
assertEquals(1, child.getChildCount());
}
@Test
public void testAddSharedChildCloneWithNewChildren() throws Exception {
YogaConfig config = new YogaConfig();
YogaNode root = new YogaNode(config);
YogaNode child = new YogaNode(config);
YogaNode grandChild = new YogaNode(config);
root.addChildAt(child, 0);
child.addChildAt(grandChild, 0);
child.setFlexDirection(YogaFlexDirection.ROW);
YogaNode clonedChild = child.cloneWithNewChildren();
assertNotSame(clonedChild, child);
assertEquals(YogaFlexDirection.ROW, clonedChild.getFlexDirection());
assertEquals(child.getFlexDirection(), clonedChild.getFlexDirection());
assertEquals(0, clonedChild.getChildCount());
assertEquals(1, child.getChildCount());
clonedChild.addSharedChildAt(grandChild, 0);
assertEquals(1, clonedChild.getChildCount());
assertNull(grandChild.getOwner());
}
@Test
public void testCloneNodeListener() throws Exception {
final AtomicBoolean onNodeClonedExecuted = new AtomicBoolean(false);
YogaConfig config = new YogaConfig();
config.setOnNodeCloned(
new YogaNodeClonedFunction() {
config.setOnCloneNode(
new YogaNodeCloneFunction() {
@Override
public void onNodeCloned(
YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex) {
public YogaNode cloneNode(YogaNode oldNode, YogaNode owner, int childIndex) {
onNodeClonedExecuted.set(true);
return oldNode.clone();
}
});
YogaNode root = new YogaNode(config);
@@ -268,6 +311,7 @@ public class YogaNodeTest {
root.setHeight(100f);
YogaNode child0 = new YogaNode(config);
root.addChildAt(child0, 0);
child0.setWidth(50f);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
// Force a clone to happen.
@@ -276,20 +320,24 @@ public class YogaNodeTest {
root2.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertTrue(onNodeClonedExecuted.get());
assertEquals(1, root2.getChildCount());
YogaNode clonedNode = root2.getChildAt(0);
assertNotSame(child0, clonedNode);
assertEquals(child0.getWidth(), clonedNode.getWidth());
assertEquals(50f, clonedNode.getWidth().value, 0.01f);
}
@Test
public void testOnNodeClonedLeak() throws Exception {
YogaConfig config = new YogaConfig();
config.setOnNodeCloned(
new YogaNodeClonedFunction() {
config.setOnCloneNode(
new YogaNodeCloneFunction() {
@Override
public void onNodeCloned(
YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex) {
// Do nothing
public YogaNode cloneNode(YogaNode oldNode, YogaNode owner, int childIndex) {
return oldNode.clone();
}
});
config.setOnNodeCloned(null);
config.setOnCloneNode(null);
WeakReference<Object> ref = new WeakReference<Object>(config);
// noinspection UnusedAssignment
config = null;

View File

@@ -23,17 +23,17 @@ TEST(YogaTest, set_children_adds_children_to_parent) {
YGNodeRef const root = YGNodeNew();
YGNodeRef const root_child0 = YGNodeNew();
YGNodeRef const root_child1 = YGNodeNew();
YGNodeSetChildren(root, {root_child0, root_child1});
const std::vector<YGNodeRef> children = getChildren(root);
const std::vector<YGNodeRef> expectedChildren = {root_child0, root_child1};
ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> parents = {YGNodeGetParent(root_child0), YGNodeGetParent(root_child1)};
const std::vector<YGNodeRef> expectedParents = {root, root};
ASSERT_EQ(parents, expectedParents);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {root, root};
ASSERT_EQ(owners, expectedOwners);
YGNodeFreeRecursive(root);
}
@@ -41,18 +41,18 @@ TEST(YogaTest, set_children_to_empty_removes_old_children) {
YGNodeRef const root = YGNodeNew();
YGNodeRef const root_child0 = YGNodeNew();
YGNodeRef const root_child1 = YGNodeNew();
YGNodeSetChildren(root, {root_child0, root_child1});
YGNodeSetChildren(root, {});
const std::vector<YGNodeRef> children = getChildren(root);
const std::vector<YGNodeRef> expectedChildren = {};
ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> parents = {YGNodeGetParent(root_child0), YGNodeGetParent(root_child1)};
const std::vector<YGNodeRef> expectedParents = {nullptr, nullptr};
ASSERT_EQ(parents, expectedParents);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
ASSERT_EQ(owners, expectedOwners);
YGNodeFreeRecursive(root);
}
@@ -60,22 +60,22 @@ TEST(YogaTest, set_children_replaces_non_common_children) {
YGNodeRef const root = YGNodeNew();
YGNodeRef const root_child0 = YGNodeNew();
YGNodeRef const root_child1 = YGNodeNew();
YGNodeSetChildren(root, {root_child0, root_child1});
YGNodeRef const root_child2 = YGNodeNew();
YGNodeRef const root_child3 = YGNodeNew();
YGNodeSetChildren(root, {root_child2, root_child3});
const std::vector<YGNodeRef> children = getChildren(root);
const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child3};
ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> parents = {YGNodeGetParent(root_child0), YGNodeGetParent(root_child1)};
const std::vector<YGNodeRef> expectedParents = {nullptr, nullptr};
ASSERT_EQ(parents, expectedParents);
const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
ASSERT_EQ(owners, expectedOwners);
YGNodeFreeRecursive(root);
YGNodeFree(root_child0);
YGNodeFree(root_child1);
@@ -86,26 +86,26 @@ TEST(YogaTest, set_children_keeps_and_reorders_common_children) {
YGNodeRef const root_child0 = YGNodeNew();
YGNodeRef const root_child1 = YGNodeNew();
YGNodeRef const root_child2 = YGNodeNew();
YGNodeSetChildren(root, {root_child0, root_child1, root_child2});
YGNodeRef const root_child3 = YGNodeNew();
YGNodeSetChildren(root, {root_child2, root_child1, root_child3});
const std::vector<YGNodeRef> children = getChildren(root);
const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child1, root_child3};
ASSERT_EQ(children, expectedChildren);
const std::vector<YGNodeRef> parents = {
YGNodeGetParent(root_child0),
YGNodeGetParent(root_child1),
YGNodeGetParent(root_child2),
YGNodeGetParent(root_child3)
const std::vector<YGNodeRef> owners = {
YGNodeGetOwner(root_child0),
YGNodeGetOwner(root_child1),
YGNodeGetOwner(root_child2),
YGNodeGetOwner(root_child3)
};
const std::vector<YGNodeRef> expectedParents = {nullptr, root, root, root};
ASSERT_EQ(parents, expectedParents);
const std::vector<YGNodeRef> expectedOwners = {nullptr, root, root, root};
ASSERT_EQ(owners, expectedOwners);
YGNodeFreeRecursive(root);
YGNodeFree(root_child0);
}

View File

@@ -58,8 +58,11 @@ float YGUnwrapFloatOptional(const YGFloatOptional& op) {
return op.isUndefined() ? YGUndefined : op.getValue();
}
bool YGFloatOptionalFloatEquals(
const YGFloatOptional& optional,
const float& val) {
return YGUnwrapFloatOptional(optional) == val;
YGFloatOptional YGFloatOptionalMax(
const YGFloatOptional& op1,
const YGFloatOptional& op2) {
if (!op1.isUndefined() && !op2.isUndefined()) {
return op1.getValue() > op2.getValue() ? op1 : op2;
}
return op1.isUndefined() ? op2 : op1;
}

View File

@@ -40,12 +40,12 @@ struct YGCollectFlexItemsRowValues {
float sizeConsumedOnCurrentLine;
float totalFlexGrowFactors;
float totalFlexShrinkScaledFactors;
float endOfLineIndex;
uint32_t endOfLineIndex;
std::vector<YGNodeRef> relativeChildren;
float remainingFreeSpace;
// The size of the mainDim for the row after considering size, padding, margin
// and border of flex items. This is used to calculate maxLineDim after going
// through all the rows to decide on the main axis size of parent.
// through all the rows to decide on the main axis size of owner.
float mainDim;
// The size of the crossDim for the row after considering size, padding,
// margin and border of flex items. Used for calculating containers crossSize.
@@ -65,6 +65,10 @@ bool YGFloatsEqual(const float a, const float b);
// compiler flag.
float YGFloatMax(const float a, const float b);
YGFloatOptional YGFloatOptionalMax(
const YGFloatOptional& op1,
const YGFloatOptional& op2);
// We need custom min function, since we want that, if one argument is
// YGUndefined then the min funtion should return the other argument as the min
// value. We wouldn't have needed a custom min function if YGUndefined was NAN
@@ -94,12 +98,6 @@ float YGFloatSanitize(const float& val);
// TODO: Get rid off this function
float YGUnwrapFloatOptional(const YGFloatOptional& op);
// This function returns true if val and optional both are undefined or if val
// and optional.val is true, otherwise its false.
bool YGFloatOptionalFloatEquals(
const YGFloatOptional& optional,
const float& val);
YGFlexDirection YGFlexDirectionCross(
const YGFlexDirection flexDirection,
const YGDirection direction);
@@ -109,7 +107,7 @@ inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) {
flexDirection == YGFlexDirectionRowReverse;
}
inline YGFloatOptional YGResolveValue(const YGValue value, const float parentSize) {
inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) {
switch (value.unit) {
case YGUnitUndefined:
case YGUnitAuto:
@@ -118,7 +116,7 @@ inline YGFloatOptional YGResolveValue(const YGValue value, const float parentSiz
return YGFloatOptional(value.value);
case YGUnitPercent:
return YGFloatOptional(
static_cast<float>(value.value * parentSize * 0.01));
static_cast<float>(value.value * ownerSize * 0.01));
}
return YGFloatOptional();
}
@@ -142,8 +140,9 @@ inline YGFlexDirection YGResolveFlexDirection(
return flexDirection;
}
static inline float YGResolveValueMargin(
static inline YGFloatOptional YGResolveValueMargin(
const YGValue value,
const float parentSize) {
return value.unit == YGUnitAuto ? 0 : YGUnwrapFloatOptional(YGResolveValue(value, parentSize));
const float ownerSize) {
return value.unit == YGUnitAuto ? YGFloatOptional(0)
: YGResolveValue(value, ownerSize);
}

19
yoga/YGConfig.cpp Normal file
View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "YGConfig.h"
const std::array<bool, YGExperimentalFeatureCount>
kYGDefaultExperimentalFeatures = {{false}};
YGConfig::YGConfig(YGLogger logger)
: experimentalFeatures(kYGDefaultExperimentalFeatures),
useWebDefaults(false),
useLegacyStretchBehaviour(false),
shouldDiffLayoutWithoutLegacyStretchBehaviour(false),
pointScaleFactor(1.0f), logger(logger), cloneNodeCallback(nullptr),
context(nullptr) {}

23
yoga/YGConfig.h Normal file
View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "Yoga-internal.h"
#include "Yoga.h"
struct YGConfig {
std::array<bool, YGExperimentalFeatureCount> experimentalFeatures;
bool useWebDefaults;
bool useLegacyStretchBehaviour;
bool shouldDiffLayoutWithoutLegacyStretchBehaviour;
float pointScaleFactor;
YGLogger logger;
YGCloneNodeFunc cloneNodeCallback;
void* context;
YGConfig(YGLogger logger);
};

View File

@@ -8,12 +8,21 @@
#include "YGFloatOptional.h"
#include <cstdlib>
#include <iostream>
#include "Yoga.h"
YGFloatOptional::YGFloatOptional(const float& value) {
if (YGFloatIsUndefined(value)) {
isUndefined_ = true;
value_ = 0;
} else {
value_ = value;
isUndefined_ = false;
}
}
YGFloatOptional::YGFloatOptional(const float& value)
: value_(value), isUndefined_(false) {}
YGFloatOptional::YGFloatOptional() : value_(0), isUndefined_(true) {}
float YGFloatOptional::getValue() const {
const float& YGFloatOptional::getValue() const {
if (isUndefined_) {
// Abort, accessing a value of an undefined float optional
std::cerr << "Tried to get value of an undefined YGFloatOptional\n";
@@ -27,6 +36,57 @@ void YGFloatOptional::setValue(const float& val) {
isUndefined_ = false;
}
bool YGFloatOptional::isUndefined() const {
const bool& YGFloatOptional::isUndefined() const {
return isUndefined_;
}
bool YGFloatOptional::operator==(const YGFloatOptional& op) const {
if (isUndefined_ == op.isUndefined()) {
return isUndefined_ ? true : value_ == op.getValue();
}
return false;
}
bool YGFloatOptional::operator!=(const YGFloatOptional& op) const {
return !(*this == op);
}
bool YGFloatOptional::operator==(const float& val) const {
if (YGFloatIsUndefined(val) == isUndefined_) {
return isUndefined_ ? true : val == value_;
}
return false;
}
bool YGFloatOptional::operator!=(const float& val) const {
return !(*this == val);
}
YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) {
if (!isUndefined_ && !op.isUndefined_) {
return YGFloatOptional(value_ + op.value_);
}
return YGFloatOptional();
}
bool YGFloatOptional::operator>(const YGFloatOptional& op) const {
if (isUndefined_ || op.isUndefined_) {
return false;
}
return value_ > op.value_;
}
bool YGFloatOptional::operator<(const YGFloatOptional& op) const {
if (isUndefined_ || op.isUndefined_) {
return false;
}
return value_ < op.value_;
}
bool YGFloatOptional::operator>=(const YGFloatOptional& op) const {
return *this == op ? true : *this > op;
}
bool YGFloatOptional::operator<=(const YGFloatOptional& op) const {
return *this == op ? true : *this < op;
}

View File

@@ -5,22 +5,35 @@
* LICENSE file in the root directory of this source tree.
*/
#pragma once
struct YGFloatOptional {
private:
float value_;
bool isUndefined_;
public:
YGFloatOptional(const float& value);
YGFloatOptional();
explicit YGFloatOptional(const float& value);
explicit YGFloatOptional();
// Program will terminate if the value of an undefined is accessed. Please
// make sure to check if the optional is defined before calling this function.
// To check if float optional is defined, use `isUndefined()`.
float getValue() const;
const float& getValue() const;
// Sets the value of float optional, and thus isUndefined is assigned false.
void setValue(const float& val);
bool isUndefined() const;
const bool& isUndefined() const;
YGFloatOptional operator+(const YGFloatOptional& op);
bool operator>(const YGFloatOptional& op) const;
bool operator<(const YGFloatOptional& op) const;
bool operator>=(const YGFloatOptional& op) const;
bool operator<=(const YGFloatOptional& op) const;
bool operator==(const YGFloatOptional& op) const;
bool operator!=(const YGFloatOptional& op) const;
bool operator==(const float& val) const;
bool operator!=(const float& val) const;
};

View File

@@ -19,10 +19,10 @@ YGLayout::YGLayout()
padding(),
direction(YGDirectionInherit),
computedFlexBasisGeneration(0),
computedFlexBasis(YGUndefined),
computedFlexBasis(YGFloatOptional()),
hadOverflow(false),
generationCount(0),
lastParentDirection((YGDirection)-1),
lastOwnerDirection((YGDirection)-1),
nextCachedMeasurementsIndex(0),
cachedMeasurements(),
measuredDimensions(kYGDefaultDimensionValues),
@@ -37,18 +37,15 @@ bool YGLayout::operator==(YGLayout layout) const {
YGFloatArrayEqual(border, layout.border) &&
YGFloatArrayEqual(padding, layout.padding) &&
direction == layout.direction && hadOverflow == layout.hadOverflow &&
lastParentDirection == layout.lastParentDirection &&
lastOwnerDirection == layout.lastOwnerDirection &&
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
cachedLayout == layout.cachedLayout;
cachedLayout == layout.cachedLayout &&
computedFlexBasis == layout.computedFlexBasis;
for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) {
isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i];
}
if (!YGFloatIsUndefined(computedFlexBasis) ||
!YGFloatIsUndefined(layout.computedFlexBasis)) {
isEqual = isEqual && (computedFlexBasis == layout.computedFlexBasis);
}
if (!YGFloatIsUndefined(measuredDimensions[0]) ||
!YGFloatIsUndefined(layout.measuredDimensions[0])) {
isEqual =

View File

@@ -6,6 +6,7 @@
*/
#pragma once
#include "YGFloatOptional.h"
#include "Yoga-internal.h"
struct YGLayout {
@@ -17,13 +18,13 @@ struct YGLayout {
YGDirection direction;
uint32_t computedFlexBasisGeneration;
float computedFlexBasis;
YGFloatOptional computedFlexBasis;
bool hadOverflow;
// Instead of recomputing the entire layout every single time, we
// cache some information to break early when nothing changed
uint32_t generationCount;
YGDirection lastParentDirection;
YGDirection lastOwnerDirection;
uint32_t nextCachedMeasurementsIndex;
std::array<YGCachedMeasurement, YG_MAX_CACHED_RESULT_COUNT>

View File

@@ -49,8 +49,8 @@ uint32_t YGNode::getLineIndex() const {
return lineIndex_;
}
YGNodeRef YGNode::getParent() const {
return parent_;
YGNodeRef YGNode::getOwner() const {
return owner_;
}
YGVector YGNode::getChildren() const {
@@ -85,14 +85,14 @@ std::array<YGValue, 2> YGNode::getResolvedDimensions() const {
return resolvedDimensions_;
}
float YGNode::getLeadingPosition(
const YGFlexDirection axis,
const float axisSize) const {
YGFloatOptional YGNode::getLeadingPosition(
const YGFlexDirection& axis,
const float& axisSize) const {
if (YGFlexDirectionIsRow(axis)) {
const YGValue* leadingPosition =
YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined);
if (leadingPosition->unit != YGUnitUndefined) {
return YGUnwrapFloatOptional(YGResolveValue(*leadingPosition, axisSize));
return YGResolveValue(*leadingPosition, axisSize);
}
}
@@ -100,18 +100,18 @@ float YGNode::getLeadingPosition(
YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined);
return leadingPosition->unit == YGUnitUndefined
? 0.0f
: YGUnwrapFloatOptional(YGResolveValue(*leadingPosition, axisSize));
? YGFloatOptional(0)
: YGResolveValue(*leadingPosition, axisSize);
}
float YGNode::getTrailingPosition(
const YGFlexDirection axis,
const float axisSize) const {
YGFloatOptional YGNode::getTrailingPosition(
const YGFlexDirection& axis,
const float& axisSize) const {
if (YGFlexDirectionIsRow(axis)) {
const YGValue* trailingPosition =
YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined);
if (trailingPosition->unit != YGUnitUndefined) {
return YGUnwrapFloatOptional(YGResolveValue(*trailingPosition, axisSize));
return YGResolveValue(*trailingPosition, axisSize);
}
}
@@ -119,11 +119,11 @@ float YGNode::getTrailingPosition(
YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined);
return trailingPosition->unit == YGUnitUndefined
? 0.0f
: YGUnwrapFloatOptional(YGResolveValue(*trailingPosition, axisSize));
? YGFloatOptional(0)
: YGResolveValue(*trailingPosition, axisSize);
}
bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const {
bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const {
return (YGFlexDirectionIsRow(axis) &&
YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined)
->unit != YGUnitUndefined) ||
@@ -131,7 +131,7 @@ bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const {
->unit != YGUnitUndefined;
}
bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const {
bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const {
return (YGFlexDirectionIsRow(axis) &&
YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined)
->unit != YGUnitUndefined) ||
@@ -139,9 +139,9 @@ bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const {
->unit != YGUnitUndefined;
}
float YGNode::getLeadingMargin(
const YGFlexDirection axis,
const float widthSize) const {
YGFloatOptional YGNode::getLeadingMargin(
const YGFlexDirection& axis,
const float& widthSize) const {
if (YGFlexDirectionIsRow(axis) &&
style_.margin[YGEdgeStart].unit != YGUnitUndefined) {
return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize);
@@ -152,9 +152,9 @@ float YGNode::getLeadingMargin(
widthSize);
}
float YGNode::getTrailingMargin(
const YGFlexDirection axis,
const float widthSize) const {
YGFloatOptional YGNode::getTrailingMargin(
const YGFlexDirection& axis,
const float& widthSize) const {
if (YGFlexDirectionIsRow(axis) &&
style_.margin[YGEdgeEnd].unit != YGUnitUndefined) {
return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize);
@@ -165,9 +165,9 @@ float YGNode::getTrailingMargin(
widthSize);
}
float YGNode::getMarginForAxis(
const YGFlexDirection axis,
const float widthSize) const {
YGFloatOptional YGNode::getMarginForAxis(
const YGFlexDirection& axis,
const float& widthSize) const {
return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize);
}
@@ -237,8 +237,8 @@ void YGNode::setLineIndex(uint32_t lineIndex) {
lineIndex_ = lineIndex;
}
void YGNode::setParent(YGNodeRef parent) {
parent_ = parent;
void YGNode::setOwner(YGNodeRef owner) {
owner_ = owner;
}
void YGNode::setChildren(const YGVector& children) {
@@ -305,11 +305,12 @@ void YGNode::setLayoutPadding(float padding, int index) {
layout_.padding[index] = padding;
}
void YGNode::setLayoutLastParentDirection(YGDirection direction) {
layout_.lastParentDirection = direction;
void YGNode::setLayoutLastOwnerDirection(YGDirection direction) {
layout_.lastOwnerDirection = direction;
}
void YGNode::setLayoutComputedFlexBasis(float computedFlexBasis) {
void YGNode::setLayoutComputedFlexBasis(
const YGFloatOptional& computedFlexBasis) {
layout_.computedFlexBasis = computedFlexBasis;
}
@@ -336,41 +337,54 @@ void YGNode::setLayoutDimension(float dimension, int index) {
// If both left and right are defined, then use left. Otherwise return
// +left or -right depending on which is defined.
float YGNode::relativePosition(
const YGFlexDirection axis,
const float axisSize) {
return isLeadingPositionDefined(axis) ? getLeadingPosition(axis, axisSize)
: -getTrailingPosition(axis, axisSize);
YGFloatOptional YGNode::relativePosition(
const YGFlexDirection& axis,
const float& axisSize) const {
if (isLeadingPositionDefined(axis)) {
return getLeadingPosition(axis, axisSize);
}
YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize);
if (!trailingPosition.isUndefined()) {
trailingPosition.setValue(-1 * trailingPosition.getValue());
}
return trailingPosition;
}
void YGNode::setPosition(
const YGDirection direction,
const float mainSize,
const float crossSize,
const float parentWidth) {
const float ownerWidth) {
/* Root nodes should be always layouted as LTR, so we don't return negative
* values. */
const YGDirection directionRespectingRoot =
parent_ != nullptr ? direction : YGDirectionLTR;
owner_ != nullptr ? direction : YGDirectionLTR;
const YGFlexDirection mainAxis =
YGResolveFlexDirection(style_.flexDirection, directionRespectingRoot);
const YGFlexDirection crossAxis =
YGFlexDirectionCross(mainAxis, directionRespectingRoot);
const float relativePositionMain = relativePosition(mainAxis, mainSize);
const float relativePositionCross = relativePosition(crossAxis, crossSize);
const YGFloatOptional relativePositionMain =
relativePosition(mainAxis, mainSize);
const YGFloatOptional relativePositionCross =
relativePosition(crossAxis, crossSize);
setLayoutPosition(
getLeadingMargin(mainAxis, parentWidth) + relativePositionMain,
YGUnwrapFloatOptional(
getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain),
leading[mainAxis]);
setLayoutPosition(
getTrailingMargin(mainAxis, parentWidth) + relativePositionMain,
YGUnwrapFloatOptional(
getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain),
trailing[mainAxis]);
setLayoutPosition(
getLeadingMargin(crossAxis, parentWidth) + relativePositionCross,
YGUnwrapFloatOptional(
getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross),
leading[crossAxis]);
setLayoutPosition(
getTrailingMargin(crossAxis, parentWidth) + relativePositionCross,
YGUnwrapFloatOptional(
getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross),
trailing[crossAxis]);
}
@@ -385,7 +399,7 @@ YGNode::YGNode()
style_(YGStyle()),
layout_(YGLayout()),
lineIndex_(0),
parent_(nullptr),
owner_(nullptr),
children_(YGVector()),
nextChild_(nullptr),
config_(nullptr),
@@ -403,7 +417,7 @@ YGNode::YGNode(const YGNode& node)
style_(node.style_),
layout_(node.layout_),
lineIndex_(node.lineIndex_),
parent_(node.parent_),
owner_(node.owner_),
children_(node.children_),
nextChild_(node.nextChild_),
config_(node.config_),
@@ -425,7 +439,7 @@ YGNode::YGNode(
YGStyle style,
const YGLayout& layout,
uint32_t lineIndex,
YGNodeRef parent,
YGNodeRef owner,
const YGVector& children,
YGNodeRef nextChild,
YGConfigRef config,
@@ -441,7 +455,7 @@ YGNode::YGNode(
style_(style),
layout_(layout),
lineIndex_(lineIndex),
parent_(parent),
owner_(owner),
children_(children),
nextChild_(nextChild),
config_(config),
@@ -467,7 +481,7 @@ YGNode& YGNode::operator=(const YGNode& node) {
style_ = node.style_;
layout_ = node.layout_;
lineIndex_ = node.getLineIndex();
parent_ = node.getParent();
owner_ = node.getOwner();
children_ = node.getChildren();
nextChild_ = node.getNextChild();
config_ = node.getConfig();
@@ -518,9 +532,9 @@ void YGNode::resolveDimension() {
}
}
YGDirection YGNode::resolveDirection(const YGDirection parentDirection) {
YGDirection YGNode::resolveDirection(const YGDirection ownerDirection) {
if (style_.direction == YGDirectionInherit) {
return parentDirection > YGDirectionInherit ? parentDirection
return ownerDirection > YGDirectionInherit ? ownerDirection
: YGDirectionLTR;
} else {
return style_.direction;
@@ -550,32 +564,35 @@ void YGNode::cloneChildrenIfNeeded() {
}
const YGNodeRef firstChild = children_.front();
if (firstChild->getParent() == this) {
// If the first child has this node as its parent, we assume that it is
if (firstChild->getOwner() == this) {
// If the first child has this node as its owner, we assume that it is
// already unique. We can do this because if we have it has a child, that
// means that its parent was at some point cloned which made that subtree
// means that its owner was at some point cloned which made that subtree
// immutable. We also assume that all its sibling are cloned as well.
return;
}
const YGNodeClonedFunc cloneNodeCallback = config_->cloneNodeCallback;
const YGCloneNodeFunc cloneNodeCallback = config_->cloneNodeCallback;
for (uint32_t i = 0; i < childCount; ++i) {
const YGNodeRef oldChild = children_[i];
const YGNodeRef newChild = YGNodeClone(oldChild);
replaceChild(newChild, i);
newChild->setParent(this);
YGNodeRef newChild = nullptr;
if (cloneNodeCallback) {
cloneNodeCallback(oldChild, newChild, this, i);
newChild = cloneNodeCallback(oldChild, this, i);
}
if (newChild == nullptr) {
newChild = YGNodeClone(oldChild);
}
replaceChild(newChild, i);
newChild->setOwner(this);
}
}
void YGNode::markDirtyAndPropogate() {
if (!isDirty_) {
setDirty(true);
setLayoutComputedFlexBasis(YGUndefined);
if (parent_) {
parent_->markDirtyAndPropogate();
setLayoutComputedFlexBasis(YGFloatOptional());
if (owner_) {
owner_->markDirtyAndPropogate();
}
}
}
@@ -589,7 +606,7 @@ void YGNode::markDirtyAndPropogateDownwards() {
float YGNode::resolveFlexGrow() {
// Root nodes flexGrow should always be 0
if (parent_ == nullptr) {
if (owner_ == nullptr) {
return 0.0;
}
if (!style_.flexGrow.isUndefined()) {
@@ -602,7 +619,7 @@ float YGNode::resolveFlexGrow() {
}
float YGNode::resolveFlexShrink() {
if (parent_ == nullptr) {
if (owner_ == nullptr) {
return 0.0;
}
if (!style_.flexShrink.isUndefined()) {
@@ -621,7 +638,7 @@ bool YGNode::isNodeFlexible() {
(resolveFlexGrow() != 0 || resolveFlexShrink() != 0));
}
float YGNode::getLeadingBorder(const YGFlexDirection axis) const {
float YGNode::getLeadingBorder(const YGFlexDirection& axis) const {
if (YGFlexDirectionIsRow(axis) &&
style_.border[YGEdgeStart].unit != YGUnitUndefined &&
!YGFloatIsUndefined(style_.border[YGEdgeStart].value) &&
@@ -634,7 +651,7 @@ float YGNode::getLeadingBorder(const YGFlexDirection axis) const {
return YGFloatMax(computedEdgeValue, 0.0f);
}
float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const {
float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const {
if (YGFlexDirectionIsRow(flexDirection) &&
style_.border[YGEdgeEnd].unit != YGUnitUndefined &&
!YGFloatIsUndefined(style_.border[YGEdgeEnd].value) &&
@@ -648,51 +665,52 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const {
return YGFloatMax(computedEdgeValue, 0.0f);
}
float YGNode::getLeadingPadding(
const YGFlexDirection axis,
const float widthSize) const {
YGFloatOptional YGNode::getLeadingPadding(
const YGFlexDirection& axis,
const float& widthSize) const {
const YGFloatOptional& paddingEdgeStart =
YGResolveValue(style_.padding[YGEdgeStart], widthSize);
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeStart].unit != YGUnitUndefined &&
!YGResolveValue(style_.padding[YGEdgeStart], widthSize).isUndefined() &&
YGUnwrapFloatOptional(
YGResolveValue(style_.padding[YGEdgeStart], widthSize)) > 0.0f) {
return YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeStart], widthSize));
!paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() > 0.0f) {
return paddingEdgeStart;
}
float resolvedValue = YGUnwrapFloatOptional(YGResolveValue(
YGFloatOptional resolvedValue = YGResolveValue(
*YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),
widthSize));
return YGFloatMax(resolvedValue, 0.0f);
widthSize);
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
}
float YGNode::getTrailingPadding(
const YGFlexDirection axis,
const float widthSize) const {
YGFloatOptional YGNode::getTrailingPadding(
const YGFlexDirection& axis,
const float& widthSize) const {
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&
!YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() &&
YGUnwrapFloatOptional(
YGResolveValue(style_.padding[YGEdgeEnd], widthSize)) >= 0.0f) {
return YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeEnd], widthSize));
YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) {
return YGResolveValue(style_.padding[YGEdgeEnd], widthSize);
}
float resolvedValue = YGUnwrapFloatOptional(YGResolveValue(
YGFloatOptional resolvedValue = YGResolveValue(
*YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),
widthSize));
widthSize);
return YGFloatMax(resolvedValue, 0.0f);
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
}
float YGNode::getLeadingPaddingAndBorder(
const YGFlexDirection axis,
const float widthSize) const {
return getLeadingPadding(axis, widthSize) + getLeadingBorder(axis);
YGFloatOptional YGNode::getLeadingPaddingAndBorder(
const YGFlexDirection& axis,
const float& widthSize) const {
return getLeadingPadding(axis, widthSize) +
YGFloatOptional(getLeadingBorder(axis));
}
float YGNode::getTrailingPaddingAndBorder(
const YGFlexDirection axis,
const float widthSize) const {
return getTrailingPadding(axis, widthSize) + getTrailingBorder(axis);
YGFloatOptional YGNode::getTrailingPaddingAndBorder(
const YGFlexDirection& axis,
const float& widthSize) const {
return getTrailingPadding(axis, widthSize) +
YGFloatOptional(getTrailingBorder(axis));
}
bool YGNode::didUseLegacyFlag() {

View File

@@ -7,6 +7,7 @@
#pragma once
#include <stdio.h>
#include "YGConfig.h"
#include "YGLayout.h"
#include "YGStyle.h"
#include "Yoga-internal.h"
@@ -23,14 +24,16 @@ struct YGNode {
YGStyle style_;
YGLayout layout_;
uint32_t lineIndex_;
YGNodeRef parent_;
YGNodeRef owner_;
YGVector children_;
YGNodeRef nextChild_;
YGConfigRef config_;
bool isDirty_;
std::array<YGValue, 2> resolvedDimensions_;
float relativePosition(const YGFlexDirection axis, const float axisSize);
YGFloatOptional relativePosition(
const YGFlexDirection& axis,
const float& axisSize) const;
public:
YGNode();
@@ -49,7 +52,7 @@ struct YGNode {
YGStyle style,
const YGLayout& layout,
uint32_t lineIndex,
YGNodeRef parent,
YGNodeRef owner,
const YGVector& children,
YGNodeRef nextChild,
YGConfigRef config,
@@ -69,7 +72,12 @@ struct YGNode {
// For Performance reasons passing as reference.
YGLayout& getLayout();
uint32_t getLineIndex() const;
YGNodeRef getParent() const;
// returns the YGNodeRef that owns this YGNode. An owner is used to identify
// the YogaTree that a YGNode belongs to.
// This method will return the parent of the YGNode when a YGNode only belongs
// to one YogaTree or nullptr when the YGNode is shared between two or more
// YogaTrees.
YGNodeRef getOwner() const;
YGVector getChildren() const;
uint32_t getChildrenCount() const;
YGNodeRef getChild(uint32_t index) const;
@@ -80,23 +88,36 @@ struct YGNode {
YGValue getResolvedDimension(int index);
// Methods related to positions, margin, padding and border
float getLeadingPosition(const YGFlexDirection axis, const float axisSize) const;
bool isLeadingPositionDefined(const YGFlexDirection axis) const;
bool isTrailingPosDefined(const YGFlexDirection axis) const;
float getTrailingPosition(const YGFlexDirection axis, const float axisSize) const;
float getLeadingMargin(const YGFlexDirection axis, const float widthSize) const;
float getTrailingMargin(const YGFlexDirection axis, const float widthSize) const;
float getLeadingBorder(const YGFlexDirection flexDirection) const;
float getTrailingBorder(const YGFlexDirection flexDirection) const;
float getLeadingPadding(const YGFlexDirection axis, const float widthSize) const;
float getTrailingPadding(const YGFlexDirection axis, const float widthSize) const;
float getLeadingPaddingAndBorder(
const YGFlexDirection axis,
const float widthSize) const;
float getTrailingPaddingAndBorder(
const YGFlexDirection axis,
const float widthSize) const;
float getMarginForAxis(const YGFlexDirection axis, const float widthSize) const;
YGFloatOptional getLeadingPosition(const YGFlexDirection& axis,
const float& axisSize) const;
bool isLeadingPositionDefined(const YGFlexDirection& axis) const;
bool isTrailingPosDefined(const YGFlexDirection& axis) const;
YGFloatOptional getTrailingPosition(
const YGFlexDirection& axis,
const float& axisSize) const;
YGFloatOptional getLeadingMargin(
const YGFlexDirection& axis,
const float& widthSize) const;
YGFloatOptional getTrailingMargin(
const YGFlexDirection& axis,
const float& widthSize) const;
float getLeadingBorder(const YGFlexDirection& flexDirection) const;
float getTrailingBorder(const YGFlexDirection& flexDirection) const;
YGFloatOptional getLeadingPadding(
const YGFlexDirection& axis,
const float& widthSize) const;
YGFloatOptional getTrailingPadding(
const YGFlexDirection& axis,
const float& widthSize) const;
YGFloatOptional getLeadingPaddingAndBorder(
const YGFlexDirection& axis,
const float& widthSize) const;
YGFloatOptional getTrailingPaddingAndBorder(
const YGFlexDirection& axis,
const float& widthSize) const;
YGFloatOptional getMarginForAxis(
const YGFlexDirection& axis,
const float& widthSize) const;
// Setters
void setContext(void* context);
@@ -111,13 +132,13 @@ struct YGNode {
void setStyleAlignContent(YGAlign alignContent);
void setLayout(const YGLayout& layout);
void setLineIndex(uint32_t lineIndex);
void setParent(YGNodeRef parent);
void setOwner(YGNodeRef owner);
void setChildren(const YGVector& children);
void setNextChild(YGNodeRef nextChild);
void setConfig(YGConfigRef config);
void setDirty(bool isDirty);
void setLayoutLastParentDirection(YGDirection direction);
void setLayoutComputedFlexBasis(float computedFlexBasis);
void setLayoutLastOwnerDirection(YGDirection direction);
void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis);
void setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration);
void setLayoutMeasuredDimension(float measuredDimension, int index);
@@ -132,7 +153,7 @@ struct YGNode {
const YGDirection direction,
const float mainSize,
const float crossSize,
const float parentWidth);
const float ownerWidth);
void setAndPropogateUseLegacyFlag(bool useLegacyFlag);
void setLayoutDoesLegacyFlagAffectsLayout(bool doesLegacyFlagAffectsLayout);
void setLayoutDidUseLegacyFlag(bool didUseLegacyFlag);
@@ -143,7 +164,7 @@ struct YGNode {
YGValue marginTrailingValue(const YGFlexDirection axis) const;
YGValue resolveFlexBasisPtr() const;
void resolveDimension();
YGDirection resolveDirection(const YGDirection parentDirection);
YGDirection resolveDirection(const YGDirection ownerDirection);
void clearChildren();
/// Replaces the occurrences of oldChild with newChild
void replaceChild(YGNodeRef oldChild, YGNodeRef newChild);

View File

@@ -9,7 +9,7 @@
const YGValue kYGValueUndefined = {0, YGUnitUndefined};
const YGValue kYGValueAuto = {YGUndefined, YGUnitAuto};
const YGValue kYGValueAuto = {0, YGUnitAuto};
const std::array<YGValue, YGEdgeCount> kYGDefaultEdgeValuesUnit = {
{kYGValueUndefined,
@@ -42,7 +42,7 @@ YGStyle::YGStyle()
flex(YGFloatOptional()),
flexGrow(YGFloatOptional()),
flexShrink(YGFloatOptional()),
flexBasis({0, YGUnitAuto}),
flexBasis(kYGValueAuto),
margin(kYGDefaultEdgeValuesUnit),
position(kYGDefaultEdgeValuesUnit),
padding(kYGDefaultEdgeValuesUnit),
@@ -50,7 +50,7 @@ YGStyle::YGStyle()
dimensions(kYGDefaultDimensionValuesAutoUnit),
minDimensions(kYGDefaultDimensionValuesUnit),
maxDimensions(kYGDefaultDimensionValuesUnit),
aspectRatio(YGUndefined) {}
aspectRatio(YGFloatOptional()) {}
// Yoga specific properties, not compatible with flexbox specification
bool YGStyle::operator==(const YGStyle& style) {
@@ -91,10 +91,9 @@ bool YGStyle::operator==(const YGStyle& style) {
flexShrink.getValue() == style.flexShrink.getValue();
}
if (!(YGFloatIsUndefined(aspectRatio) &&
YGFloatIsUndefined(style.aspectRatio))) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && aspectRatio == style.aspectRatio;
if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
aspectRatio.getValue() == style.aspectRatio.getValue();
}
return areNonFloatValuesEqual;

View File

@@ -32,7 +32,7 @@ struct YGStyle {
std::array<YGValue, 2> dimensions;
std::array<YGValue, 2> minDimensions;
std::array<YGValue, 2> maxDimensions;
float aspectRatio;
YGFloatOptional aspectRatio;
YGStyle();
// Yoga specific properties, not compatible with flexbox specification

View File

@@ -87,16 +87,6 @@ struct YGCachedMeasurement {
// layouts should not require more than 16 entries to fit within the cache.
#define YG_MAX_CACHED_RESULT_COUNT 16
struct YGConfig {
bool experimentalFeatures[YGExperimentalFeatureCount + 1];
bool useWebDefaults;
bool useLegacyStretchBehaviour;
bool shouldDiffLayoutWithoutLegacyStretchBehaviour;
float pointScaleFactor;
YGLogger logger;
YGNodeClonedFunc cloneNodeCallback;
void* context;
};
static const float kDefaultFlexGrow = 0.0f;
static const float kDefaultFlexShrink = 0.0f;

File diff suppressed because it is too large Load Diff

View File

@@ -62,10 +62,8 @@ typedef int (*YGLogger)(const YGConfigRef config,
YGLogLevel level,
const char *format,
va_list args);
typedef void (*YGNodeClonedFunc)(YGNodeRef oldNode,
YGNodeRef newNode,
YGNodeRef parent,
int childIndex);
typedef YGNodeRef (
*YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex);
// YGNode
WIN_EXPORT YGNodeRef YGNodeNew(void);
@@ -79,17 +77,31 @@ WIN_EXPORT int32_t YGNodeGetInstanceCount(void);
WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node,
const YGNodeRef child,
const uint32_t index);
// This function inserts the child YGNodeRef as a children of the node received
// by parameter and set the Owner of the child object to null. This function is
// expected to be called when using Yoga in persistent mode in order to share a
// YGNodeRef object as a child of two different Yoga trees. The child YGNodeRef
// is expected to be referenced from its original owner and from a clone of its
// original owner.
WIN_EXPORT void YGNodeInsertSharedChild(
const YGNodeRef node,
const YGNodeRef child,
const uint32_t index);
WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child);
WIN_EXPORT void YGNodeRemoveAllChildren(const YGNodeRef node);
WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index);
WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node);
WIN_EXPORT YGNodeRef YGNodeGetOwner(const YGNodeRef node);
WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node);
WIN_EXPORT void YGNodeSetChildren(YGNodeRef const parent, const YGNodeRef children[], const uint32_t count);
WIN_EXPORT void YGNodeSetChildren(
YGNodeRef const owner,
const YGNodeRef children[],
const uint32_t count);
WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node,
const float availableWidth,
const float availableHeight,
const YGDirection parentDirection);
const YGDirection ownerDirection);
// Mark a node as dirty. Only valid for nodes with a custom measure function
// set.
@@ -283,8 +295,8 @@ WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);
WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);
WIN_EXPORT void YGConfigSetNodeClonedFunc(const YGConfigRef config,
const YGNodeClonedFunc callback);
WIN_EXPORT void YGConfigSetCloneNodeFunc(const YGConfigRef config,
const YGCloneNodeFunc callback);
// Export only for C#
WIN_EXPORT YGConfigRef YGConfigGetDefault(void);
@@ -308,6 +320,8 @@ YG_EXTERN_C_END
// Calls f on each node in the tree including the given node argument.
extern void YGTraversePreOrder(YGNodeRef const node, std::function<void(YGNodeRef node)>&& f);
extern void YGNodeSetChildren(YGNodeRef const parent, const std::vector<YGNodeRef> &children);
extern void YGNodeSetChildren(
YGNodeRef const owner,
const std::vector<YGNodeRef>& children);
#endif

View File

@@ -32,6 +32,7 @@ BASE_COMPILER_FLAGS = [
'-Wall',
'-Werror',
'-O3',
'-ffast-math',
]
LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [
@@ -112,4 +113,3 @@ def prebuilt_jar(*args, **kwargs):
def is_apple_platform():
return True