Compare commits
19 Commits
export-D70
...
mateoguzma
Author | SHA1 | Date | |
---|---|---|---|
|
16c82cac8b | ||
|
8bf7a34d02 | ||
|
82671c0132 | ||
|
9f2a9476e5 | ||
|
c7c85621fc | ||
|
73980a3cf8 | ||
|
4b5ca50117 | ||
|
30291398f3 | ||
|
27d632c697 | ||
|
117fa494f7 | ||
|
073c136117 | ||
|
1232761571 | ||
|
c935fd5e10 | ||
|
624325302c | ||
|
37a94a86de | ||
|
4abc1a7d5f | ||
|
51e6095005 | ||
|
79cef614ce | ||
|
6455a848a7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -73,3 +73,6 @@ local.properties
|
|||||||
|
|
||||||
# Docusarus build
|
# Docusarus build
|
||||||
.docusaurus
|
.docusaurus
|
||||||
|
|
||||||
|
# Android Studio
|
||||||
|
.idea
|
||||||
|
@@ -9,6 +9,7 @@ plugins {
|
|||||||
id("com.android.library") version "8.7.1" apply false
|
id("com.android.library") version "8.7.1" apply false
|
||||||
id("com.android.application") version "8.7.1" apply false
|
id("com.android.application") version "8.7.1" apply false
|
||||||
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
||||||
|
id 'org.jetbrains.kotlin.android' version '2.1.20' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@@ -34,6 +35,8 @@ nexusPublishing {
|
|||||||
sonatype {
|
sonatype {
|
||||||
username.set(sonatypeUsername)
|
username.set(sonatypeUsername)
|
||||||
password.set(sonatypePassword)
|
password.set(sonatypePassword)
|
||||||
|
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
|
||||||
|
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
enums.py
53
enums.py
@@ -84,6 +84,12 @@ ENUMS = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Temporary filter enums to not upgrade all enums at once
|
||||||
|
KOTLIN_ENUM_NAMES = {"Direction"}
|
||||||
|
|
||||||
|
ENUMS_KOTLIN = {name: ENUMS[name] for name in KOTLIN_ENUM_NAMES}
|
||||||
|
ENUMS_JAVA = {name: values for name, values in ENUMS.items() if name not in KOTLIN_ENUM_NAMES}
|
||||||
|
|
||||||
DO_NOT_STRIP = ["LogLevel"]
|
DO_NOT_STRIP = ["LogLevel"]
|
||||||
|
|
||||||
BITSET_ENUMS = ["Errata"]
|
BITSET_ENUMS = ["Errata"]
|
||||||
@@ -120,6 +126,9 @@ def to_java_upper(symbol):
|
|||||||
return _format_name(symbol, "_", "upper")
|
return _format_name(symbol, "_", "upper")
|
||||||
|
|
||||||
|
|
||||||
|
def to_kotlin_upper(symbol):
|
||||||
|
return _format_name(symbol, "_", "upper")
|
||||||
|
|
||||||
def to_hyphenated_lower(symbol):
|
def to_hyphenated_lower(symbol):
|
||||||
return _format_name(symbol, "-", "lower")
|
return _format_name(symbol, "-", "lower")
|
||||||
|
|
||||||
@@ -215,7 +224,7 @@ with open(root + "/yoga/YGEnums.cpp", "w") as f:
|
|||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
# write out java files
|
# write out java files
|
||||||
for name, values in sorted(ENUMS.items()):
|
for name, values in sorted(ENUMS_JAVA.items()):
|
||||||
with open(root + "/java/com/facebook/yoga/Yoga%s.java" % name, "w") as f:
|
with open(root + "/java/com/facebook/yoga/Yoga%s.java" % name, "w") as f:
|
||||||
f.write(get_license("java"))
|
f.write(get_license("java"))
|
||||||
f.write("package com.facebook.yoga;\n\n")
|
f.write("package com.facebook.yoga;\n\n")
|
||||||
@@ -267,6 +276,48 @@ for name, values in sorted(ENUMS.items()):
|
|||||||
f.write(" }\n")
|
f.write(" }\n")
|
||||||
f.write("}\n")
|
f.write("}\n")
|
||||||
|
|
||||||
|
# write out Kotlin files
|
||||||
|
for name, values in sorted(ENUMS_KOTLIN.items()):
|
||||||
|
with open(root + "/java/com/facebook/yoga/Yoga%s.kt" % name, "w") as f:
|
||||||
|
f.write(get_license("kotlin"))
|
||||||
|
f.write("package com.facebook.yoga\n\n")
|
||||||
|
f.write("public enum class Yoga%s(public val intValue: Int) {\n" % name)
|
||||||
|
if len(values) > 0:
|
||||||
|
for value in values:
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
f.write(" %s(%d)" % (to_kotlin_upper(value[0]), value[1]))
|
||||||
|
else:
|
||||||
|
f.write(" %s(%d)" % (to_kotlin_upper(value), values.index(value)))
|
||||||
|
if values.index(value) is len(values) - 1:
|
||||||
|
f.write(";\n")
|
||||||
|
else:
|
||||||
|
f.write(",\n")
|
||||||
|
else:
|
||||||
|
f.write("__EMPTY(-1);")
|
||||||
|
f.write("\n")
|
||||||
|
f.write(" public fun intValue(): Int = intValue\n")
|
||||||
|
f.write("\n")
|
||||||
|
f.write(" public companion object {\n")
|
||||||
|
f.write(" @JvmStatic\n")
|
||||||
|
f.write(" public fun fromInt(value: Int): Yoga%s =\n" % name)
|
||||||
|
f.write(" when (value) {\n")
|
||||||
|
for value in values:
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
f.write(
|
||||||
|
" %d -> %s\n" % (value[1], to_kotlin_upper(value[0]))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
f.write(
|
||||||
|
" %d -> %s\n"
|
||||||
|
% (values.index(value), to_kotlin_upper(value))
|
||||||
|
)
|
||||||
|
f.write(
|
||||||
|
' else -> throw IllegalArgumentException("Unknown enum value: $value")\n'
|
||||||
|
)
|
||||||
|
f.write(" }\n")
|
||||||
|
f.write(" }\n")
|
||||||
|
f.write("}\n")
|
||||||
|
|
||||||
# write out TypeScript file
|
# write out TypeScript file
|
||||||
with open(root + "/javascript/src/generated/YGEnums.ts", "w") as f:
|
with open(root + "/javascript/src/generated/YGEnums.ts", "w") as f:
|
||||||
f.write(get_license("js"))
|
f.write(get_license("js"))
|
||||||
|
@@ -240,3 +240,14 @@
|
|||||||
<div style="position:relative; width:50px; height:50px;">
|
<div style="position:relative; width:50px; height:50px;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="align_items_non_stretch_s526008"
|
||||||
|
style="flex-direction: column; width: 400px; height: 400px;">
|
||||||
|
<div style="flex-direction: row;">
|
||||||
|
<div style="flex-direction: column; align-items: flex-start;">
|
||||||
|
<div>
|
||||||
|
<div style="width: 0; height: 10px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// You can use this script to configure the gradleEnterprise{} block in your build.
|
|
||||||
// You need to rename this file to ./gradle/gradle-enterprise.gradle.kts in order for
|
|
||||||
// this to be processed.
|
|
||||||
extensions.getByName("gradleEnterprise").withGroovyBuilder {
|
|
||||||
setProperty("server", "https://your-gradle-enterprise-instance.example.com")
|
|
||||||
getProperty("buildScan").withGroovyBuilder {
|
|
||||||
"publishAlways"()
|
|
||||||
"tag"(if(System.getenv("CI") != null) "CI" else "Local")
|
|
||||||
}
|
|
||||||
}
|
|
@@ -9,6 +9,7 @@ plugins {
|
|||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
id("maven-publish")
|
id("maven-publish")
|
||||||
id("signing")
|
id("signing")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.facebook.yoga"
|
group = "com.facebook.yoga"
|
||||||
@@ -48,6 +49,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions { jvmTarget = "1.8" }
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
multipleVariants {
|
multipleVariants {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
@@ -60,6 +63,7 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.google.code.findbugs:jsr305:3.0.2")
|
implementation("com.google.code.findbugs:jsr305:3.0.2")
|
||||||
implementation("com.facebook.soloader:soloader:0.10.5")
|
implementation("com.facebook.soloader:soloader:0.10.5")
|
||||||
|
implementation("androidx.core:core-ktx:1.16.0")
|
||||||
testImplementation("junit:junit:4.12")
|
testImplementation("junit:junit:4.12")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.yoga;
|
|
||||||
|
|
||||||
public class YogaConstants {
|
|
||||||
|
|
||||||
public static final float UNDEFINED = Float.NaN;
|
|
||||||
|
|
||||||
public static boolean isUndefined(float value) {
|
|
||||||
return Float.compare(value, UNDEFINED) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isUndefined(YogaValue value) {
|
|
||||||
return value.unit == YogaUnit.UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float getUndefined() {
|
|
||||||
return UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
18
java/com/facebook/yoga/YogaConstants.kt
Normal file
18
java/com/facebook/yoga/YogaConstants.kt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.yoga
|
||||||
|
|
||||||
|
public object YogaConstants {
|
||||||
|
@JvmField public val UNDEFINED: Float = Float.NaN
|
||||||
|
|
||||||
|
@JvmStatic public fun isUndefined(value: Float): Boolean = value.compareTo(UNDEFINED) == 0
|
||||||
|
|
||||||
|
@JvmStatic public fun isUndefined(value: YogaValue): Boolean = value.unit == YogaUnit.UNDEFINED
|
||||||
|
|
||||||
|
@JvmStatic public fun getUndefined(): Float = UNDEFINED
|
||||||
|
}
|
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @generated by enums.py
|
|
||||||
|
|
||||||
package com.facebook.yoga;
|
|
||||||
|
|
||||||
public enum YogaDirection {
|
|
||||||
INHERIT(0),
|
|
||||||
LTR(1),
|
|
||||||
RTL(2);
|
|
||||||
|
|
||||||
private final int mIntValue;
|
|
||||||
|
|
||||||
YogaDirection(int intValue) {
|
|
||||||
mIntValue = intValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int intValue() {
|
|
||||||
return mIntValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static YogaDirection fromInt(int value) {
|
|
||||||
switch (value) {
|
|
||||||
case 0: return INHERIT;
|
|
||||||
case 1: return LTR;
|
|
||||||
case 2: return RTL;
|
|
||||||
default: throw new IllegalArgumentException("Unknown enum value: " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
29
java/com/facebook/yoga/YogaDirection.kt
Normal file
29
java/com/facebook/yoga/YogaDirection.kt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @generated by enums.py
|
||||||
|
|
||||||
|
package com.facebook.yoga
|
||||||
|
|
||||||
|
public enum class YogaDirection(public val intValue: Int) {
|
||||||
|
INHERIT(0),
|
||||||
|
LTR(1),
|
||||||
|
RTL(2);
|
||||||
|
|
||||||
|
public fun intValue(): Int = intValue
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
@JvmStatic
|
||||||
|
public fun fromInt(value: Int): YogaDirection =
|
||||||
|
when (value) {
|
||||||
|
0 -> INHERIT
|
||||||
|
1 -> LTR
|
||||||
|
2 -> RTL
|
||||||
|
else -> throw IllegalArgumentException("Unknown enum value: $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* @generated SignedSource<<e8d11c0e97041bb2f1487f0d87363fdc>>
|
* @generated SignedSource<<84597dd8b2c4f3aac1f21abe68f25308>>
|
||||||
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2293,6 +2293,86 @@ public class YGAlignItemsTest {
|
|||||||
assertEquals(50f, root_child1.getLayoutHeight(), 0.0f);
|
assertEquals(50f, root_child1.getLayoutHeight(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_align_items_non_stretch_s526008() {
|
||||||
|
YogaConfig config = YogaConfigFactory.create();
|
||||||
|
|
||||||
|
final YogaNode root = createNode(config);
|
||||||
|
root.setPositionType(YogaPositionType.ABSOLUTE);
|
||||||
|
root.setWidth(400f);
|
||||||
|
root.setHeight(400f);
|
||||||
|
|
||||||
|
final YogaNode root_child0 = createNode(config);
|
||||||
|
root_child0.setFlexDirection(YogaFlexDirection.ROW);
|
||||||
|
root.addChildAt(root_child0, 0);
|
||||||
|
|
||||||
|
final YogaNode root_child0_child0 = createNode(config);
|
||||||
|
root_child0_child0.setAlignItems(YogaAlign.FLEX_START);
|
||||||
|
root_child0.addChildAt(root_child0_child0, 0);
|
||||||
|
|
||||||
|
final YogaNode root_child0_child0_child0 = createNode(config);
|
||||||
|
root_child0_child0.addChildAt(root_child0_child0_child0, 0);
|
||||||
|
|
||||||
|
final YogaNode root_child0_child0_child0_child0 = createNode(config);
|
||||||
|
root_child0_child0_child0_child0.setHeight(10f);
|
||||||
|
root_child0_child0_child0.addChildAt(root_child0_child0_child0_child0, 0);
|
||||||
|
root.setDirection(YogaDirection.LTR);
|
||||||
|
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
|
||||||
|
|
||||||
|
assertEquals(0f, root.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(400f, root.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(400f, root.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(400f, root_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
root.setDirection(YogaDirection.RTL);
|
||||||
|
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
|
||||||
|
|
||||||
|
assertEquals(0f, root.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(400f, root.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(400f, root.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(400f, root_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(400f, root_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutX(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutY(), 0.0f);
|
||||||
|
assertEquals(0f, root_child0_child0_child0_child0.getLayoutWidth(), 0.0f);
|
||||||
|
assertEquals(10f, root_child0_child0_child0_child0.getLayoutHeight(), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
private YogaNode createNode(YogaConfig config) {
|
private YogaNode createNode(YogaConfig config) {
|
||||||
return mNodeFactory.create(config);
|
return mNodeFactory.create(config);
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* @generated SignedSource<<075a0b67003e5c4a1f51bd99da71c700>>
|
* @generated SignedSource<<fd80af208d8635435f86ffa8f3810b39>>
|
||||||
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2442,3 +2442,88 @@ test('align_stretch_with_row_reverse', () => {
|
|||||||
config.free();
|
config.free();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
test('align_items_non_stretch_s526008', () => {
|
||||||
|
const config = Yoga.Config.create();
|
||||||
|
let root;
|
||||||
|
|
||||||
|
try {
|
||||||
|
root = Yoga.Node.create(config);
|
||||||
|
root.setPositionType(PositionType.Absolute);
|
||||||
|
root.setWidth(400);
|
||||||
|
root.setHeight(400);
|
||||||
|
|
||||||
|
const root_child0 = Yoga.Node.create(config);
|
||||||
|
root_child0.setFlexDirection(FlexDirection.Row);
|
||||||
|
root.insertChild(root_child0, 0);
|
||||||
|
|
||||||
|
const root_child0_child0 = Yoga.Node.create(config);
|
||||||
|
root_child0_child0.setAlignItems(Align.FlexStart);
|
||||||
|
root_child0.insertChild(root_child0_child0, 0);
|
||||||
|
|
||||||
|
const root_child0_child0_child0 = Yoga.Node.create(config);
|
||||||
|
root_child0_child0.insertChild(root_child0_child0_child0, 0);
|
||||||
|
|
||||||
|
const root_child0_child0_child0_child0 = Yoga.Node.create(config);
|
||||||
|
root_child0_child0_child0_child0.setHeight(10);
|
||||||
|
root_child0_child0_child0.insertChild(root_child0_child0_child0_child0, 0);
|
||||||
|
root.calculateLayout(undefined, undefined, Direction.LTR);
|
||||||
|
|
||||||
|
expect(root.getComputedLeft()).toBe(0);
|
||||||
|
expect(root.getComputedTop()).toBe(0);
|
||||||
|
expect(root.getComputedWidth()).toBe(400);
|
||||||
|
expect(root.getComputedHeight()).toBe(400);
|
||||||
|
|
||||||
|
expect(root_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0.getComputedWidth()).toBe(400);
|
||||||
|
expect(root_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
root.calculateLayout(undefined, undefined, Direction.RTL);
|
||||||
|
|
||||||
|
expect(root.getComputedLeft()).toBe(0);
|
||||||
|
expect(root.getComputedTop()).toBe(0);
|
||||||
|
expect(root.getComputedWidth()).toBe(400);
|
||||||
|
expect(root.getComputedHeight()).toBe(400);
|
||||||
|
|
||||||
|
expect(root_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0.getComputedWidth()).toBe(400);
|
||||||
|
expect(root_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0.getComputedLeft()).toBe(400);
|
||||||
|
expect(root_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedLeft()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedTop()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedWidth()).toBe(0);
|
||||||
|
expect(root_child0_child0_child0_child0.getComputedHeight()).toBe(10);
|
||||||
|
} finally {
|
||||||
|
if (typeof root !== 'undefined') {
|
||||||
|
root.freeRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
config.free();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@@ -19,10 +19,11 @@ include(":yoga")
|
|||||||
|
|
||||||
project(":yoga").projectDir = file("java")
|
project(":yoga").projectDir = file("java")
|
||||||
|
|
||||||
rootProject.name = "yoga-github"
|
gradleEnterprise {
|
||||||
|
buildScan {
|
||||||
// If you specify a file inside gradle/gradle-enterprise.gradle.kts
|
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||||
// you can configure your custom Gradle Enterprise instance
|
termsOfServiceAgree = "yes"
|
||||||
if (file("./gradle/gradle-enterprise.gradle.kts").exists()) {
|
}
|
||||||
apply(from = "./gradle/gradle-enterprise.gradle.kts")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootProject.name = "yoga-github"
|
||||||
|
7
tests/.clang-tidy
Normal file
7
tests/.clang-tidy
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
InheritParentConfig: true
|
||||||
|
Checks: '
|
||||||
|
-facebook-hte-CArray,
|
||||||
|
-modernize-avoid-c-arrays,
|
||||||
|
'
|
||||||
|
...
|
214
tests/YGPersistentNodeCloningTest.cpp
Normal file
214
tests/YGPersistentNodeCloningTest.cpp
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
#include <yoga/config/Config.h>
|
||||||
|
#include <yoga/node/Node.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace facebook::yoga {
|
||||||
|
|
||||||
|
struct YGPersistentNodeCloningTest : public ::testing::Test {
|
||||||
|
struct NodeWrapper {
|
||||||
|
explicit NodeWrapper(
|
||||||
|
YGConfigRef config,
|
||||||
|
std::vector<std::shared_ptr<NodeWrapper>> children = {})
|
||||||
|
: node{YGNodeNewWithConfig(config)}, children{std::move(children)} {
|
||||||
|
YGNodeSetContext(node, this);
|
||||||
|
|
||||||
|
auto privateNode = resolveRef(node);
|
||||||
|
for (const auto& child : this->children) {
|
||||||
|
auto privateChild = resolveRef(child->node);
|
||||||
|
// Claim first ownership of not yet owned nodes, to avoid immediately
|
||||||
|
// cloning them
|
||||||
|
if (YGNodeGetOwner(child->node) == nullptr) {
|
||||||
|
privateChild->setOwner(privateNode);
|
||||||
|
}
|
||||||
|
privateNode->insertChild(privateChild, privateNode->getChildCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone, with current children, for mutation
|
||||||
|
NodeWrapper(const NodeWrapper& other)
|
||||||
|
: node{YGNodeClone(other.node)}, children{other.children} {
|
||||||
|
YGNodeSetContext(node, this);
|
||||||
|
|
||||||
|
auto privateNode = resolveRef(node);
|
||||||
|
privateNode->setOwner(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone, with new children
|
||||||
|
NodeWrapper(
|
||||||
|
const NodeWrapper& other,
|
||||||
|
std::vector<std::shared_ptr<NodeWrapper>> children)
|
||||||
|
: node{YGNodeClone(other.node)}, children{std::move(children)} {
|
||||||
|
YGNodeSetContext(node, this);
|
||||||
|
|
||||||
|
auto privateNode = resolveRef(node);
|
||||||
|
privateNode->setOwner(nullptr);
|
||||||
|
privateNode->setChildren({});
|
||||||
|
privateNode->setDirty(true);
|
||||||
|
|
||||||
|
for (const auto& child : this->children) {
|
||||||
|
auto privateChild = resolveRef(child->node);
|
||||||
|
// Claim first ownership of not yet owned nodes, to avoid immediately
|
||||||
|
// cloning them
|
||||||
|
if (YGNodeGetOwner(child->node) == nullptr) {
|
||||||
|
privateChild->setOwner(privateNode);
|
||||||
|
}
|
||||||
|
privateNode->insertChild(privateChild, privateNode->getChildCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeWrapper(NodeWrapper&&) = delete;
|
||||||
|
|
||||||
|
~NodeWrapper() {
|
||||||
|
YGNodeFree(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeWrapper& operator=(const NodeWrapper& other) = delete;
|
||||||
|
NodeWrapper& operator=(NodeWrapper&& other) = delete;
|
||||||
|
|
||||||
|
YGNodeRef node;
|
||||||
|
std::vector<std::shared_ptr<NodeWrapper>> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConfigWrapper {
|
||||||
|
ConfigWrapper() {
|
||||||
|
YGConfigSetCloneNodeFunc(
|
||||||
|
config,
|
||||||
|
[](YGNodeConstRef oldNode, YGNodeConstRef owner, size_t childIndex) {
|
||||||
|
onClone(oldNode, owner, childIndex);
|
||||||
|
auto wrapper = static_cast<NodeWrapper*>(YGNodeGetContext(owner));
|
||||||
|
auto old = static_cast<NodeWrapper*>(YGNodeGetContext(oldNode));
|
||||||
|
|
||||||
|
wrapper->children[childIndex] = std::make_shared<NodeWrapper>(*old);
|
||||||
|
return wrapper->children[childIndex]->node;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigWrapper(const ConfigWrapper&) = delete;
|
||||||
|
ConfigWrapper(ConfigWrapper&&) = delete;
|
||||||
|
|
||||||
|
~ConfigWrapper() {
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigWrapper& operator=(const ConfigWrapper&) = delete;
|
||||||
|
ConfigWrapper& operator=(ConfigWrapper&&) = delete;
|
||||||
|
|
||||||
|
YGConfigRef config{YGConfigNew()};
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfigWrapper configWrapper;
|
||||||
|
YGConfigRef config{configWrapper.config};
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
onClone = [](...) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
static inline std::function<void(YGNodeConstRef, YGNodeConstRef, size_t)>
|
||||||
|
onClone;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(
|
||||||
|
YGPersistentNodeCloningTest,
|
||||||
|
changing_sibling_height_does_not_clone_neighbors) {
|
||||||
|
// <ScrollView>
|
||||||
|
// <View id="Sibling" style={{ height: 1 }} />
|
||||||
|
// <View id="A" style={{ height: 1 }}>
|
||||||
|
// <View id="B">
|
||||||
|
// <View id="C">
|
||||||
|
// <View id="D"/>
|
||||||
|
// </View>
|
||||||
|
// </View>
|
||||||
|
// </View>
|
||||||
|
// </ScrollView>
|
||||||
|
|
||||||
|
auto sibling = std::make_shared<NodeWrapper>(config);
|
||||||
|
YGNodeStyleSetHeight(sibling->node, 1);
|
||||||
|
|
||||||
|
auto d = std::make_shared<NodeWrapper>(config);
|
||||||
|
auto c = std::make_shared<NodeWrapper>(config, std::vector{d});
|
||||||
|
auto b = std::make_shared<NodeWrapper>(config, std::vector{c});
|
||||||
|
auto a = std::make_shared<NodeWrapper>(config, std::vector{b});
|
||||||
|
YGNodeStyleSetHeight(a->node, 1);
|
||||||
|
|
||||||
|
auto scrollContentView =
|
||||||
|
std::make_shared<NodeWrapper>(config, std::vector{sibling, a});
|
||||||
|
YGNodeStyleSetPositionType(scrollContentView->node, YGPositionTypeAbsolute);
|
||||||
|
|
||||||
|
auto scrollView =
|
||||||
|
std::make_shared<NodeWrapper>(config, std::vector{scrollContentView});
|
||||||
|
YGNodeStyleSetWidth(scrollView->node, 100);
|
||||||
|
YGNodeStyleSetHeight(scrollView->node, 100);
|
||||||
|
|
||||||
|
// We don't expect any cloning during the first layout
|
||||||
|
onClone = [](...) { FAIL(); };
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(
|
||||||
|
scrollView->node, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
auto siblingPrime = std::make_shared<NodeWrapper>(config);
|
||||||
|
YGNodeStyleSetHeight(siblingPrime->node, 2);
|
||||||
|
|
||||||
|
auto scrollContentViewPrime = std::make_shared<NodeWrapper>(
|
||||||
|
*scrollContentView, std::vector{siblingPrime, a});
|
||||||
|
auto scrollViewPrime = std::make_shared<NodeWrapper>(
|
||||||
|
*scrollView, std::vector{scrollContentViewPrime});
|
||||||
|
|
||||||
|
std::vector<NodeWrapper*> nodesCloned;
|
||||||
|
// We should only need to clone "A"
|
||||||
|
onClone = [&](YGNodeConstRef oldNode,
|
||||||
|
YGNodeConstRef /*owner*/,
|
||||||
|
size_t /*childIndex*/) {
|
||||||
|
nodesCloned.push_back(static_cast<NodeWrapper*>(YGNodeGetContext(oldNode)));
|
||||||
|
};
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(
|
||||||
|
scrollViewPrime->node, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
EXPECT_EQ(nodesCloned.size(), 1);
|
||||||
|
EXPECT_EQ(nodesCloned[0], a.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(YGPersistentNodeCloningTest, clone_leaf_display_contents_node) {
|
||||||
|
// <View id="A">
|
||||||
|
// <View id="B" style={{ display: 'contents' }} />
|
||||||
|
// </View>
|
||||||
|
|
||||||
|
auto b = std::make_shared<NodeWrapper>(config);
|
||||||
|
auto a = std::make_shared<NodeWrapper>(config, std::vector{b});
|
||||||
|
YGNodeStyleSetDisplay(b->node, YGDisplayContents);
|
||||||
|
|
||||||
|
// We don't expect any cloning during the first layout
|
||||||
|
onClone = [](...) { FAIL(); };
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(a->node, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
auto aPrime = std::make_shared<NodeWrapper>(config, std::vector{b});
|
||||||
|
|
||||||
|
std::vector<NodeWrapper*> nodesCloned;
|
||||||
|
// We should clone "C"
|
||||||
|
onClone = [&](YGNodeConstRef oldNode,
|
||||||
|
YGNodeConstRef /*owner*/,
|
||||||
|
size_t /*childIndex*/) {
|
||||||
|
nodesCloned.push_back(static_cast<NodeWrapper*>(YGNodeGetContext(oldNode)));
|
||||||
|
};
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(aPrime->node, 100, 100, YGDirectionLTR);
|
||||||
|
|
||||||
|
EXPECT_EQ(nodesCloned.size(), 1);
|
||||||
|
EXPECT_EQ(nodesCloned[0], b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace facebook::yoga
|
@@ -161,3 +161,23 @@ TEST(YogaTest, per_node_point_scale_factor) {
|
|||||||
YGConfigFree(config2);
|
YGConfigFree(config2);
|
||||||
YGConfigFree(config3);
|
YGConfigFree(config3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, raw_layout_dimensions) {
|
||||||
|
YGConfigRef config = YGConfigNew();
|
||||||
|
YGConfigSetPointScaleFactor(config, 0.5f);
|
||||||
|
|
||||||
|
YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetWidth(root, 11.5f);
|
||||||
|
YGNodeStyleSetHeight(root, 9.5f);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(YGNodeLayoutGetWidth(root), 12.0f);
|
||||||
|
ASSERT_EQ(YGNodeLayoutGetHeight(root), 10.0f);
|
||||||
|
ASSERT_EQ(YGNodeLayoutGetRawWidth(root), 11.5f);
|
||||||
|
ASSERT_EQ(YGNodeLayoutGetRawHeight(root), 9.5f);
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* clang-format off
|
* clang-format off
|
||||||
* @generated SignedSource<<71295a398c89ea424490884a05e2c77c>>
|
* @generated SignedSource<<1db57b05babb408c08efcec7dbdf16fb>>
|
||||||
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2310,3 +2310,84 @@ TEST(YogaTest, align_stretch_with_row_reverse) {
|
|||||||
|
|
||||||
YGConfigFree(config);
|
YGConfigFree(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, align_items_non_stretch_s526008) {
|
||||||
|
YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
|
||||||
|
YGNodeStyleSetWidth(root, 400);
|
||||||
|
YGNodeStyleSetHeight(root, 400);
|
||||||
|
|
||||||
|
YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetAlignItems(root_child0_child0, YGAlignFlexStart);
|
||||||
|
YGNodeInsertChild(root_child0, root_child0_child0, 0);
|
||||||
|
|
||||||
|
YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
|
||||||
|
|
||||||
|
YGNodeRef root_child0_child0_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetHeight(root_child0_child0_child0_child0, 10);
|
||||||
|
YGNodeInsertChild(root_child0_child0_child0, root_child0_child0_child0_child0, 0);
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetLeft(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
@@ -17,15 +17,15 @@ has effect when items are wrapped to multiple lines using [flex wrap](/docs/styl
|
|||||||
|
|
||||||
**Center**: Align wrapped lines in the center of the container's cross axis.
|
**Center**: Align wrapped lines in the center of the container's cross axis.
|
||||||
|
|
||||||
**Space between**: Evenly space wrapped lines across the container's main axis, distributing
|
**Space between**: Evenly space wrapped lines across the container's cross axis, distributing
|
||||||
remaining space between the lines.
|
remaining space between the lines.
|
||||||
|
|
||||||
**Space around**: Evenly space wrapped lines across the container's main axis, distributing
|
**Space around**: Evenly space wrapped lines across the container's cross axis, distributing
|
||||||
remaining space around the lines. Compared to space between using
|
remaining space around the lines. Compared to space between using
|
||||||
space around will result in space being distributed to the beginning of
|
space around will result in space being distributed to the beginning of
|
||||||
the first lines and end of the last line.
|
the first lines and end of the last line.
|
||||||
|
|
||||||
**Space evenly**: Evenly space wrapped lines across the container's main axis, distributing
|
**Space evenly**: Evenly space wrapped lines across the container's cross axis, distributing
|
||||||
remaining space around the lines. Compared to space around, space evenly will not
|
remaining space around the lines. Compared to space around, space evenly will not
|
||||||
double the gaps between children. The size of gaps between children and between
|
double the gaps between children. The size of gaps between children and between
|
||||||
the parent's edges and the first/last child will all be equal.
|
the parent's edges and the first/last child will all be equal.
|
||||||
|
@@ -90,3 +90,11 @@ float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) {
|
|||||||
return getResolvedLayoutProperty<&LayoutResults::padding>(
|
return getResolvedLayoutProperty<&LayoutResults::padding>(
|
||||||
node, scopedEnum(edge));
|
node, scopedEnum(edge));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float YGNodeLayoutGetRawHeight(YGNodeConstRef node) {
|
||||||
|
return resolveRef(node)->getLayout().rawDimension(Dimension::Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
float YGNodeLayoutGetRawWidth(YGNodeConstRef node) {
|
||||||
|
return resolveRef(node)->getLayout().rawDimension(Dimension::Width);
|
||||||
|
}
|
||||||
|
@@ -32,4 +32,14 @@ YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge);
|
|||||||
YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge);
|
YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge);
|
||||||
YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge);
|
YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the measured height of the node, before layout rounding
|
||||||
|
*/
|
||||||
|
YG_EXPORT float YGNodeLayoutGetRawHeight(YGNodeConstRef node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the measured width of the node, before layout rounding
|
||||||
|
*/
|
||||||
|
YG_EXPORT float YGNodeLayoutGetRawWidth(YGNodeConstRef node);
|
||||||
|
|
||||||
YG_EXTERN_C_END
|
YG_EXTERN_C_END
|
||||||
|
@@ -72,9 +72,9 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
|
|||||||
case YGUnitPoint:
|
case YGUnitPoint:
|
||||||
case YGUnitPercent:
|
case YGUnitPercent:
|
||||||
return lhs.value == rhs.value;
|
return lhs.value == rhs.value;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const YGValue& lhs, const YGValue& rhs) {
|
inline bool operator!=(const YGValue& lhs, const YGValue& rhs) {
|
||||||
|
16
yoga/Yoga.h
16
yoga/Yoga.h
@@ -11,11 +11,11 @@
|
|||||||
* `#include <yoga/Yoga.h>` includes all of Yoga's public headers.
|
* `#include <yoga/Yoga.h>` includes all of Yoga's public headers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <yoga/YGConfig.h>
|
#include <yoga/YGConfig.h> // IWYU pragma: export
|
||||||
#include <yoga/YGEnums.h>
|
#include <yoga/YGEnums.h> // IWYU pragma: export
|
||||||
#include <yoga/YGMacros.h>
|
#include <yoga/YGMacros.h> // IWYU pragma: export
|
||||||
#include <yoga/YGNode.h>
|
#include <yoga/YGNode.h> // IWYU pragma: export
|
||||||
#include <yoga/YGNodeLayout.h>
|
#include <yoga/YGNodeLayout.h> // IWYU pragma: export
|
||||||
#include <yoga/YGNodeStyle.h>
|
#include <yoga/YGNodeStyle.h> // IWYU pragma: export
|
||||||
#include <yoga/YGPixelGrid.h>
|
#include <yoga/YGPixelGrid.h> // IWYU pragma: export
|
||||||
#include <yoga/YGValue.h>
|
#include <yoga/YGValue.h> // IWYU pragma: export
|
||||||
|
@@ -415,6 +415,12 @@ static void measureNodeWithoutChildren(
|
|||||||
Dimension::Height);
|
Dimension::Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isFixedSize(float dim, SizingMode sizingMode) {
|
||||||
|
return sizingMode == SizingMode::StretchFit ||
|
||||||
|
(yoga::isDefined(dim) && sizingMode == SizingMode::FitContent &&
|
||||||
|
dim <= 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
static bool measureNodeWithFixedSize(
|
static bool measureNodeWithFixedSize(
|
||||||
yoga::Node* const node,
|
yoga::Node* const node,
|
||||||
const Direction direction,
|
const Direction direction,
|
||||||
@@ -424,12 +430,8 @@ static bool measureNodeWithFixedSize(
|
|||||||
const SizingMode heightSizingMode,
|
const SizingMode heightSizingMode,
|
||||||
const float ownerWidth,
|
const float ownerWidth,
|
||||||
const float ownerHeight) {
|
const float ownerHeight) {
|
||||||
if ((yoga::isDefined(availableWidth) &&
|
if (isFixedSize(availableWidth, widthSizingMode) &&
|
||||||
widthSizingMode == SizingMode::FitContent && availableWidth <= 0.0f) ||
|
isFixedSize(availableHeight, heightSizingMode)) {
|
||||||
(yoga::isDefined(availableHeight) &&
|
|
||||||
heightSizingMode == SizingMode::FitContent && availableHeight <= 0.0f) ||
|
|
||||||
(widthSizingMode == SizingMode::StretchFit &&
|
|
||||||
heightSizingMode == SizingMode::StretchFit)) {
|
|
||||||
node->setLayoutMeasuredDimension(
|
node->setLayoutMeasuredDimension(
|
||||||
boundAxis(
|
boundAxis(
|
||||||
node,
|
node,
|
||||||
@@ -476,16 +478,19 @@ static void zeroOutLayoutRecursively(yoga::Node* const node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cleanupContentsNodesRecursively(yoga::Node* const node) {
|
static void cleanupContentsNodesRecursively(yoga::Node* const node) {
|
||||||
for (auto child : node->getChildren()) {
|
if (node->hasContentsChildren()) [[unlikely]] {
|
||||||
if (child->style().display() == Display::Contents) {
|
node->cloneContentsChildrenIfNeeded();
|
||||||
child->getLayout() = {};
|
for (auto child : node->getChildren()) {
|
||||||
child->setLayoutDimension(0, Dimension::Width);
|
if (child->style().display() == Display::Contents) {
|
||||||
child->setLayoutDimension(0, Dimension::Height);
|
child->getLayout() = {};
|
||||||
child->setHasNewLayout(true);
|
child->setLayoutDimension(0, Dimension::Width);
|
||||||
child->setDirty(false);
|
child->setLayoutDimension(0, Dimension::Height);
|
||||||
child->cloneChildrenIfNeeded();
|
child->setHasNewLayout(true);
|
||||||
|
child->setDirty(false);
|
||||||
|
child->cloneChildrenIfNeeded();
|
||||||
|
|
||||||
cleanupContentsNodesRecursively(child);
|
cleanupContentsNodesRecursively(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -106,25 +106,25 @@ void roundLayoutResultsToPixelGrid(
|
|||||||
const bool hasFractionalHeight =
|
const bool hasFractionalHeight =
|
||||||
!yoga::inexactEquals(round(scaledNodeHeight), scaledNodeHeight);
|
!yoga::inexactEquals(round(scaledNodeHeight), scaledNodeHeight);
|
||||||
|
|
||||||
node->setLayoutDimension(
|
node->getLayout().setDimension(
|
||||||
|
Dimension::Width,
|
||||||
roundValueToPixelGrid(
|
roundValueToPixelGrid(
|
||||||
absoluteNodeRight,
|
absoluteNodeRight,
|
||||||
pointScaleFactor,
|
pointScaleFactor,
|
||||||
(textRounding && hasFractionalWidth),
|
(textRounding && hasFractionalWidth),
|
||||||
(textRounding && !hasFractionalWidth)) -
|
(textRounding && !hasFractionalWidth)) -
|
||||||
roundValueToPixelGrid(
|
roundValueToPixelGrid(
|
||||||
absoluteNodeLeft, pointScaleFactor, false, textRounding),
|
absoluteNodeLeft, pointScaleFactor, false, textRounding));
|
||||||
Dimension::Width);
|
|
||||||
|
|
||||||
node->setLayoutDimension(
|
node->getLayout().setDimension(
|
||||||
|
Dimension::Height,
|
||||||
roundValueToPixelGrid(
|
roundValueToPixelGrid(
|
||||||
absoluteNodeBottom,
|
absoluteNodeBottom,
|
||||||
pointScaleFactor,
|
pointScaleFactor,
|
||||||
(textRounding && hasFractionalHeight),
|
(textRounding && hasFractionalHeight),
|
||||||
(textRounding && !hasFractionalHeight)) -
|
(textRounding && !hasFractionalHeight)) -
|
||||||
roundValueToPixelGrid(
|
roundValueToPixelGrid(
|
||||||
absoluteNodeTop, pointScaleFactor, false, textRounding),
|
absoluteNodeTop, pointScaleFactor, false, textRounding));
|
||||||
Dimension::Height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (yoga::Node* child : node->getChildren()) {
|
for (yoga::Node* child : node->getChildren()) {
|
||||||
|
@@ -19,6 +19,7 @@ namespace facebook::yoga {
|
|||||||
#if defined(__cpp_exceptions)
|
#if defined(__cpp_exceptions)
|
||||||
throw std::logic_error(message);
|
throw std::logic_error(message);
|
||||||
#else
|
#else
|
||||||
|
static_cast<void>(message); // Unused
|
||||||
std::terminate();
|
std::terminate();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -36,12 +36,12 @@ enum struct LayoutPassReason : int {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LayoutData {
|
struct LayoutData {
|
||||||
int layouts;
|
int layouts = 0;
|
||||||
int measures;
|
int measures = 0;
|
||||||
uint32_t maxMeasureCache;
|
uint32_t maxMeasureCache = 0;
|
||||||
int cachedLayouts;
|
int cachedLayouts = 0;
|
||||||
int cachedMeasures;
|
int cachedMeasures = 0;
|
||||||
int measureCallbacks;
|
int measureCallbacks = 0;
|
||||||
std::array<int, static_cast<uint8_t>(LayoutPassReason::COUNT)>
|
std::array<int, static_cast<uint8_t>(LayoutPassReason::COUNT)>
|
||||||
measureCallbackReasonsCount;
|
measureCallbackReasonsCount;
|
||||||
};
|
};
|
||||||
|
@@ -66,10 +66,18 @@ struct LayoutResults {
|
|||||||
return measuredDimensions_[yoga::to_underlying(axis)];
|
return measuredDimensions_[yoga::to_underlying(axis)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rawDimension(Dimension axis) const {
|
||||||
|
return rawDimensions_[yoga::to_underlying(axis)];
|
||||||
|
}
|
||||||
|
|
||||||
void setMeasuredDimension(Dimension axis, float dimension) {
|
void setMeasuredDimension(Dimension axis, float dimension) {
|
||||||
measuredDimensions_[yoga::to_underlying(axis)] = dimension;
|
measuredDimensions_[yoga::to_underlying(axis)] = dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRawDimension(Dimension axis, float dimension) {
|
||||||
|
rawDimensions_[yoga::to_underlying(axis)] = dimension;
|
||||||
|
}
|
||||||
|
|
||||||
float position(PhysicalEdge physicalEdge) const {
|
float position(PhysicalEdge physicalEdge) const {
|
||||||
return position_[yoga::to_underlying(physicalEdge)];
|
return position_[yoga::to_underlying(physicalEdge)];
|
||||||
}
|
}
|
||||||
@@ -113,6 +121,7 @@ struct LayoutResults {
|
|||||||
|
|
||||||
std::array<float, 2> dimensions_ = {{YGUndefined, YGUndefined}};
|
std::array<float, 2> dimensions_ = {{YGUndefined, YGUndefined}};
|
||||||
std::array<float, 2> measuredDimensions_ = {{YGUndefined, YGUndefined}};
|
std::array<float, 2> measuredDimensions_ = {{YGUndefined, YGUndefined}};
|
||||||
|
std::array<float, 2> rawDimensions_ = {{YGUndefined, YGUndefined}};
|
||||||
std::array<float, 4> position_ = {};
|
std::array<float, 4> position_ = {};
|
||||||
std::array<float, 4> margin_ = {};
|
std::array<float, 4> margin_ = {};
|
||||||
std::array<float, 4> border_ = {};
|
std::array<float, 4> border_ = {};
|
||||||
|
@@ -181,6 +181,17 @@ void Node::setDirty(bool isDirty) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::setChildren(const std::vector<Node*>& children) {
|
||||||
|
children_ = children;
|
||||||
|
|
||||||
|
contentsChildrenCount_ = 0;
|
||||||
|
for (const auto& child : children) {
|
||||||
|
if (child->style().display() == Display::Contents) {
|
||||||
|
contentsChildrenCount_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Node::removeChild(Node* child) {
|
bool Node::removeChild(Node* child) {
|
||||||
auto p = std::find(children_.begin(), children_.end(), child);
|
auto p = std::find(children_.begin(), children_.end(), child);
|
||||||
if (p != children_.end()) {
|
if (p != children_.end()) {
|
||||||
@@ -247,6 +258,7 @@ void Node::setLayoutHadOverflow(bool hadOverflow) {
|
|||||||
|
|
||||||
void Node::setLayoutDimension(float lengthValue, Dimension dimension) {
|
void Node::setLayoutDimension(float lengthValue, Dimension dimension) {
|
||||||
layout_.setDimension(dimension, lengthValue);
|
layout_.setDimension(dimension, lengthValue);
|
||||||
|
layout_.setRawDimension(dimension, lengthValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both left and right are defined, then use left. Otherwise return +left or
|
// If both left and right are defined, then use left. Otherwise return +left or
|
||||||
@@ -379,6 +391,23 @@ void Node::cloneChildrenIfNeeded() {
|
|||||||
if (child->getOwner() != this) {
|
if (child->getOwner() != this) {
|
||||||
child = resolveRef(config_->cloneNode(child, this, i));
|
child = resolveRef(config_->cloneNode(child, this, i));
|
||||||
child->setOwner(this);
|
child->setOwner(this);
|
||||||
|
|
||||||
|
if (child->hasContentsChildren()) [[unlikely]] {
|
||||||
|
child->cloneContentsChildrenIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::cloneContentsChildrenIfNeeded() {
|
||||||
|
size_t i = 0;
|
||||||
|
for (Node*& child : children_) {
|
||||||
|
if (child->style().display() == Display::Contents &&
|
||||||
|
child->getOwner() != this) {
|
||||||
|
child = resolveRef(config_->cloneNode(child, this, i));
|
||||||
|
child->setOwner(this);
|
||||||
|
child->cloneChildrenIfNeeded();
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@@ -96,6 +96,10 @@ class YG_EXPORT Node : public ::YGNode {
|
|||||||
return config_->hasErrata(errata);
|
return config_->hasErrata(errata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasContentsChildren() const {
|
||||||
|
return contentsChildrenCount_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
YGDirtiedFunc getDirtiedFunc() const {
|
YGDirtiedFunc getDirtiedFunc() const {
|
||||||
return dirtiedFunc_;
|
return dirtiedFunc_;
|
||||||
}
|
}
|
||||||
@@ -244,15 +248,12 @@ class YG_EXPORT Node : public ::YGNode {
|
|||||||
owner_ = owner;
|
owner_ = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChildren(const std::vector<Node*>& children) {
|
|
||||||
children_ = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: rvalue override for setChildren
|
// TODO: rvalue override for setChildren
|
||||||
|
|
||||||
void setConfig(Config* config);
|
void setConfig(Config* config);
|
||||||
|
|
||||||
void setDirty(bool isDirty);
|
void setDirty(bool isDirty);
|
||||||
|
void setChildren(const std::vector<Node*>& children);
|
||||||
void setLayoutLastOwnerDirection(Direction direction);
|
void setLayoutLastOwnerDirection(Direction direction);
|
||||||
void setLayoutComputedFlexBasis(FloatOptional computedFlexBasis);
|
void setLayoutComputedFlexBasis(FloatOptional computedFlexBasis);
|
||||||
void setLayoutComputedFlexBasisGeneration(
|
void setLayoutComputedFlexBasisGeneration(
|
||||||
@@ -286,6 +287,7 @@ class YG_EXPORT Node : public ::YGNode {
|
|||||||
void removeChild(size_t index);
|
void removeChild(size_t index);
|
||||||
|
|
||||||
void cloneChildrenIfNeeded();
|
void cloneChildrenIfNeeded();
|
||||||
|
void cloneContentsChildrenIfNeeded();
|
||||||
void markDirtyAndPropagate();
|
void markDirtyAndPropagate();
|
||||||
float resolveFlexGrow() const;
|
float resolveFlexGrow() const;
|
||||||
float resolveFlexShrink() const;
|
float resolveFlexShrink() const;
|
||||||
|
Reference in New Issue
Block a user