Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0c3168f150 | ||
|
40861c699e | ||
|
d8fee24778 | ||
|
5c617a5947 | ||
|
ff0a3f39d9 | ||
|
bfb4dabf0c | ||
|
58d14ee557 | ||
|
c5182c4bf5 | ||
|
132b016bae | ||
|
4785e95a0c | ||
|
be94a5ef8d | ||
|
208b70a93c | ||
|
6c3155ae3b | ||
|
32f071c2ad | ||
|
fdd1dbe3a9 | ||
|
1ca5bb694d | ||
|
b4cfaa916c | ||
|
fc6c85996e | ||
|
969f055f47 | ||
|
58328d01ef | ||
|
d90914f3dc | ||
|
3a0a86788e | ||
|
a77aa9a41e | ||
|
7217471427 | ||
|
bcc36cc1b2 | ||
|
16052085d0 | ||
|
c20f2864ab | ||
|
4185a44393 | ||
|
c79c5e3c9d | ||
|
35a9f33abb | ||
|
32f128640b | ||
|
18d19af7ec | ||
|
2ee2dd439f | ||
|
5edfb679e7 | ||
|
f45059e1e6 | ||
|
c9384762ee | ||
|
7ea50439ce | ||
|
154e67adbc | ||
|
570a193b7e |
@@ -1,9 +1,10 @@
|
|||||||
[cxx]
|
[cxx]
|
||||||
gtest_dep = //lib/gtest:gtest
|
gtest_dep = //lib/gtest:gtest
|
||||||
[android]
|
[android]
|
||||||
target = android-23
|
target = android-25
|
||||||
|
build_tools_version = 26.0.2
|
||||||
[ndk]
|
[ndk]
|
||||||
ndk_version = 13.1.3345770
|
ndk_version = 15.2.4203891
|
||||||
compiler = clang
|
compiler = clang
|
||||||
app_platform = android-21
|
app_platform = android-21
|
||||||
cpu_abis = arm64, armv7, x86, x86_64
|
cpu_abis = arm64, armv7, x86, x86_64
|
||||||
|
@@ -12,6 +12,8 @@ compiler: clang
|
|||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/Library/Caches/Homebrew
|
- $HOME/Library/Caches/Homebrew
|
||||||
|
- $HOME/android-sdk
|
||||||
|
- $HOME/android-ndk
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- TARGET=c
|
- TARGET=c
|
||||||
@@ -73,6 +75,8 @@ before_install:
|
|||||||
export TERMINAL=dumb;
|
export TERMINAL=dumb;
|
||||||
source scripts/android-setup.sh && installAndroidSDK
|
source scripts/android-setup.sh && installAndroidSDK
|
||||||
export ANDROID_SDK=$ANDROID_HOME
|
export ANDROID_SDK=$ANDROID_HOME
|
||||||
|
export ANDROID_NDK_REPOSITORY=$HOME/android-ndk
|
||||||
|
export ANDROID_NDK_HOME=$ANDROID_NDK_REPOSITORY/android-ndk-r15c
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# JavaScript
|
# JavaScript
|
||||||
|
4
BUCK
4
BUCK
@@ -21,9 +21,9 @@ TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ["-std=c++11"
|
|||||||
cxx_library(
|
cxx_library(
|
||||||
name = "yoga",
|
name = "yoga",
|
||||||
srcs = glob(["yoga/*.c"]),
|
srcs = glob(["yoga/*.c"]),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
|
||||||
exported_headers = subdir_glob([("", "yoga/*.h")]),
|
|
||||||
header_namespace = "",
|
header_namespace = "",
|
||||||
|
exported_headers = subdir_glob([("", "yoga/*.h")]),
|
||||||
|
compiler_flags = COMPILER_FLAGS,
|
||||||
soname = "libyogacore.$(ext)",
|
soname = "libyogacore.$(ext)",
|
||||||
tests = [":YogaTests"],
|
tests = [":YogaTests"],
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |spec|
|
Pod::Spec.new do |spec|
|
||||||
spec.name = 'Yoga'
|
spec.name = 'Yoga'
|
||||||
spec.version = '1.6.0'
|
spec.version = '1.7.0'
|
||||||
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
||||||
spec.homepage = 'https://facebook.github.io/yoga/'
|
spec.homepage = 'https://facebook.github.io/yoga/'
|
||||||
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/c/'
|
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/c/'
|
||||||
@@ -11,7 +11,7 @@ Pod::Spec.new do |spec|
|
|||||||
spec.authors = 'Facebook'
|
spec.authors = 'Facebook'
|
||||||
spec.source = {
|
spec.source = {
|
||||||
:git => 'https://github.com/facebook/yoga.git',
|
:git => 'https://github.com/facebook/yoga.git',
|
||||||
:tag => '1.6.0',
|
:tag => '1.7.0',
|
||||||
}
|
}
|
||||||
|
|
||||||
spec.module_name = 'yoga'
|
spec.module_name = 'yoga'
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
podspec = Pod::Spec.new do |spec|
|
podspec = Pod::Spec.new do |spec|
|
||||||
spec.name = 'YogaKit'
|
spec.name = 'YogaKit'
|
||||||
spec.version = '1.6.0'
|
spec.version = '1.7.0'
|
||||||
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
spec.license = { :type => 'BSD', :file => "LICENSE" }
|
||||||
spec.homepage = 'https://facebook.github.io/yoga/'
|
spec.homepage = 'https://facebook.github.io/yoga/'
|
||||||
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/'
|
spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/'
|
||||||
@@ -11,14 +11,14 @@ podspec = Pod::Spec.new do |spec|
|
|||||||
spec.authors = 'Facebook'
|
spec.authors = 'Facebook'
|
||||||
spec.source = {
|
spec.source = {
|
||||||
:git => 'https://github.com/facebook/yoga.git',
|
:git => 'https://github.com/facebook/yoga.git',
|
||||||
:tag => '1.6.0',
|
:tag => '1.7.0',
|
||||||
}
|
}
|
||||||
|
|
||||||
spec.platform = :ios
|
spec.platform = :ios
|
||||||
spec.ios.deployment_target = '8.0'
|
spec.ios.deployment_target = '8.0'
|
||||||
spec.ios.frameworks = 'UIKit'
|
spec.ios.frameworks = 'UIKit'
|
||||||
|
|
||||||
spec.dependency 'Yoga', '~> 1.6'
|
spec.dependency 'Yoga', '~> 1.7'
|
||||||
spec.source_files = 'YogaKit/Source/*.{h,m,swift}'
|
spec.source_files = 'YogaKit/Source/*.{h,m,swift}'
|
||||||
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
||||||
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
||||||
|
@@ -30,12 +30,13 @@ COMPILER_FLAGS = [
|
|||||||
apple_library(
|
apple_library(
|
||||||
name = "YogaKit",
|
name = "YogaKit",
|
||||||
srcs = glob(["Source/**/*.m"]),
|
srcs = glob(["Source/**/*.m"]),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
|
||||||
exported_headers = glob(["Source/**/*.h"]),
|
exported_headers = glob(["Source/**/*.h"]),
|
||||||
|
compiler_flags = COMPILER_FLAGS,
|
||||||
frameworks = [
|
frameworks = [
|
||||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||||
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
|
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
|
||||||
],
|
],
|
||||||
|
link_whole = True,
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
yoga_dep(":yoga"),
|
yoga_dep(":yoga"),
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
YogaKit is available to install via [CocoaPods](https://cocoapods.org/).
|
YogaKit is available to install via [CocoaPods](https://cocoapods.org/).
|
||||||
|
|
||||||
```
|
```
|
||||||
pod 'YogaKit', '~> 1.6'
|
pod 'YogaKit', '~> 1.7'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
@@ -20,6 +20,10 @@ typedef void (^YGLayoutConfigurationBlock)(YGLayout *);
|
|||||||
The YGLayout that is attached to this view. It is lazily created.
|
The YGLayout that is attached to this view. It is lazily created.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, strong) YGLayout *yoga;
|
@property (nonatomic, readonly, strong) YGLayout *yoga;
|
||||||
|
/**
|
||||||
|
Indicates whether or not Yoga is enabled
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, assign) BOOL isYogaEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend`
|
In ObjC land, every time you access `view.yoga.*` you are adding another `objc_msgSend`
|
||||||
|
@@ -26,6 +26,11 @@ static const void *kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
|
|||||||
return yoga;
|
return yoga;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)isYogaEnabled
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
|
||||||
{
|
{
|
||||||
if (block != nil) {
|
if (block != nil) {
|
||||||
|
@@ -361,7 +361,7 @@ static void YGAttachNodesFromViewHierachy(UIView *const view)
|
|||||||
|
|
||||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||||
for (UIView *subview in view.subviews) {
|
for (UIView *subview in view.subviews) {
|
||||||
if (subview.yoga.isIncludedInLayout) {
|
if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) {
|
||||||
[subviewsToInclude addObject:subview];
|
[subviewsToInclude addObject:subview];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,9 @@ PODS:
|
|||||||
- IGListKit/Default (2.1.0):
|
- IGListKit/Default (2.1.0):
|
||||||
- IGListKit/Diffing
|
- IGListKit/Diffing
|
||||||
- IGListKit/Diffing (2.1.0)
|
- IGListKit/Diffing (2.1.0)
|
||||||
- Yoga (1.6.0)
|
- Yoga (1.7.0)
|
||||||
- YogaKit (1.6.0):
|
- YogaKit (1.7.0):
|
||||||
- Yoga (~> 1.6)
|
- Yoga (~> 1.7)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- IGListKit (~> 2.1.0)
|
- IGListKit (~> 2.1.0)
|
||||||
|
@@ -22,7 +22,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':yoga')
|
api project(':yoga')
|
||||||
}
|
}
|
||||||
|
|
||||||
task sourcesJar(type: Jar) {
|
task sourcesJar(type: Jar) {
|
||||||
|
@@ -10,6 +10,8 @@ include_defs("//YOGA_DEFS")
|
|||||||
cxx_binary(
|
cxx_binary(
|
||||||
name = "benchmark",
|
name = "benchmark",
|
||||||
srcs = glob(["*.c"]),
|
srcs = glob(["*.c"]),
|
||||||
|
headers = subdir_glob([("", "*.h")]),
|
||||||
|
header_namespace = "",
|
||||||
compiler_flags = [
|
compiler_flags = [
|
||||||
"-fno-omit-frame-pointer",
|
"-fno-omit-frame-pointer",
|
||||||
"-fexceptions",
|
"-fexceptions",
|
||||||
@@ -18,8 +20,6 @@ cxx_binary(
|
|||||||
"-O3",
|
"-O3",
|
||||||
"-std=c11",
|
"-std=c11",
|
||||||
],
|
],
|
||||||
header_namespace = "",
|
|
||||||
headers = subdir_glob([("", "*.h")]),
|
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
yoga_dep(":yoga"),
|
yoga_dep(":yoga"),
|
||||||
|
10
build.gradle
10
build.gradle
@@ -3,12 +3,12 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://maven.google.com/' }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
||||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
|
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
|
||||||
classpath 'com.nabilhachicha:android-native-dependencies:0.1'
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
@@ -24,8 +24,8 @@ allprojects {
|
|||||||
ext {
|
ext {
|
||||||
minSdkVersion = 14
|
minSdkVersion = 14
|
||||||
targetSdkVersion = 25
|
targetSdkVersion = 25
|
||||||
compileSdkVersion = 25
|
compileSdkVersion = 26
|
||||||
buildToolsVersion = '25.0.2'
|
buildToolsVersion = '26.0.2'
|
||||||
sourceCompatibilityVersion = JavaVersion.VERSION_1_7
|
sourceCompatibilityVersion = JavaVersion.VERSION_1_7
|
||||||
targetCompatibilityVersion = JavaVersion.VERSION_1_7
|
targetCompatibilityVersion = JavaVersion.VERSION_1_7
|
||||||
}
|
}
|
||||||
|
@@ -595,12 +595,14 @@ namespace Facebook.Yoga
|
|||||||
Native.YGNodeSetBaselineFunc(_ygNode, _managedBaseline);
|
Native.YGNodeSetBaselineFunc(_ygNode, _managedBaseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateLayout()
|
public void CalculateLayout(
|
||||||
|
float width = YogaConstants.Undefined,
|
||||||
|
float height = YogaConstants.Undefined)
|
||||||
{
|
{
|
||||||
Native.YGNodeCalculateLayout(
|
Native.YGNodeCalculateLayout(
|
||||||
_ygNode,
|
_ygNode,
|
||||||
YogaConstants.Undefined,
|
width,
|
||||||
YogaConstants.Undefined,
|
height,
|
||||||
Native.YGNodeStyleGetDirection(_ygNode));
|
Native.YGNodeStyleGetDirection(_ygNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
#if __IOS__
|
#if __IOS__
|
||||||
using NativeView = UIKit.UIView;
|
using NativeView = UIKit.UIView;
|
||||||
|
using NativeScrollView = UIKit.UIScrollView;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Facebook.YogaKit
|
namespace Facebook.YogaKit
|
||||||
@@ -699,12 +700,12 @@ namespace Facebook.YogaKit
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _node.StyleAspectRatio;
|
return _node.AspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_node.StyleAspectRatio = value;
|
_node.AspectRatio = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,6 +717,17 @@ namespace Facebook.YogaKit
|
|||||||
float width = 0;
|
float width = 0;
|
||||||
float height = 0;
|
float height = 0;
|
||||||
GetWidthHeightOfNativeView(view, out width, out height);
|
GetWidthHeightOfNativeView(view, out width, out height);
|
||||||
|
if (view is NativeScrollView)
|
||||||
|
{
|
||||||
|
if (FlexDirection == YogaFlexDirection.Column || FlexDirection == YogaFlexDirection.ColumnReverse)
|
||||||
|
{
|
||||||
|
height = float.NaN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = float.NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
CalculateLayoutWithSize(this, width, height);
|
CalculateLayoutWithSize(this, width, height);
|
||||||
ApplyLayoutToViewHierarchy(view);
|
ApplyLayoutToViewHierarchy(view);
|
||||||
}
|
}
|
||||||
@@ -743,9 +755,7 @@ namespace Facebook.YogaKit
|
|||||||
|
|
||||||
var node = layout._node;
|
var node = layout._node;
|
||||||
|
|
||||||
node.Width = width;
|
node.CalculateLayout(width, height);
|
||||||
node.Height = height;
|
|
||||||
node.CalculateLayout();
|
|
||||||
|
|
||||||
return new SizeF { Width = node.LayoutWidth, Height = node.LayoutHeight };
|
return new SizeF { Width = node.LayoutWidth, Height = node.LayoutHeight };
|
||||||
}
|
}
|
||||||
@@ -775,14 +785,14 @@ namespace Facebook.YogaKit
|
|||||||
float result;
|
float result;
|
||||||
if (measureMode == YogaMeasureMode.Exactly)
|
if (measureMode == YogaMeasureMode.Exactly)
|
||||||
{
|
{
|
||||||
result = (float)constrainedSize;
|
result = constrainedSize;
|
||||||
}
|
}
|
||||||
else if (measureMode == YogaMeasureMode.AtMost)
|
else if (measureMode == YogaMeasureMode.AtMost)
|
||||||
{
|
{
|
||||||
result = (float)Math.Min(constrainedSize, measuredSize);
|
result = Math.Min(constrainedSize, measuredSize);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = (float)measuredSize;
|
result = measuredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -820,7 +830,7 @@ namespace Facebook.YogaKit
|
|||||||
var subviewsToInclude = new List<NativeView>();
|
var subviewsToInclude = new List<NativeView>();
|
||||||
foreach (var subview in view.Subviews)
|
foreach (var subview in view.Subviews)
|
||||||
{
|
{
|
||||||
if (subview.Yoga().IsIncludeInLayout)
|
if (subview.Yoga().IsEnabled && subview.Yoga().IsIncludeInLayout)
|
||||||
{
|
{
|
||||||
subviewsToInclude.Add(subview);
|
subviewsToInclude.Add(subview);
|
||||||
}
|
}
|
||||||
@@ -856,7 +866,7 @@ namespace Facebook.YogaKit
|
|||||||
|
|
||||||
static double RoundPointValue(float value)
|
static double RoundPointValue(float value)
|
||||||
{
|
{
|
||||||
float scale = NativePointScale;
|
float scale = NativePixelScale;
|
||||||
|
|
||||||
return Math.Round(value * scale) / scale;
|
return Math.Round(value * scale) / scale;
|
||||||
}
|
}
|
||||||
|
@@ -22,8 +22,6 @@
|
|||||||
<MtouchDebug>true</MtouchDebug>
|
<MtouchDebug>true</MtouchDebug>
|
||||||
<MtouchFastDev>true</MtouchFastDev>
|
<MtouchFastDev>true</MtouchFastDev>
|
||||||
<MtouchProfiling>true</MtouchProfiling>
|
<MtouchProfiling>true</MtouchProfiling>
|
||||||
<MtouchUseSGen>true</MtouchUseSGen>
|
|
||||||
<MtouchUseRefCounting>true</MtouchUseRefCounting>
|
|
||||||
<IOSDebuggerPort>17481</IOSDebuggerPort>
|
<IOSDebuggerPort>17481</IOSDebuggerPort>
|
||||||
<MtouchLink>None</MtouchLink>
|
<MtouchLink>None</MtouchLink>
|
||||||
<MtouchArch>x86_64</MtouchArch>
|
<MtouchArch>x86_64</MtouchArch>
|
||||||
@@ -39,8 +37,6 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<CodesignKey>iPhone Developer</CodesignKey>
|
<CodesignKey>iPhone Developer</CodesignKey>
|
||||||
<MtouchUseSGen>true</MtouchUseSGen>
|
|
||||||
<MtouchUseRefCounting>true</MtouchUseRefCounting>
|
|
||||||
<MtouchFloat32>true</MtouchFloat32>
|
<MtouchFloat32>true</MtouchFloat32>
|
||||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||||
<MtouchLink>SdkOnly</MtouchLink>
|
<MtouchLink>SdkOnly</MtouchLink>
|
||||||
@@ -56,8 +52,6 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<CodesignKey>iPhone Developer</CodesignKey>
|
<CodesignKey>iPhone Developer</CodesignKey>
|
||||||
<MtouchUseSGen>true</MtouchUseSGen>
|
|
||||||
<MtouchUseRefCounting>true</MtouchUseRefCounting>
|
|
||||||
<MtouchLink>None</MtouchLink>
|
<MtouchLink>None</MtouchLink>
|
||||||
<MtouchArch>x86_64</MtouchArch>
|
<MtouchArch>x86_64</MtouchArch>
|
||||||
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
@@ -76,8 +70,6 @@
|
|||||||
<MtouchDebug>true</MtouchDebug>
|
<MtouchDebug>true</MtouchDebug>
|
||||||
<MtouchFastDev>true</MtouchFastDev>
|
<MtouchFastDev>true</MtouchFastDev>
|
||||||
<MtouchProfiling>true</MtouchProfiling>
|
<MtouchProfiling>true</MtouchProfiling>
|
||||||
<MtouchUseSGen>true</MtouchUseSGen>
|
|
||||||
<MtouchUseRefCounting>true</MtouchUseRefCounting>
|
|
||||||
<MtouchFloat32>true</MtouchFloat32>
|
<MtouchFloat32>true</MtouchFloat32>
|
||||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||||
<MtouchLink>SdkOnly</MtouchLink>
|
<MtouchLink>SdkOnly</MtouchLink>
|
||||||
@@ -102,6 +94,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Main.cs" />
|
<Compile Include="Main.cs" />
|
||||||
<Compile Include="UnitTestAppDelegate.cs" />
|
<Compile Include="UnitTestAppDelegate.cs" />
|
||||||
|
<Compile Include="YogaKitNativeTest.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Facebook.YogaKit.iOS\Facebook.YogaKit.iOS.csproj">
|
<ProjectReference Include="..\Facebook.YogaKit.iOS\Facebook.YogaKit.iOS.csproj">
|
||||||
|
51
csharp/iOS/Facebook.YogaKit.iOS.Tests/YogaKitNativeTest.cs
Normal file
51
csharp/iOS/Facebook.YogaKit.iOS.Tests/YogaKitNativeTest.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using Facebook.Yoga;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using UIKit;
|
||||||
|
using CoreGraphics;
|
||||||
|
|
||||||
|
namespace Facebook.YogaKit.iOS.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class YogaKitNativeTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void ScrollViewVertical()
|
||||||
|
{
|
||||||
|
var view = new UIScrollView() {
|
||||||
|
Frame = new CGRect(0, 0, 100, 100),
|
||||||
|
};
|
||||||
|
|
||||||
|
view.Yoga().Overflow = YogaOverflow.Scroll;
|
||||||
|
var subview = new UIView();
|
||||||
|
subview.Yoga().Height = 1000;
|
||||||
|
subview.Yoga().IsEnabled = true;
|
||||||
|
|
||||||
|
view.AddSubview(subview);
|
||||||
|
view.Yoga().IsEnabled = true;
|
||||||
|
view.Yoga().ApplyLayout();
|
||||||
|
Assert.True(view.ContentSize.Height == 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void NormalViewVertical()
|
||||||
|
{
|
||||||
|
var view = new UIView() {
|
||||||
|
Frame = new CGRect(0,0, 100, 100),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var subview = new UIView();
|
||||||
|
subview.Yoga().Height = 1000;
|
||||||
|
subview.Yoga().Width = 2;
|
||||||
|
subview.Yoga().IsEnabled = true;
|
||||||
|
|
||||||
|
view.AddSubview(subview);
|
||||||
|
view.Yoga().IsEnabled = true;
|
||||||
|
view.Yoga().ApplyLayout();
|
||||||
|
Assert.True(view.Bounds.Height == 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -23,14 +23,21 @@ namespace Facebook.YogaKit
|
|||||||
height = (float)view.Bounds.Height;
|
height = (float)view.Bounds.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float NativePixelScale => (float)UIScreen.MainScreen.Scale;
|
static float NativePixelScale => (float)UIScreen.MainScreen.Scale;
|
||||||
|
|
||||||
|
|
||||||
static void ApplyLayoutToNativeView(UIView view, YogaNode node)
|
static void ApplyLayoutToNativeView(UIView view, YogaNode node)
|
||||||
{
|
{
|
||||||
var topLeft = new CGPoint(node.LayoutX, node.LayoutY);
|
var topLeft = new CGPoint(node.LayoutX, node.LayoutY);
|
||||||
var bottomRight = new CGPoint(topLeft.X + node.LayoutWidth, topLeft.Y + node.LayoutHeight);
|
var bottomRight = new CGPoint(topLeft.X + node.LayoutWidth, topLeft.Y + node.LayoutHeight);
|
||||||
view.Frame = new CGRect(RoundPointValue((float)topLeft.X), RoundPointValue((float)topLeft.Y), RoundPointValue((float)bottomRight.X) - RoundPointValue((float)topLeft.X), RoundPointValue((float)bottomRight.Y) - RoundPointValue((float)topLeft.Y));
|
if (view is UIScrollView scrollView)
|
||||||
|
{
|
||||||
|
scrollView.ContentSize = new CGSize(RoundPointValue((float)bottomRight.X) - RoundPointValue((float)topLeft.X), RoundPointValue((float)bottomRight.Y) - RoundPointValue((float)topLeft.Y));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
view.Frame = new CGRect(RoundPointValue((float)topLeft.X), RoundPointValue((float)topLeft.Y), RoundPointValue((float)bottomRight.X) - RoundPointValue((float)topLeft.X), RoundPointValue((float)bottomRight.Y) - RoundPointValue((float)topLeft.Y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
|
@@ -8,36 +8,11 @@ permalink: /docs/api/csharp/
|
|||||||
|
|
||||||
### Lifecycle
|
### Lifecycle
|
||||||
|
|
||||||
Create a `YogaNode` via its default constructor or the static `Create()` builder method and use `Reset` if you want to pool and re-use nodes. The native memory of a `YogaNode` will automatically be freed when the node is garbage collected.
|
Create a `YogaNode` via its default constructor and use `Reset` if you want to pool and re-use nodes. The native memory of a `YogaNode` will automatically be freed when the node is garbage collected.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
YogaNode();
|
YogaNode();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
static YogaNode Create(
|
|
||||||
YogaDirection? styleDirection = null,
|
|
||||||
YogaFlexDirection? flexDirection = null,
|
|
||||||
YogaJustify? justifyContent = null,
|
|
||||||
YogaAlign? alignContent = null,
|
|
||||||
YogaAlign? alignItems = null,
|
|
||||||
YogaAlign? alignSelf = null,
|
|
||||||
YogaPositionType? positionType = null,
|
|
||||||
YogaWrap? wrap = null,
|
|
||||||
YogaOverflow? overflow = null,
|
|
||||||
float? flex = null,
|
|
||||||
float? flexGrow = null,
|
|
||||||
float? flexShrink = null,
|
|
||||||
float? flexBasis = null,
|
|
||||||
Spacing position = null,
|
|
||||||
Spacing margin = null,
|
|
||||||
Spacing padding = null,
|
|
||||||
Spacing border = null,
|
|
||||||
float? Width = null,
|
|
||||||
float? Height = null,
|
|
||||||
float? MaxWidth = null,
|
|
||||||
float? MaxHeight = null,
|
|
||||||
float? MinWidth = null,
|
|
||||||
float? MinHeight = null);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Children
|
### Children
|
||||||
@@ -95,6 +70,9 @@ enum YogaAlign
|
|||||||
Center,
|
Center,
|
||||||
FlexEnd,
|
FlexEnd,
|
||||||
Stretch,
|
Stretch,
|
||||||
|
Baseline,
|
||||||
|
SpaceBetween,
|
||||||
|
SpaceAround
|
||||||
}
|
}
|
||||||
|
|
||||||
YogaAlign AlignItems {get, set};
|
YogaAlign AlignItems {get, set};
|
||||||
@@ -113,6 +91,7 @@ enum YogaWrap
|
|||||||
{
|
{
|
||||||
NoWrap,
|
NoWrap,
|
||||||
Wrap,
|
Wrap,
|
||||||
|
WrapReverse
|
||||||
}
|
}
|
||||||
|
|
||||||
YogaWrap Wrap {get, set};
|
YogaWrap Wrap {get, set};
|
||||||
@@ -197,18 +176,13 @@ enum YogaMeasureMode
|
|||||||
AtMost,
|
AtMost,
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate long MeasureFunction(
|
public delegate YogaSize MeasureFunction(
|
||||||
YogaNode node,
|
YogaNode node,
|
||||||
float width,
|
float width,
|
||||||
YogaMeasureMode widthMode,
|
YogaMeasureMode widthMode,
|
||||||
float height,
|
float height,
|
||||||
YogaMeasureMode heightMode);
|
YogaMeasureMode heightMode);
|
||||||
|
|
||||||
class MeasureOutput
|
|
||||||
{
|
|
||||||
public static long Make(int width, int height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMeasureFunction(MeasureFunction measureFunction);
|
void SetMeasureFunction(MeasureFunction measureFunction);
|
||||||
bool IsMeasureDefined();
|
bool IsMeasureDefined();
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ permalink: /docs/api/yogakit/
|
|||||||
|
|
||||||
YogaKit is a Objective-C (and Swift-compatible) wrapper for Yoga. It allows iOS Developers to manage the layout of their views using the power of Yoga.
|
YogaKit is a Objective-C (and Swift-compatible) wrapper for Yoga. It allows iOS Developers to manage the layout of their views using the power of Yoga.
|
||||||
|
|
||||||
Layout configuration is done via the [YGLayout](https://github.com/facebook/yoga/blob/master/YogaKit/YGLayout.h) object. YogaKit exposes `YGLayout` via a [category](https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Category.html) on [UIView](https://developer.apple.com/reference/uikit/uiview).
|
Layout configuration is done via the [YGLayout](https://github.com/facebook/yoga/blob/master/YogaKit/Source/YGLayout.h) object. YogaKit exposes `YGLayout` via a [category](https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Category.html) on [UIView](https://developer.apple.com/reference/uikit/uiview).
|
||||||
|
|
||||||
### Lifecycle
|
### Lifecycle
|
||||||
|
|
||||||
|
@@ -124,18 +124,20 @@ root.addChildAt(image, 1);
|
|||||||
<div class="blockContent">
|
<div class="blockContent">
|
||||||
<div markdown="1" style="width: 700px; max-width: 100%;">
|
<div markdown="1" style="width: 700px; max-width: 100%;">
|
||||||
```csharp
|
```csharp
|
||||||
YogaNode root = YogaNode.Create(
|
YogaNode root = new YogaNode {
|
||||||
width: 500,
|
Width = 500,
|
||||||
height: 300,
|
Height = 300
|
||||||
);
|
};
|
||||||
|
|
||||||
YogaNode image = YogaNode.Create(flexGrow: 1);
|
YogaNode image = new YogaNode {
|
||||||
|
FlexGrow = 1
|
||||||
|
};
|
||||||
|
|
||||||
YogaNode text = YogaNode.Create(
|
YogaNode text = new YogaNode {
|
||||||
width: 300,
|
Width = 300,
|
||||||
height: 25,
|
Height = 25,
|
||||||
margin: new Spacing(left: 20, top: 20, right: 20, bottom: 20),
|
Margin = 20
|
||||||
);
|
};
|
||||||
|
|
||||||
root.Insert(image, 0);
|
root.Insert(image, 0);
|
||||||
root.Insert(text, 1);
|
root.Insert(text, 1);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
|
||||||
VERSION_NAME=1.6.0
|
VERSION_NAME=1.7.0
|
||||||
POM_URL=https://github.com/facebook/yoga
|
POM_URL=https://github.com/facebook/yoga
|
||||||
POM_SCM_URL=https://github.com/facebook/yoga.git
|
POM_SCM_URL=https://github.com/facebook/yoga.git
|
||||||
POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git
|
POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-bin.zip
|
||||||
|
11
java/BUCK
11
java/BUCK
@@ -10,6 +10,7 @@ include_defs("//YOGA_DEFS")
|
|||||||
cxx_library(
|
cxx_library(
|
||||||
name = "jni",
|
name = "jni",
|
||||||
srcs = glob(["jni/*.cpp"]),
|
srcs = glob(["jni/*.cpp"]),
|
||||||
|
header_namespace = "",
|
||||||
compiler_flags = [
|
compiler_flags = [
|
||||||
"-fno-omit-frame-pointer",
|
"-fno-omit-frame-pointer",
|
||||||
"-fexceptions",
|
"-fexceptions",
|
||||||
@@ -19,7 +20,6 @@ cxx_library(
|
|||||||
"-O3",
|
"-O3",
|
||||||
"-std=c++11",
|
"-std=c++11",
|
||||||
],
|
],
|
||||||
header_namespace = "",
|
|
||||||
soname = "libyoga.$(ext)",
|
soname = "libyoga.$(ext)",
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
@@ -32,6 +32,7 @@ cxx_library(
|
|||||||
java_library(
|
java_library(
|
||||||
name = "java",
|
name = "java",
|
||||||
srcs = glob(["com/facebook/yoga/*.java"]),
|
srcs = glob(["com/facebook/yoga/*.java"]),
|
||||||
|
required_for_source_only_abi = True,
|
||||||
source = "1.7",
|
source = "1.7",
|
||||||
target = "1.7",
|
target = "1.7",
|
||||||
tests = [
|
tests = [
|
||||||
@@ -58,3 +59,11 @@ java_test(
|
|||||||
JUNIT_TARGET,
|
JUNIT_TARGET,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
java_binary(
|
||||||
|
name = "yoga",
|
||||||
|
deps = [
|
||||||
|
":java",
|
||||||
|
FBJNI_JAVA_TARGET,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@@ -50,10 +50,10 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.1'
|
compileOnly 'com.google.code.findbugs:jsr305:3.0.1'
|
||||||
compile 'com.facebook.soloader:soloader:0.2.0'
|
compileOnly project(':yoga:proguard-annotations')
|
||||||
provided project(':yoga:proguard-annotations')
|
implementation 'com.facebook.soloader:soloader:0.2.0'
|
||||||
testCompile 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
task sourcesJar(type: Jar) {
|
task sourcesJar(type: Jar) {
|
||||||
|
@@ -422,9 +422,7 @@ void jni_YGConfigSetLogger(alias_ref<jobject>, jlong nativePointer, alias_ref<jo
|
|||||||
|
|
||||||
auto context = YGConfigGetContext(config);
|
auto context = YGConfigGetContext(config);
|
||||||
if (context) {
|
if (context) {
|
||||||
auto jlogger = reinterpret_cast<global_ref<jobject> *>(context);
|
delete reinterpret_cast<global_ref<jobject> *>(context);
|
||||||
jlogger->releaseAlias();
|
|
||||||
delete jlogger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger) {
|
if (logger) {
|
||||||
|
43
java/tests/com/facebook/yoga/YogaLoggerTest.java
Normal file
43
java/tests/com/facebook/yoga/YogaLoggerTest.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.yoga;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
public class YogaLoggerTest {
|
||||||
|
@Test
|
||||||
|
public void testLoggerLeak() throws Exception {
|
||||||
|
final YogaConfig config = new YogaConfig();
|
||||||
|
YogaLogger logger = new YogaLogger() {
|
||||||
|
@Override
|
||||||
|
public void log(YogaNode yogaNode, YogaLogLevel level, String message) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
config.setLogger(logger);
|
||||||
|
config.setLogger(null);
|
||||||
|
WeakReference<Object> ref = new WeakReference<Object>(logger);
|
||||||
|
// noinspection UnusedAssignment
|
||||||
|
logger = null;
|
||||||
|
// try and free for the next 5 seconds, usually it works after the
|
||||||
|
// first GC attempt.
|
||||||
|
for (int i=0; i < 50; i++) {
|
||||||
|
System.gc();
|
||||||
|
if (ref.get() == null) {
|
||||||
|
// free successfully
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
fail("YogaLogger leaked");
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yoga-layout",
|
"name": "yoga-layout",
|
||||||
"version": "1.6.0",
|
"version": "1.7.0",
|
||||||
"description": "Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.",
|
"description": "Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@@ -22,6 +22,8 @@ prebuilt_cxx_library(
|
|||||||
cxx_library(
|
cxx_library(
|
||||||
name = "fbjni",
|
name = "fbjni",
|
||||||
srcs = glob(["src/main/cpp/**/*.cpp"]),
|
srcs = glob(["src/main/cpp/**/*.cpp"]),
|
||||||
|
header_namespace = "",
|
||||||
|
exported_headers = subdir_glob([("src/main/cpp/include", "**/*.h")]),
|
||||||
compiler_flags = [
|
compiler_flags = [
|
||||||
"-DLOG_TAG=\"libfb\"",
|
"-DLOG_TAG=\"libfb\"",
|
||||||
"-DDISABLE_CPUCAP",
|
"-DDISABLE_CPUCAP",
|
||||||
@@ -35,8 +37,6 @@ cxx_library(
|
|||||||
"-Wno-unused-parameter",
|
"-Wno-unused-parameter",
|
||||||
"-std=c++11",
|
"-std=c++11",
|
||||||
],
|
],
|
||||||
exported_headers = subdir_glob([("src/main/cpp/include", "**/*.h")]),
|
|
||||||
header_namespace = "",
|
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
deps = [
|
deps = [
|
||||||
":ndklog",
|
":ndklog",
|
||||||
|
@@ -26,8 +26,8 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.facebook.soloader:soloader:0.2.0'
|
implementation 'com.facebook.soloader:soloader:0.2.0'
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.1'
|
compileOnly 'com.google.code.findbugs:jsr305:3.0.1'
|
||||||
compile project(':yoga:proguard-annotations')
|
compileOnly project(':yoga:proguard-annotations')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,13 +15,13 @@ COMPILER_FLAGS = [
|
|||||||
cxx_library(
|
cxx_library(
|
||||||
name = "gtest",
|
name = "gtest",
|
||||||
srcs = glob(["googletest/googletest/src/*.cc"]),
|
srcs = glob(["googletest/googletest/src/*.cc"]),
|
||||||
compiler_flags = COMPILER_FLAGS,
|
header_namespace = "",
|
||||||
exported_headers = subdir_glob([
|
exported_headers = subdir_glob([
|
||||||
("googletest/googletest/include", "**/*.h"),
|
("googletest/googletest/include", "**/*.h"),
|
||||||
("googletest/googletest", "src/*.h"),
|
("googletest/googletest", "src/*.h"),
|
||||||
("googletest/googletest", "src/*.cc"),
|
("googletest/googletest", "src/*.cc"),
|
||||||
]),
|
]),
|
||||||
header_namespace = "",
|
compiler_flags = COMPILER_FLAGS,
|
||||||
visibility = YOGA_ROOTS,
|
visibility = YOGA_ROOTS,
|
||||||
deps = [],
|
deps = [],
|
||||||
)
|
)
|
||||||
|
@@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
cxx_library(
|
cxx_library(
|
||||||
name = "jni",
|
name = "jni",
|
||||||
|
header_namespace = "",
|
||||||
exported_headers = [
|
exported_headers = [
|
||||||
"jni.h",
|
"jni.h",
|
||||||
"real/jni.h",
|
"real/jni.h",
|
||||||
],
|
],
|
||||||
force_static = True,
|
force_static = True,
|
||||||
header_namespace = "",
|
|
||||||
visibility = ["PUBLIC"],
|
visibility = ["PUBLIC"],
|
||||||
)
|
)
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
function download() {
|
function download() {
|
||||||
|
echo "Downloading '$1' to '$2' ..."
|
||||||
if hash curl 2>/dev/null; then
|
if hash curl 2>/dev/null; then
|
||||||
curl -L -o $2 $1
|
curl --retry 10 -L -o "$2" "$1"
|
||||||
elif hash wget 2>/dev/null; then
|
elif hash wget 2>/dev/null; then
|
||||||
wget -O $2 $1
|
wget -O "$2" "$1"
|
||||||
else
|
else
|
||||||
echo >&2 "No supported download tool installed. Please get either wget or curl."
|
echo >&2 "No supported download tool installed. Please get either wget or curl."
|
||||||
exit
|
exit
|
||||||
@@ -17,21 +18,32 @@ function installsdk() {
|
|||||||
PROXY_ARGS="--proxy=http --proxy_host=$PROXY_HOST --proxy_port=$PROXY_PORT"
|
PROXY_ARGS="--proxy=http --proxy_host=$PROXY_HOST --proxy_port=$PROXY_PORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
yes | $ANDROID_HOME/tools/bin/sdkmanager $PROXY_ARGS $@
|
yes | "$ANDROID_HOME/tools/bin/sdkmanager" $PROXY_ARGS $@
|
||||||
}
|
}
|
||||||
|
|
||||||
function installAndroidSDK {
|
function installAndroidSDK {
|
||||||
TMP=/tmp/sdk$$.zip
|
|
||||||
download 'https://dl.google.com/android/repository/tools_r25.2.3-linux.zip' $TMP
|
|
||||||
unzip -d $HOME/android-sdk $TMP
|
|
||||||
rm $TMP
|
|
||||||
|
|
||||||
export ANDROID_HOME=$HOME/android-sdk
|
export ANDROID_HOME=$HOME/android-sdk
|
||||||
|
export ANDROID_NDK_REPOSITORY=$HOME/android-ndk
|
||||||
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$PATH"
|
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$PATH"
|
||||||
|
|
||||||
mkdir -p $ANDROID_HOME/licenses/
|
if [[ ! -f "$ANDROID_HOME/tools/bin/sdkmanager" ]]; then
|
||||||
echo > $ANDROID_HOME/licenses/android-sdk-license
|
TMP=/tmp/sdk$$.zip
|
||||||
echo -n 8933bad161af4178b1185d1a37fbf41ea5269c55 > $ANDROID_HOME/licenses/android-sdk-license
|
download 'https://dl.google.com/android/repository/sdk-tools-darwin-3859397.zip' $TMP
|
||||||
|
unzip -qod "$ANDROID_HOME" "$TMP"
|
||||||
|
rm $TMP
|
||||||
|
fi
|
||||||
|
|
||||||
installsdk 'build-tools;23.0.2' 'build-tools;25.0.2' 'build-tools;25.0.1' 'platforms;android-23' 'platforms;android-25' 'ndk-bundle' 'extras;android;m2repository'
|
if [[ ! -d "$ANDROID_NDK_REPOSITORY/android-ndk-r15c" ]]; then
|
||||||
|
TMP=/tmp/ndk$$.zip
|
||||||
|
mkdir -p "$ANDROID_NDK_REPOSITORY"
|
||||||
|
download 'https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip' $TMP
|
||||||
|
unzip -qod "$ANDROID_NDK_REPOSITORY" "$TMP"
|
||||||
|
rm $TMP
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$ANDROID_HOME/licenses/"
|
||||||
|
echo > "$ANDROID_HOME/licenses/android-sdk-license"
|
||||||
|
echo -n d56f5187479451eabf01fb78af6dfcb131a6481e >> "$ANDROID_HOME/licenses/android-sdk-license"
|
||||||
|
|
||||||
|
installsdk 'build-tools;26.0.2' 'platform-tools' 'platforms;android-23' 'platforms;android-25' 'extras;android;m2repository'
|
||||||
}
|
}
|
||||||
|
@@ -171,6 +171,38 @@ TEST(YogaTest, aspect_ratio_flex_shrink) {
|
|||||||
YGNodeFreeRecursive(root);
|
YGNodeFreeRecursive(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, aspect_ratio_flex_shrink_2) {
|
||||||
|
const YGNodeRef root = YGNodeNew();
|
||||||
|
YGNodeStyleSetWidth(root, 100);
|
||||||
|
YGNodeStyleSetHeight(root, 100);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNew();
|
||||||
|
YGNodeStyleSetHeightPercent(root_child0, 100);
|
||||||
|
YGNodeStyleSetFlexShrink(root_child0, 1);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child0, 1);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1 = YGNodeNew();
|
||||||
|
YGNodeStyleSetHeightPercent(root_child1, 100);
|
||||||
|
YGNodeStyleSetFlexShrink(root_child1, 1);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child1, 1);
|
||||||
|
YGNodeInsertChild(root, root_child1, 1);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetTop(root_child1));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child1));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(YogaTest, aspect_ratio_basis) {
|
TEST(YogaTest, aspect_ratio_basis) {
|
||||||
const YGNodeRef root = YGNodeNew();
|
const YGNodeRef root = YGNodeNew();
|
||||||
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
|
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
|
||||||
@@ -562,8 +594,8 @@ TEST(YogaTest, aspect_ratio_overrides_flex_grow_row) {
|
|||||||
|
|
||||||
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
|
ASSERT_EQ(200, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
YGNodeFreeRecursive(root);
|
YGNodeFreeRecursive(root);
|
||||||
}
|
}
|
||||||
@@ -584,8 +616,8 @@ TEST(YogaTest, aspect_ratio_overrides_flex_grow_column) {
|
|||||||
|
|
||||||
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0));
|
||||||
ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
YGNodeFreeRecursive(root);
|
YGNodeFreeRecursive(root);
|
||||||
}
|
}
|
||||||
@@ -747,3 +779,96 @@ TEST(YogaTest, aspect_ratio_defined_cross_with_margin) {
|
|||||||
|
|
||||||
YGNodeFreeRecursive(root);
|
YGNodeFreeRecursive(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, aspect_ratio_should_prefer_explicit_height) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
YGConfigSetUseWebDefaults(config, true);
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionColumn);
|
||||||
|
YGNodeStyleSetHeight(root_child0_child0, 100);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child0_child0, 2);
|
||||||
|
YGNodeInsertChild(root_child0, root_child0_child0, 0);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, 100, 200, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_EQ(200, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, aspect_ratio_should_prefer_explicit_width) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
YGConfigSetUseWebDefaults(config, true);
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow);
|
||||||
|
YGNodeStyleSetWidth(root_child0_child0, 100);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child0_child0, 0.5);
|
||||||
|
YGNodeInsertChild(root_child0, root_child0_child0, 0);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(200, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
|
||||||
|
ASSERT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, aspect_ratio_should_prefer_flexed_dimension) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
YGConfigSetUseWebDefaults(config, true);
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child0, 2);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child0, 1);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetAspectRatio(root_child0_child0, 4);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child0_child0, 1);
|
||||||
|
YGNodeInsertChild(root_child0, root_child0_child0, 0);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
|
||||||
|
ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
}
|
||||||
|
55
tests/YGInfiniteHeightTest.cpp
Normal file
55
tests/YGInfiniteHeightTest.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
|
||||||
|
// This test isn't correct from the Flexbox standard standpoint,
|
||||||
|
// because percentages are calculated with parent constraints.
|
||||||
|
// However, we need to make sure we fail gracefully in this case, not returning NaN
|
||||||
|
TEST(YogaTest, percent_absolute_position_infinite_height) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
|
||||||
|
YGNodeStyleSetWidth(root, 300);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetWidth(root_child0, 300);
|
||||||
|
YGNodeStyleSetHeight(root_child0, 300);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetPositionType(root_child1, YGPositionTypeAbsolute);
|
||||||
|
YGNodeStyleSetPositionPercent(root_child1, YGEdgeLeft, 20);
|
||||||
|
YGNodeStyleSetPositionPercent(root_child1, YGEdgeTop, 20);
|
||||||
|
YGNodeStyleSetWidthPercent(root_child1, 20);
|
||||||
|
YGNodeStyleSetHeightPercent(root_child1, 20);
|
||||||
|
YGNodeInsertChild(root, root_child1, 1);
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
||||||
|
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
251
tests/YGPersistenceTest.cpp
Normal file
251
tests/YGPersistenceTest.cpp
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
|
||||||
|
TEST(YogaTest, cloning_shared_root) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetWidth(root, 100);
|
||||||
|
YGNodeStyleSetHeight(root, 100);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child0, 1);
|
||||||
|
YGNodeStyleSetFlexBasis(root_child0, 50);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child1, 1);
|
||||||
|
YGNodeInsertChild(root, root_child1, 1);
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
|
||||||
|
const YGNodeRef root2 = YGNodeClone(root);
|
||||||
|
YGNodeStyleSetWidth(root2, 100);
|
||||||
|
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
||||||
|
// The children should have referential equality at this point.
|
||||||
|
ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
|
||||||
|
ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
||||||
|
// Relayout with no changed input should result in referential equality.
|
||||||
|
ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
|
||||||
|
ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
|
||||||
|
|
||||||
|
YGNodeStyleSetWidth(root2, 150);
|
||||||
|
YGNodeStyleSetHeight(root2, 200);
|
||||||
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
||||||
|
// Relayout with changed input should result in cloned children.
|
||||||
|
const YGNodeRef root2_child0 = YGNodeGetChild(root2, 0);
|
||||||
|
const YGNodeRef root2_child1 = YGNodeGetChild(root2, 1);
|
||||||
|
ASSERT_NE(root_child0, root2_child0);
|
||||||
|
ASSERT_NE(root_child1, root2_child1);
|
||||||
|
|
||||||
|
// Everything in the root should remain unchanged.
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
|
||||||
|
// The new root now has new layout.
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2));
|
||||||
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2));
|
||||||
|
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root2));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child0));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2_child0));
|
||||||
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child0));
|
||||||
|
ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root2_child0));
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child1));
|
||||||
|
ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root2_child1));
|
||||||
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child1));
|
||||||
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root2_child1));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root2);
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, mutating_children_of_a_clone_clones) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
ASSERT_EQ(0, YGNodeGetChildCount(root));
|
||||||
|
|
||||||
|
const YGNodeRef root2 = YGNodeClone(root);
|
||||||
|
ASSERT_EQ(0, YGNodeGetChildCount(root2));
|
||||||
|
|
||||||
|
const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeInsertChild(root2, root2_child0, 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, YGNodeGetChildCount(root));
|
||||||
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
||||||
|
|
||||||
|
const YGNodeRef root3 = YGNodeClone(root2);
|
||||||
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
||||||
|
ASSERT_EQ(1, YGNodeGetChildCount(root3));
|
||||||
|
ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
||||||
|
|
||||||
|
const YGNodeRef root3_child1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeInsertChild(root3, root3_child1, 1);
|
||||||
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
||||||
|
ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
|
||||||
|
ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
||||||
|
|
||||||
|
const YGNodeRef root4 = YGNodeClone(root3);
|
||||||
|
ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));
|
||||||
|
|
||||||
|
YGNodeRemoveChild(root4, root3_child1);
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
||||||
|
ASSERT_EQ(1, YGNodeGetChildCount(root4));
|
||||||
|
ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root4);
|
||||||
|
YGNodeFreeRecursive(root3);
|
||||||
|
YGNodeFreeRecursive(root2);
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, cloning_two_levels) {
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetWidth(root, 100);
|
||||||
|
YGNodeStyleSetHeight(root, 100);
|
||||||
|
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child0, 1);
|
||||||
|
YGNodeStyleSetFlexBasis(root_child0, 15);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child1, 1);
|
||||||
|
YGNodeInsertChild(root, root_child1, 1);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1_0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexBasis(root_child1_0, 10);
|
||||||
|
YGNodeStyleSetFlexGrow(root_child1_0, 1);
|
||||||
|
YGNodeInsertChild(root_child1, root_child1_0, 0);
|
||||||
|
|
||||||
|
const YGNodeRef root_child1_1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetFlexBasis(root_child1_1, 25);
|
||||||
|
YGNodeInsertChild(root_child1, root_child1_1, 1);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
|
||||||
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
|
||||||
|
|
||||||
|
const YGNodeRef root2_child0 = YGNodeClone(root_child0);
|
||||||
|
const YGNodeRef root2_child1 = YGNodeClone(root_child1);
|
||||||
|
const YGNodeRef root2 = YGNodeClone(root);
|
||||||
|
|
||||||
|
YGNodeStyleSetFlexGrow(root2_child0, 0);
|
||||||
|
YGNodeStyleSetFlexBasis(root2_child0, 40);
|
||||||
|
|
||||||
|
YGNodeRemoveAllChildren(root2);
|
||||||
|
YGNodeInsertChild(root2, root2_child0, 0);
|
||||||
|
YGNodeInsertChild(root2, root2_child1, 1);
|
||||||
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
// Original root is unchanged
|
||||||
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
|
||||||
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
|
||||||
|
ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
|
||||||
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
|
||||||
|
|
||||||
|
// New root has new layout at the top
|
||||||
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root2_child0));
|
||||||
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root2_child1));
|
||||||
|
|
||||||
|
// The deeper children are untouched.
|
||||||
|
ASSERT_EQ(YGNodeGetChild(root2_child1, 0), root_child1_0);
|
||||||
|
ASSERT_EQ(YGNodeGetChild(root2_child1, 1), root_child1_1);
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root2);
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(YogaTest, cloning_and_freeing) {
|
||||||
|
const int32_t initialInstanceCount = YGNodeGetInstanceCount();
|
||||||
|
|
||||||
|
const YGConfigRef config = YGConfigNew();
|
||||||
|
|
||||||
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeStyleSetWidth(root, 100);
|
||||||
|
YGNodeStyleSetHeight(root, 100);
|
||||||
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeInsertChild(root, root_child0, 0);
|
||||||
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
||||||
|
YGNodeInsertChild(root, root_child1, 1);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
const YGNodeRef root2 = YGNodeClone(root);
|
||||||
|
|
||||||
|
// Freeing the original root should be safe as long as we don't free its children.
|
||||||
|
YGNodeFree(root);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root2);
|
||||||
|
|
||||||
|
YGNodeFree(root_child0);
|
||||||
|
YGNodeFree(root_child1);
|
||||||
|
|
||||||
|
YGConfigFree(config);
|
||||||
|
|
||||||
|
ASSERT_EQ(initialInstanceCount, YGNodeGetInstanceCount());
|
||||||
|
}
|
31
tests/YGRoundingFunctionTest.cpp
Normal file
31
tests/YGRoundingFunctionTest.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
#include <yoga/Yoga-internal.h>
|
||||||
|
|
||||||
|
TEST(YogaTest, rounding_value) {
|
||||||
|
// Test that whole numbers are rounded to whole despite ceil/floor flags
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, true));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, true));
|
||||||
|
|
||||||
|
// Test that numbers with fraction are rounded correctly accounting for ceil/floor flags
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.5, YGRoundValueToPixelGrid(6.01, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, true));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(5.5, YGRoundValueToPixelGrid(5.99, 2.0, false, true));
|
||||||
|
}
|
39
tests/YGZeroOutLayoutRecursivlyTest.cpp
Normal file
39
tests/YGZeroOutLayoutRecursivlyTest.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
|
||||||
|
TEST(YogaTest, zero_out_layout) {
|
||||||
|
const YGNodeRef root = YGNodeNew();
|
||||||
|
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
|
||||||
|
YGNodeStyleSetWidth(root, 200);
|
||||||
|
YGNodeStyleSetHeight(root, 200);
|
||||||
|
|
||||||
|
const YGNodeRef child = YGNodeNew();
|
||||||
|
YGNodeInsertChild(root, child, 0);
|
||||||
|
YGNodeStyleSetWidth(child, 100);
|
||||||
|
YGNodeStyleSetHeight(child, 100);
|
||||||
|
YGNodeStyleSetMargin(child, YGEdgeTop, 10);
|
||||||
|
YGNodeStyleSetPadding(child, YGEdgeTop, 10);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetMargin(child, YGEdgeTop));
|
||||||
|
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetPadding(child, YGEdgeTop));
|
||||||
|
|
||||||
|
YGNodeStyleSetDisplay(child, YGDisplayNone);
|
||||||
|
|
||||||
|
YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
|
||||||
|
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(child, YGEdgeTop));
|
||||||
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(child, YGEdgeTop));
|
||||||
|
|
||||||
|
YGNodeFreeRecursive(root);
|
||||||
|
}
|
@@ -7,6 +7,8 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "YGNodeList.h"
|
#include "YGNodeList.h"
|
||||||
|
|
||||||
extern YGMalloc gYGMalloc;
|
extern YGMalloc gYGMalloc;
|
||||||
@@ -72,6 +74,17 @@ void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t
|
|||||||
list->items[index] = node;
|
list->items[index] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void YGNodeListReplace(YGNodeListRef list, const uint32_t index, const YGNodeRef newNode) {
|
||||||
|
list->items[index] = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void YGNodeListRemoveAll(const YGNodeListRef list) {
|
||||||
|
for (uint32_t i = 0; i < list->count; i++) {
|
||||||
|
list->items[i] = NULL;
|
||||||
|
}
|
||||||
|
list->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index) {
|
YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index) {
|
||||||
const YGNodeRef removed = list->items[index];
|
const YGNodeRef removed = list->items[index];
|
||||||
list->items[index] = NULL;
|
list->items[index] = NULL;
|
||||||
@@ -102,3 +115,17 @@ YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index) {
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YGNodeListRef YGNodeListClone(const YGNodeListRef oldList) {
|
||||||
|
if (!oldList) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const uint32_t count = oldList->count;
|
||||||
|
if (count == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const YGNodeListRef newList = YGNodeListNew(count);
|
||||||
|
memcpy(newList->items, oldList->items, sizeof(YGNodeRef) * count);
|
||||||
|
newList->count = count;
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
@@ -26,8 +26,11 @@ void YGNodeListFree(const YGNodeListRef list);
|
|||||||
uint32_t YGNodeListCount(const YGNodeListRef list);
|
uint32_t YGNodeListCount(const YGNodeListRef list);
|
||||||
void YGNodeListAdd(YGNodeListRef *listp, const YGNodeRef node);
|
void YGNodeListAdd(YGNodeListRef *listp, const YGNodeRef node);
|
||||||
void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t index);
|
void YGNodeListInsert(YGNodeListRef *listp, const YGNodeRef node, const uint32_t index);
|
||||||
|
void YGNodeListReplace(const YGNodeListRef list, const uint32_t index, const YGNodeRef newNode);
|
||||||
|
void YGNodeListRemoveAll(const YGNodeListRef list);
|
||||||
YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index);
|
YGNodeRef YGNodeListRemove(const YGNodeListRef list, const uint32_t index);
|
||||||
YGNodeRef YGNodeListDelete(const YGNodeListRef list, const YGNodeRef node);
|
YGNodeRef YGNodeListDelete(const YGNodeListRef list, const YGNodeRef node);
|
||||||
YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index);
|
YGNodeRef YGNodeListGet(const YGNodeListRef list, const uint32_t index);
|
||||||
|
YGNodeListRef YGNodeListClone(YGNodeListRef list);
|
||||||
|
|
||||||
YG_EXTERN_C_END
|
YG_EXTERN_C_END
|
||||||
|
19
yoga/Yoga-internal.h
Normal file
19
yoga/Yoga-internal.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
YG_EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
WIN_EXPORT float YGRoundValueToPixelGrid(const float value,
|
||||||
|
const float pointScaleFactor,
|
||||||
|
const bool forceCeil,
|
||||||
|
const bool forceFloor);
|
||||||
|
|
||||||
|
YG_EXTERN_C_END
|
533
yoga/Yoga.c
533
yoga/Yoga.c
@@ -10,6 +10,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "YGNodeList.h"
|
#include "YGNodeList.h"
|
||||||
|
#include "Yoga-internal.h"
|
||||||
#include "Yoga.h"
|
#include "Yoga.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -101,6 +102,7 @@ typedef struct YGConfig {
|
|||||||
bool useLegacyStretchBehaviour;
|
bool useLegacyStretchBehaviour;
|
||||||
float pointScaleFactor;
|
float pointScaleFactor;
|
||||||
YGLogger logger;
|
YGLogger logger;
|
||||||
|
YGNodeClonedFunc cloneNodeCallback;
|
||||||
void *context;
|
void *context;
|
||||||
} YGConfig;
|
} YGConfig;
|
||||||
|
|
||||||
@@ -155,7 +157,7 @@ static const float kDefaultFlexGrow = 0.0f;
|
|||||||
static const float kDefaultFlexShrink = 0.0f;
|
static const float kDefaultFlexShrink = 0.0f;
|
||||||
static const float kWebDefaultFlexShrink = 1.0f;
|
static const float kWebDefaultFlexShrink = 1.0f;
|
||||||
|
|
||||||
static YGNode gYGNodeDefaults = {
|
static const YGNode gYGNodeDefaults = {
|
||||||
.parent = NULL,
|
.parent = NULL,
|
||||||
.children = NULL,
|
.children = NULL,
|
||||||
.hasNewLayout = true,
|
.hasNewLayout = true,
|
||||||
@@ -361,6 +363,17 @@ YGNodeRef YGNodeNew(void) {
|
|||||||
return YGNodeNewWithConfig(&gYGConfigDefaults);
|
return YGNodeNewWithConfig(&gYGConfigDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YGNodeRef YGNodeClone(const YGNodeRef oldNode) {
|
||||||
|
const YGNodeRef node = gYGMalloc(sizeof(YGNode));
|
||||||
|
YGAssertWithConfig(oldNode->config, node != NULL, "Could not allocate memory for node");
|
||||||
|
gNodeInstanceCount++;
|
||||||
|
|
||||||
|
memcpy(node, oldNode, sizeof(YGNode));
|
||||||
|
node->children = YGNodeListClone(oldNode->children);
|
||||||
|
node->parent = NULL;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
void YGNodeFree(const YGNodeRef node) {
|
void YGNodeFree(const YGNodeRef node) {
|
||||||
if (node->parent) {
|
if (node->parent) {
|
||||||
YGNodeListDelete(node->parent->children, node);
|
YGNodeListDelete(node->parent->children, node);
|
||||||
@@ -381,6 +394,10 @@ void YGNodeFree(const YGNodeRef node) {
|
|||||||
void YGNodeFreeRecursive(const YGNodeRef root) {
|
void YGNodeFreeRecursive(const YGNodeRef root) {
|
||||||
while (YGNodeGetChildCount(root) > 0) {
|
while (YGNodeGetChildCount(root) > 0) {
|
||||||
const YGNodeRef child = YGNodeGetChild(root, 0);
|
const YGNodeRef child = YGNodeGetChild(root, 0);
|
||||||
|
if (child->parent != root) {
|
||||||
|
// Don't free shared nodes that we don't own.
|
||||||
|
break;
|
||||||
|
}
|
||||||
YGNodeRemoveChild(root, child);
|
YGNodeRemoveChild(root, child);
|
||||||
YGNodeFreeRecursive(child);
|
YGNodeFreeRecursive(child);
|
||||||
}
|
}
|
||||||
@@ -473,6 +490,34 @@ YGBaselineFunc YGNodeGetBaselineFunc(const YGNodeRef node) {
|
|||||||
return node->baseline;
|
return node->baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void YGCloneChildrenIfNeeded(const YGNodeRef parent) {
|
||||||
|
// YGNodeRemoveChild has a forked variant of this algorithm optimized for deletions.
|
||||||
|
const uint32_t childCount = YGNodeGetChildCount(parent);
|
||||||
|
if (childCount == 0) {
|
||||||
|
// This is an empty set. Nothing to clone.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
|
||||||
|
if (firstChild->parent == parent) {
|
||||||
|
// If the first child has this node as its parent, 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 immutable.
|
||||||
|
// We also assume that all its sibling are cloned as well.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const YGNodeClonedFunc cloneNodeCallback = parent->config->cloneNodeCallback;
|
||||||
|
const YGNodeListRef children = parent->children;
|
||||||
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
|
const YGNodeRef oldChild = YGNodeListGet(children, i);
|
||||||
|
const YGNodeRef newChild = YGNodeClone(oldChild);
|
||||||
|
YGNodeListReplace(children, i, newChild);
|
||||||
|
newChild->parent = parent;
|
||||||
|
if (cloneNodeCallback) {
|
||||||
|
cloneNodeCallback(oldChild, newChild, parent, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) {
|
void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) {
|
||||||
YGAssertWithNode(node,
|
YGAssertWithNode(node,
|
||||||
child->parent == NULL,
|
child->parent == NULL,
|
||||||
@@ -481,17 +526,81 @@ void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32
|
|||||||
node->measure == NULL,
|
node->measure == NULL,
|
||||||
"Cannot add child: Nodes with measure functions cannot have children.");
|
"Cannot add child: Nodes with measure functions cannot have children.");
|
||||||
|
|
||||||
|
YGCloneChildrenIfNeeded(node);
|
||||||
|
|
||||||
YGNodeListInsert(&node->children, child, index);
|
YGNodeListInsert(&node->children, child, index);
|
||||||
child->parent = node;
|
child->parent = node;
|
||||||
YGNodeMarkDirtyInternal(node);
|
YGNodeMarkDirtyInternal(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child) {
|
void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) {
|
||||||
if (YGNodeListDelete(node->children, child) != NULL) {
|
// This algorithm is a forked variant from YGCloneChildrenIfNeeded that excludes a child.
|
||||||
child->layout = gYGNodeDefaults.layout; // layout is no longer valid
|
const uint32_t childCount = YGNodeGetChildCount(parent);
|
||||||
child->parent = NULL;
|
if (childCount == 0) {
|
||||||
YGNodeMarkDirtyInternal(node);
|
// This is an empty set. Nothing to remove.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
|
||||||
|
if (firstChild->parent == parent) {
|
||||||
|
// If the first child has this node as its parent, we assume that it is already unique.
|
||||||
|
// We can now try to delete a child in this list.
|
||||||
|
if (YGNodeListDelete(parent->children, excludedChild) != NULL) {
|
||||||
|
excludedChild->layout = gYGNodeDefaults.layout; // layout is no longer valid
|
||||||
|
excludedChild->parent = NULL;
|
||||||
|
YGNodeMarkDirtyInternal(parent);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Otherwise we have to clone the node list except for the child we're trying to delete.
|
||||||
|
// We don't want to simply clone all children, because then the host will need to free
|
||||||
|
// the clone of the child that was just deleted.
|
||||||
|
const YGNodeClonedFunc cloneNodeCallback = parent->config->cloneNodeCallback;
|
||||||
|
const YGNodeListRef children = parent->children;
|
||||||
|
uint32_t nextInsertIndex = 0;
|
||||||
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
|
const YGNodeRef oldChild = YGNodeListGet(children, i);
|
||||||
|
if (excludedChild == oldChild) {
|
||||||
|
// Ignore the deleted child. Don't reset its layout or parent since it is still valid
|
||||||
|
// in the other parent. However, since this parent has now changed, we need to mark it
|
||||||
|
// as dirty.
|
||||||
|
YGNodeMarkDirtyInternal(parent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const YGNodeRef newChild = YGNodeClone(oldChild);
|
||||||
|
YGNodeListReplace(children, nextInsertIndex, newChild);
|
||||||
|
newChild->parent = parent;
|
||||||
|
if (cloneNodeCallback) {
|
||||||
|
cloneNodeCallback(oldChild, newChild, parent, nextInsertIndex);
|
||||||
|
}
|
||||||
|
nextInsertIndex++;
|
||||||
|
}
|
||||||
|
while (nextInsertIndex < childCount) {
|
||||||
|
YGNodeListRemove(children, nextInsertIndex);
|
||||||
|
nextInsertIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void YGNodeRemoveAllChildren(const YGNodeRef parent) {
|
||||||
|
const uint32_t childCount = YGNodeGetChildCount(parent);
|
||||||
|
if (childCount == 0) {
|
||||||
|
// This is an empty set already. Nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
|
||||||
|
if (firstChild->parent == parent) {
|
||||||
|
// If the first child has this node as its parent, we assume that this child set is unique.
|
||||||
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
|
const YGNodeRef oldChild = YGNodeGetChild(parent, i);
|
||||||
|
oldChild->layout = gYGNodeDefaults.layout; // layout is no longer valid
|
||||||
|
oldChild->parent = NULL;
|
||||||
|
}
|
||||||
|
YGNodeListRemoveAll(parent->children);
|
||||||
|
YGNodeMarkDirtyInternal(parent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Otherwise, we are not the owner of the child set. We don't have to do anything to clear it.
|
||||||
|
parent->children = NULL;
|
||||||
|
YGNodeMarkDirtyInternal(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index) {
|
YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index) {
|
||||||
@@ -502,7 +611,7 @@ YGNodeRef YGNodeGetParent(const YGNodeRef node) {
|
|||||||
return node->parent;
|
return node->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t YGNodeGetChildCount(const YGNodeRef node) {
|
uint32_t YGNodeGetChildCount(const YGNodeRef node) {
|
||||||
return YGNodeListCount(node->children);
|
return YGNodeListCount(node->children);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,53 +947,84 @@ static inline bool YGFloatsEqual(const float a, const float b) {
|
|||||||
return fabs(a - b) < 0.0001f;
|
return fabs(a - b) < 0.0001f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGIndent(const YGNodeRef node, const uint32_t n) {
|
typedef struct YGStringStream {
|
||||||
|
char *str;
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t capacity;
|
||||||
|
} YGStringStream;
|
||||||
|
|
||||||
|
static void YGWriteToStringStream(YGStringStream *stream, const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
va_list argsCopy;
|
||||||
|
va_copy(argsCopy, args);
|
||||||
|
int available = stream->capacity - stream->length;
|
||||||
|
int required = vsnprintf(NULL, 0, format, args);
|
||||||
|
va_end(args);
|
||||||
|
if (required >= available) {
|
||||||
|
char *newStr = (char *) realloc(stream->str, sizeof(char) * (stream->capacity) * 2);
|
||||||
|
if (newStr != NULL) {
|
||||||
|
stream->str = newStr;
|
||||||
|
stream->capacity *= 2;
|
||||||
|
available = stream->capacity - stream->length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
vsnprintf(stream->str + stream->length, available, format, argsCopy);
|
||||||
|
if (required < available) {
|
||||||
|
stream->length += required;
|
||||||
|
} else {
|
||||||
|
stream->length = stream->capacity - 1;
|
||||||
|
}
|
||||||
|
va_end(argsCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YGIndent(YGStringStream *stream, const uint32_t n) {
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
YGLog(node, YGLogLevelDebug, " ");
|
YGWriteToStringStream(stream, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintNumberIfNotUndefinedf(const YGNodeRef node,
|
static void YGPrintNumberIfNotUndefinedf(YGStringStream *stream,
|
||||||
const char *str,
|
const char *str,
|
||||||
const float number) {
|
const float number) {
|
||||||
if (!YGFloatIsUndefined(number)) {
|
if (!YGFloatIsUndefined(number)) {
|
||||||
YGLog(node, YGLogLevelDebug, "%s: %g; ", str, number);
|
YGWriteToStringStream(stream, "%s: %g; ", str, number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintNumberIfNotUndefined(const YGNodeRef node,
|
static void YGPrintNumberIfNotUndefined(YGStringStream *stream,
|
||||||
const char *str,
|
const char *str,
|
||||||
const YGValue *const number) {
|
const YGValue *const number) {
|
||||||
if (number->unit != YGUnitUndefined) {
|
if (number->unit != YGUnitUndefined) {
|
||||||
if (number->unit == YGUnitAuto) {
|
if (number->unit == YGUnitAuto) {
|
||||||
YGLog(node, YGLogLevelDebug, "%s: auto; ", str);
|
YGWriteToStringStream(stream, "%s: auto; ", str);
|
||||||
} else {
|
} else {
|
||||||
const char *unit = number->unit == YGUnitPoint ? "px" : "%";
|
const char *unit = number->unit == YGUnitPoint ? "px" : "%%";
|
||||||
YGLog(node, YGLogLevelDebug, "%s: %g%s; ", str, number->value, unit);
|
YGWriteToStringStream(stream, "%s: %g%s; ", str, number->value, unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintNumberIfNotAuto(const YGNodeRef node,
|
static void YGPrintNumberIfNotAuto(YGStringStream *stream,
|
||||||
const char *str,
|
const char *str,
|
||||||
const YGValue *const number) {
|
const YGValue *const number) {
|
||||||
if (number->unit != YGUnitAuto) {
|
if (number->unit != YGUnitAuto) {
|
||||||
YGPrintNumberIfNotUndefined(node, str, number);
|
YGPrintNumberIfNotUndefined(stream, str, number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintEdgeIfNotUndefined(const YGNodeRef node,
|
static void YGPrintEdgeIfNotUndefined(YGStringStream *stream,
|
||||||
const char *str,
|
const char *str,
|
||||||
const YGValue *edges,
|
const YGValue *edges,
|
||||||
const YGEdge edge) {
|
const YGEdge edge) {
|
||||||
YGPrintNumberIfNotUndefined(node, str, YGComputedEdgeValue(edges, edge, &YGValueUndefined));
|
YGPrintNumberIfNotUndefined(stream, str, YGComputedEdgeValue(edges, edge, &YGValueUndefined));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintNumberIfNotZero(const YGNodeRef node,
|
static void YGPrintNumberIfNotZero(YGStringStream *stream,
|
||||||
const char *str,
|
const char *str,
|
||||||
const YGValue *const number) {
|
const YGValue *const number) {
|
||||||
if (!YGFloatsEqual(number->value, 0)) {
|
if (!YGFloatsEqual(number->value, 0)) {
|
||||||
YGPrintNumberIfNotUndefined(node, str, number);
|
YGPrintNumberIfNotUndefined(stream, str, number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,122 +1033,133 @@ static bool YGFourValuesEqual(const YGValue four[4]) {
|
|||||||
YGValueEqual(four[0], four[3]);
|
YGValueEqual(four[0], four[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGPrintEdges(const YGNodeRef node, const char *str, const YGValue *edges) {
|
static void YGPrintEdges(YGStringStream *stream, const char *str, const YGValue *edges) {
|
||||||
if (YGFourValuesEqual(edges)) {
|
if (YGFourValuesEqual(edges)) {
|
||||||
YGPrintNumberIfNotZero(node, str, &edges[YGEdgeLeft]);
|
YGPrintNumberIfNotZero(stream, str, &edges[YGEdgeLeft]);
|
||||||
} else {
|
} else {
|
||||||
for (YGEdge edge = YGEdgeLeft; edge < YGEdgeCount; edge++) {
|
for (YGEdge edge = YGEdgeLeft; edge < YGEdgeCount; edge++) {
|
||||||
char buf[30];
|
char buf[30];
|
||||||
snprintf(buf, sizeof(buf), "%s-%s", str, YGEdgeToString(edge));
|
snprintf(buf, sizeof(buf), "%s-%s", str, YGEdgeToString(edge));
|
||||||
YGPrintNumberIfNotZero(node, buf, &edges[edge]);
|
YGPrintNumberIfNotZero(stream, buf, &edges[edge]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGNodePrintInternal(const YGNodeRef node,
|
static void YGNodeToString(YGStringStream *stream,
|
||||||
const YGPrintOptions options,
|
const YGNodeRef node,
|
||||||
const uint32_t level) {
|
const YGPrintOptions options,
|
||||||
YGIndent(node, level);
|
const uint32_t level) {
|
||||||
YGLog(node, YGLogLevelDebug, "<div ");
|
YGIndent(stream, level);
|
||||||
|
YGWriteToStringStream(stream, "<div ");
|
||||||
|
|
||||||
if (node->print) {
|
if (node->print) {
|
||||||
node->print(node);
|
node->print(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options & YGPrintOptionsLayout) {
|
if (options & YGPrintOptionsLayout) {
|
||||||
YGLog(node, YGLogLevelDebug, "layout=\"");
|
YGWriteToStringStream(stream, "layout=\"");
|
||||||
YGLog(node, YGLogLevelDebug, "width: %g; ", node->layout.dimensions[YGDimensionWidth]);
|
YGWriteToStringStream(stream, "width: %g; ", node->layout.dimensions[YGDimensionWidth]);
|
||||||
YGLog(node, YGLogLevelDebug, "height: %g; ", node->layout.dimensions[YGDimensionHeight]);
|
YGWriteToStringStream(stream, "height: %g; ", node->layout.dimensions[YGDimensionHeight]);
|
||||||
YGLog(node, YGLogLevelDebug, "top: %g; ", node->layout.position[YGEdgeTop]);
|
YGWriteToStringStream(stream, "top: %g; ", node->layout.position[YGEdgeTop]);
|
||||||
YGLog(node, YGLogLevelDebug, "left: %g;", node->layout.position[YGEdgeLeft]);
|
YGWriteToStringStream(stream, "left: %g;", node->layout.position[YGEdgeLeft]);
|
||||||
YGLog(node, YGLogLevelDebug, "\" ");
|
YGWriteToStringStream(stream, "\" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options & YGPrintOptionsStyle) {
|
if (options & YGPrintOptionsStyle) {
|
||||||
YGLog(node, YGLogLevelDebug, "style=\"");
|
YGWriteToStringStream(stream, "style=\"");
|
||||||
if (node->style.flexDirection != gYGNodeDefaults.style.flexDirection) {
|
if (node->style.flexDirection != gYGNodeDefaults.style.flexDirection) {
|
||||||
YGLog(node,
|
YGWriteToStringStream(stream,
|
||||||
YGLogLevelDebug,
|
"flex-direction: %s; ",
|
||||||
"flex-direction: %s; ",
|
YGFlexDirectionToString(node->style.flexDirection));
|
||||||
YGFlexDirectionToString(node->style.flexDirection));
|
|
||||||
}
|
}
|
||||||
if (node->style.justifyContent != gYGNodeDefaults.style.justifyContent) {
|
if (node->style.justifyContent != gYGNodeDefaults.style.justifyContent) {
|
||||||
YGLog(node,
|
YGWriteToStringStream(stream,
|
||||||
YGLogLevelDebug,
|
"justify-content: %s; ",
|
||||||
"justify-content: %s; ",
|
YGJustifyToString(node->style.justifyContent));
|
||||||
YGJustifyToString(node->style.justifyContent));
|
|
||||||
}
|
}
|
||||||
if (node->style.alignItems != gYGNodeDefaults.style.alignItems) {
|
if (node->style.alignItems != gYGNodeDefaults.style.alignItems) {
|
||||||
YGLog(node, YGLogLevelDebug, "align-items: %s; ", YGAlignToString(node->style.alignItems));
|
YGWriteToStringStream(stream, "align-items: %s; ", YGAlignToString(node->style.alignItems));
|
||||||
}
|
}
|
||||||
if (node->style.alignContent != gYGNodeDefaults.style.alignContent) {
|
if (node->style.alignContent != gYGNodeDefaults.style.alignContent) {
|
||||||
YGLog(node, YGLogLevelDebug, "align-content: %s; ", YGAlignToString(node->style.alignContent));
|
YGWriteToStringStream(stream, "align-content: %s; ", YGAlignToString(node->style.alignContent));
|
||||||
}
|
}
|
||||||
if (node->style.alignSelf != gYGNodeDefaults.style.alignSelf) {
|
if (node->style.alignSelf != gYGNodeDefaults.style.alignSelf) {
|
||||||
YGLog(node, YGLogLevelDebug, "align-self: %s; ", YGAlignToString(node->style.alignSelf));
|
YGWriteToStringStream(stream, "align-self: %s; ", YGAlignToString(node->style.alignSelf));
|
||||||
}
|
}
|
||||||
|
|
||||||
YGPrintNumberIfNotUndefinedf(node, "flex-grow", node->style.flexGrow);
|
YGPrintNumberIfNotUndefinedf(stream, "flex-grow", node->style.flexGrow);
|
||||||
YGPrintNumberIfNotUndefinedf(node, "flex-shrink", node->style.flexShrink);
|
YGPrintNumberIfNotUndefinedf(stream, "flex-shrink", node->style.flexShrink);
|
||||||
YGPrintNumberIfNotAuto(node, "flex-basis", &node->style.flexBasis);
|
YGPrintNumberIfNotAuto(stream, "flex-basis", &node->style.flexBasis);
|
||||||
YGPrintNumberIfNotUndefinedf(node, "flex", node->style.flex);
|
YGPrintNumberIfNotUndefinedf(stream, "flex", node->style.flex);
|
||||||
|
|
||||||
if (node->style.flexWrap != gYGNodeDefaults.style.flexWrap) {
|
if (node->style.flexWrap != gYGNodeDefaults.style.flexWrap) {
|
||||||
YGLog(node, YGLogLevelDebug, "flexWrap: %s; ", YGWrapToString(node->style.flexWrap));
|
YGWriteToStringStream(stream, "flexWrap: %s; ", YGWrapToString(node->style.flexWrap));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->style.overflow != gYGNodeDefaults.style.overflow) {
|
if (node->style.overflow != gYGNodeDefaults.style.overflow) {
|
||||||
YGLog(node, YGLogLevelDebug, "overflow: %s; ", YGOverflowToString(node->style.overflow));
|
YGWriteToStringStream(stream, "overflow: %s; ", YGOverflowToString(node->style.overflow));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->style.display != gYGNodeDefaults.style.display) {
|
if (node->style.display != gYGNodeDefaults.style.display) {
|
||||||
YGLog(node, YGLogLevelDebug, "display: %s; ", YGDisplayToString(node->style.display));
|
YGWriteToStringStream(stream, "display: %s; ", YGDisplayToString(node->style.display));
|
||||||
}
|
}
|
||||||
|
|
||||||
YGPrintEdges(node, "margin", node->style.margin);
|
YGPrintEdges(stream, "margin", node->style.margin);
|
||||||
YGPrintEdges(node, "padding", node->style.padding);
|
YGPrintEdges(stream, "padding", node->style.padding);
|
||||||
YGPrintEdges(node, "border", node->style.border);
|
YGPrintEdges(stream, "border", node->style.border);
|
||||||
|
|
||||||
YGPrintNumberIfNotAuto(node, "width", &node->style.dimensions[YGDimensionWidth]);
|
YGPrintNumberIfNotAuto(stream, "width", &node->style.dimensions[YGDimensionWidth]);
|
||||||
YGPrintNumberIfNotAuto(node, "height", &node->style.dimensions[YGDimensionHeight]);
|
YGPrintNumberIfNotAuto(stream, "height", &node->style.dimensions[YGDimensionHeight]);
|
||||||
YGPrintNumberIfNotAuto(node, "max-width", &node->style.maxDimensions[YGDimensionWidth]);
|
YGPrintNumberIfNotAuto(stream, "max-width", &node->style.maxDimensions[YGDimensionWidth]);
|
||||||
YGPrintNumberIfNotAuto(node, "max-height", &node->style.maxDimensions[YGDimensionHeight]);
|
YGPrintNumberIfNotAuto(stream, "max-height", &node->style.maxDimensions[YGDimensionHeight]);
|
||||||
YGPrintNumberIfNotAuto(node, "min-width", &node->style.minDimensions[YGDimensionWidth]);
|
YGPrintNumberIfNotAuto(stream, "min-width", &node->style.minDimensions[YGDimensionWidth]);
|
||||||
YGPrintNumberIfNotAuto(node, "min-height", &node->style.minDimensions[YGDimensionHeight]);
|
YGPrintNumberIfNotAuto(stream, "min-height", &node->style.minDimensions[YGDimensionHeight]);
|
||||||
|
|
||||||
if (node->style.positionType != gYGNodeDefaults.style.positionType) {
|
if (node->style.positionType != gYGNodeDefaults.style.positionType) {
|
||||||
YGLog(node,
|
YGWriteToStringStream(stream,
|
||||||
YGLogLevelDebug,
|
"position: %s; ",
|
||||||
"position: %s; ",
|
YGPositionTypeToString(node->style.positionType));
|
||||||
YGPositionTypeToString(node->style.positionType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
YGPrintEdgeIfNotUndefined(node, "left", node->style.position, YGEdgeLeft);
|
YGPrintEdgeIfNotUndefined(stream, "left", node->style.position, YGEdgeLeft);
|
||||||
YGPrintEdgeIfNotUndefined(node, "right", node->style.position, YGEdgeRight);
|
YGPrintEdgeIfNotUndefined(stream, "right", node->style.position, YGEdgeRight);
|
||||||
YGPrintEdgeIfNotUndefined(node, "top", node->style.position, YGEdgeTop);
|
YGPrintEdgeIfNotUndefined(stream, "top", node->style.position, YGEdgeTop);
|
||||||
YGPrintEdgeIfNotUndefined(node, "bottom", node->style.position, YGEdgeBottom);
|
YGPrintEdgeIfNotUndefined(stream, "bottom", node->style.position, YGEdgeBottom);
|
||||||
YGLog(node, YGLogLevelDebug, "\" ");
|
YGWriteToStringStream(stream, "\" ");
|
||||||
|
|
||||||
if (node->measure != NULL) {
|
if (node->measure != NULL) {
|
||||||
YGLog(node, YGLogLevelDebug, "has-custom-measure=\"true\"");
|
YGWriteToStringStream(stream, "has-custom-measure=\"true\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
YGLog(node, YGLogLevelDebug, ">");
|
YGWriteToStringStream(stream, ">");
|
||||||
|
|
||||||
const uint32_t childCount = YGNodeListCount(node->children);
|
const uint32_t childCount = YGNodeListCount(node->children);
|
||||||
if (options & YGPrintOptionsChildren && childCount > 0) {
|
if (options & YGPrintOptionsChildren && childCount > 0) {
|
||||||
for (uint32_t i = 0; i < childCount; i++) {
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
YGLog(node, YGLogLevelDebug, "\n");
|
YGWriteToStringStream(stream, "\n");
|
||||||
YGNodePrintInternal(YGNodeGetChild(node, i), options, level + 1);
|
YGNodeToString(stream, YGNodeGetChild(node, i), options, level + 1);
|
||||||
}
|
}
|
||||||
YGIndent(node, level);
|
YGWriteToStringStream(stream, "\n");
|
||||||
YGLog(node, YGLogLevelDebug, "\n");
|
YGIndent(stream, level);
|
||||||
|
}
|
||||||
|
YGWriteToStringStream(stream, "</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void YGNodePrintInternal(const YGNodeRef node,
|
||||||
|
const YGPrintOptions options) {
|
||||||
|
YGStringStream stream;
|
||||||
|
stream.str = (char *) malloc(sizeof(char) * 1024);
|
||||||
|
stream.length = 0;
|
||||||
|
stream.capacity = 1024;
|
||||||
|
if (stream.str != NULL) {
|
||||||
|
YGNodeToString(&stream, node, options, 0);
|
||||||
|
YGLog(node, YGLogLevelDebug, stream.str);
|
||||||
|
free(stream.str);
|
||||||
}
|
}
|
||||||
YGLog(node, YGLogLevelDebug, "</div>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void YGNodePrint(const YGNodeRef node, const YGPrintOptions options) {
|
void YGNodePrint(const YGNodeRef node, const YGPrintOptions options) {
|
||||||
YGNodePrintInternal(node, options, 0);
|
YGNodePrintInternal(node, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const YGEdge leading[4] = {
|
static const YGEdge leading[4] = {
|
||||||
@@ -1513,31 +1664,42 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
||||||
|
if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) {
|
||||||
|
childHeight = (childWidth - marginRow) / child->style.aspectRatio;
|
||||||
|
childHeightMeasureMode = YGMeasureModeExactly;
|
||||||
|
} else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) {
|
||||||
|
childWidth = (childHeight - marginColumn) * child->style.aspectRatio;
|
||||||
|
childWidthMeasureMode = YGMeasureModeExactly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If child has no defined size in the cross axis and is set to stretch,
|
// If child has no defined size in the cross axis and is set to stretch,
|
||||||
// set the cross
|
// set the cross
|
||||||
// axis to be measured exactly with the available inner width
|
// axis to be measured exactly with the available inner width
|
||||||
if (!isMainAxisRow && !YGFloatIsUndefined(width) && !isRowStyleDimDefined &&
|
|
||||||
widthMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) {
|
const bool hasExactWidth = !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly;
|
||||||
|
const bool childWidthStretch = YGNodeAlignItem(node, child) == YGAlignStretch &&
|
||||||
|
childWidthMeasureMode != YGMeasureModeExactly;
|
||||||
|
if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && childWidthStretch) {
|
||||||
childWidth = width;
|
childWidth = width;
|
||||||
childWidthMeasureMode = YGMeasureModeExactly;
|
childWidthMeasureMode = YGMeasureModeExactly;
|
||||||
}
|
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
||||||
if (isMainAxisRow && !YGFloatIsUndefined(height) && !isColumnStyleDimDefined &&
|
childHeight = (childWidth - marginRow) / child->style.aspectRatio;
|
||||||
heightMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) {
|
childHeightMeasureMode = YGMeasureModeExactly;
|
||||||
childHeight = height;
|
}
|
||||||
childHeightMeasureMode = YGMeasureModeExactly;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
const bool hasExactHeight = !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly;
|
||||||
if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) {
|
const bool childHeightStretch = YGNodeAlignItem(node, child) == YGAlignStretch &&
|
||||||
child->layout.computedFlexBasis =
|
childHeightMeasureMode != YGMeasureModeExactly;
|
||||||
fmaxf((childWidth - marginRow) / child->style.aspectRatio,
|
if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && childHeightStretch) {
|
||||||
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, parentWidth));
|
childHeight = height;
|
||||||
return;
|
childHeightMeasureMode = YGMeasureModeExactly;
|
||||||
} else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) {
|
|
||||||
child->layout.computedFlexBasis =
|
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
||||||
fmaxf((childHeight - marginColumn) * child->style.aspectRatio,
|
childWidth = (childHeight - marginColumn) * child->style.aspectRatio;
|
||||||
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, parentWidth));
|
childWidthMeasureMode = YGMeasureModeExactly;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1630,13 +1792,9 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
|||||||
if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) {
|
if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) {
|
||||||
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
if (!YGFloatIsUndefined(child->style.aspectRatio)) {
|
||||||
if (YGFloatIsUndefined(childWidth)) {
|
if (YGFloatIsUndefined(childWidth)) {
|
||||||
childWidth =
|
childWidth = marginRow + (childHeight - marginColumn) * child->style.aspectRatio;
|
||||||
marginRow + fmaxf((childHeight - marginColumn) * child->style.aspectRatio,
|
|
||||||
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, width));
|
|
||||||
} else if (YGFloatIsUndefined(childHeight)) {
|
} else if (YGFloatIsUndefined(childHeight)) {
|
||||||
childHeight =
|
childHeight = marginColumn + (childWidth - marginRow) / child->style.aspectRatio;
|
||||||
marginColumn + fmaxf((childWidth - marginRow) / child->style.aspectRatio,
|
|
||||||
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, width));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1687,11 +1845,11 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
|||||||
config);
|
config);
|
||||||
|
|
||||||
if (YGNodeIsTrailingPosDefined(child, mainAxis) && !YGNodeIsLeadingPosDefined(child, mainAxis)) {
|
if (YGNodeIsTrailingPosDefined(child, mainAxis) && !YGNodeIsLeadingPosDefined(child, mainAxis)) {
|
||||||
child->layout.position[leading[mainAxis]] = node->layout.measuredDimensions[dim[mainAxis]] -
|
child->layout.position[leading[mainAxis]] =
|
||||||
child->layout.measuredDimensions[dim[mainAxis]] -
|
node->layout.measuredDimensions[dim[mainAxis]] -
|
||||||
YGNodeTrailingBorder(node, mainAxis) -
|
child->layout.measuredDimensions[dim[mainAxis]] - YGNodeTrailingBorder(node, mainAxis) -
|
||||||
YGNodeTrailingMargin(child, mainAxis, width) -
|
YGNodeTrailingMargin(child, mainAxis, width) -
|
||||||
YGNodeTrailingPosition(child, mainAxis, isMainAxisRow ? width : height);
|
YGNodeTrailingPosition(child, mainAxis, isMainAxisRow ? width : height);
|
||||||
} else if (!YGNodeIsLeadingPosDefined(child, mainAxis) &&
|
} else if (!YGNodeIsLeadingPosDefined(child, mainAxis) &&
|
||||||
node->style.justifyContent == YGJustifyCenter) {
|
node->style.justifyContent == YGJustifyCenter) {
|
||||||
child->layout.position[leading[mainAxis]] = (node->layout.measuredDimensions[dim[mainAxis]] -
|
child->layout.position[leading[mainAxis]] = (node->layout.measuredDimensions[dim[mainAxis]] -
|
||||||
@@ -1705,11 +1863,11 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
|||||||
|
|
||||||
if (YGNodeIsTrailingPosDefined(child, crossAxis) &&
|
if (YGNodeIsTrailingPosDefined(child, crossAxis) &&
|
||||||
!YGNodeIsLeadingPosDefined(child, crossAxis)) {
|
!YGNodeIsLeadingPosDefined(child, crossAxis)) {
|
||||||
child->layout.position[leading[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] -
|
child->layout.position[leading[crossAxis]] =
|
||||||
child->layout.measuredDimensions[dim[crossAxis]] -
|
node->layout.measuredDimensions[dim[crossAxis]] -
|
||||||
YGNodeTrailingBorder(node, crossAxis) -
|
child->layout.measuredDimensions[dim[crossAxis]] - YGNodeTrailingBorder(node, crossAxis) -
|
||||||
YGNodeTrailingMargin(child, crossAxis, width) -
|
YGNodeTrailingMargin(child, crossAxis, width) -
|
||||||
YGNodeTrailingPosition(child, crossAxis, isMainAxisRow ? height : width);
|
YGNodeTrailingPosition(child, crossAxis, isMainAxisRow ? height : width);
|
||||||
} else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
|
} else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
|
||||||
YGNodeAlignItem(node, child) == YGAlignCenter) {
|
YGNodeAlignItem(node, child) == YGAlignCenter) {
|
||||||
child->layout.position[leading[crossAxis]] =
|
child->layout.position[leading[crossAxis]] =
|
||||||
@@ -1717,7 +1875,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
|||||||
child->layout.measuredDimensions[dim[crossAxis]]) /
|
child->layout.measuredDimensions[dim[crossAxis]]) /
|
||||||
2.0f;
|
2.0f;
|
||||||
} else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
|
} else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
|
||||||
((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^ (node->style.flexWrap == YGWrapWrapReverse))) {
|
((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^
|
||||||
|
(node->style.flexWrap == YGWrapWrapReverse))) {
|
||||||
child->layout.position[leading[crossAxis]] = (node->layout.measuredDimensions[dim[crossAxis]] -
|
child->layout.position[leading[crossAxis]] = (node->layout.measuredDimensions[dim[crossAxis]] -
|
||||||
child->layout.measuredDimensions[dim[crossAxis]]);
|
child->layout.measuredDimensions[dim[crossAxis]]);
|
||||||
}
|
}
|
||||||
@@ -1741,11 +1900,12 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node,
|
|||||||
|
|
||||||
// We want to make sure we don't call measure with negative size
|
// We want to make sure we don't call measure with negative size
|
||||||
const float innerWidth = YGFloatIsUndefined(availableWidth)
|
const float innerWidth = YGFloatIsUndefined(availableWidth)
|
||||||
? availableWidth
|
? availableWidth
|
||||||
: fmaxf(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);
|
: fmaxf(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);
|
||||||
const float innerHeight = YGFloatIsUndefined(availableHeight)
|
const float innerHeight =
|
||||||
? availableHeight
|
YGFloatIsUndefined(availableHeight)
|
||||||
: fmaxf(0, availableHeight - marginAxisColumn - paddingAndBorderAxisColumn);
|
? availableHeight
|
||||||
|
: fmaxf(0, availableHeight - marginAxisColumn - paddingAndBorderAxisColumn);
|
||||||
|
|
||||||
if (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly) {
|
if (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly) {
|
||||||
// Don't bother sizing the text if both dimensions are already defined.
|
// Don't bother sizing the text if both dimensions are already defined.
|
||||||
@@ -1855,19 +2015,9 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
|
static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
|
||||||
node->layout.dimensions[YGDimensionHeight] = 0;
|
memset(&(node->layout), 0, sizeof(YGLayout));
|
||||||
node->layout.dimensions[YGDimensionWidth] = 0;
|
|
||||||
node->layout.position[YGEdgeTop] = 0;
|
|
||||||
node->layout.position[YGEdgeBottom] = 0;
|
|
||||||
node->layout.position[YGEdgeLeft] = 0;
|
|
||||||
node->layout.position[YGEdgeRight] = 0;
|
|
||||||
node->layout.cachedLayout.availableHeight = 0;
|
|
||||||
node->layout.cachedLayout.availableWidth = 0;
|
|
||||||
node->layout.cachedLayout.heightMeasureMode = YGMeasureModeExactly;
|
|
||||||
node->layout.cachedLayout.widthMeasureMode = YGMeasureModeExactly;
|
|
||||||
node->layout.cachedLayout.computedWidth = 0;
|
|
||||||
node->layout.cachedLayout.computedHeight = 0;
|
|
||||||
node->hasNewLayout = true;
|
node->hasNewLayout = true;
|
||||||
|
YGCloneChildrenIfNeeded(node);
|
||||||
const uint32_t childCount = YGNodeGetChildCount(node);
|
const uint32_t childCount = YGNodeGetChildCount(node);
|
||||||
for (uint32_t i = 0; i < childCount; i++) {
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
const YGNodeRef child = YGNodeListGet(node->children, i);
|
const YGNodeRef child = YGNodeListGet(node->children, i);
|
||||||
@@ -2041,6 +2191,9 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point we know we're going to perform work. Ensure that each child has a mutable copy.
|
||||||
|
YGCloneChildrenIfNeeded(node);
|
||||||
|
|
||||||
// Reset layout flags, as they could have changed.
|
// Reset layout flags, as they could have changed.
|
||||||
node->layout.hadOverflow = false;
|
node->layout.hadOverflow = false;
|
||||||
|
|
||||||
@@ -2243,7 +2396,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
const float childMarginMainAxis = YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
|
const float childMarginMainAxis = YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
|
||||||
const float flexBasisWithMaxConstraints =
|
const float flexBasisWithMaxConstraints =
|
||||||
fminf(YGResolveValue(&child->style.maxDimensions[dim[mainAxis]], mainAxisParentSize),
|
fminf(YGResolveValue(&child->style.maxDimensions[dim[mainAxis]], mainAxisParentSize),
|
||||||
child->layout.computedFlexBasis);
|
child->layout.computedFlexBasis);
|
||||||
const float flexBasisWithMinAndMaxConstraints =
|
const float flexBasisWithMinAndMaxConstraints =
|
||||||
fmaxf(YGResolveValue(&child->style.minDimensions[dim[mainAxis]], mainAxisParentSize),
|
fmaxf(YGResolveValue(&child->style.minDimensions[dim[mainAxis]], mainAxisParentSize),
|
||||||
flexBasisWithMaxConstraints);
|
flexBasisWithMaxConstraints);
|
||||||
@@ -2497,11 +2650,21 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
YGMeasureMode childCrossMeasureMode;
|
YGMeasureMode childCrossMeasureMode;
|
||||||
YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
|
YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
|
||||||
|
|
||||||
if (!YGFloatIsUndefined(availableInnerCrossDim) &&
|
if (!YGFloatIsUndefined(currentRelativeChild->style.aspectRatio)) {
|
||||||
!YGNodeIsStyleDimDefined(currentRelativeChild, crossAxis, availableInnerCrossDim) &&
|
childCrossSize =
|
||||||
measureModeCrossDim == YGMeasureModeExactly &&
|
isMainAxisRow
|
||||||
!(isNodeFlexWrap && flexBasisOverflows) &&
|
? (childMainSize - marginMain) / currentRelativeChild->style.aspectRatio
|
||||||
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) {
|
: (childMainSize - marginMain) * currentRelativeChild->style.aspectRatio;
|
||||||
|
childCrossMeasureMode = YGMeasureModeExactly;
|
||||||
|
|
||||||
|
childCrossSize += marginCross;
|
||||||
|
} else if (!YGFloatIsUndefined(availableInnerCrossDim) &&
|
||||||
|
!YGNodeIsStyleDimDefined(currentRelativeChild,
|
||||||
|
crossAxis,
|
||||||
|
availableInnerCrossDim) &&
|
||||||
|
measureModeCrossDim == YGMeasureModeExactly &&
|
||||||
|
!(isNodeFlexWrap && flexBasisOverflows) &&
|
||||||
|
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) {
|
||||||
childCrossSize = availableInnerCrossDim;
|
childCrossSize = availableInnerCrossDim;
|
||||||
childCrossMeasureMode = YGMeasureModeExactly;
|
childCrossMeasureMode = YGMeasureModeExactly;
|
||||||
} else if (!YGNodeIsStyleDimDefined(currentRelativeChild,
|
} else if (!YGNodeIsStyleDimDefined(currentRelativeChild,
|
||||||
@@ -2522,26 +2685,6 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
: YGMeasureModeExactly;
|
: YGMeasureModeExactly;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!YGFloatIsUndefined(currentRelativeChild->style.aspectRatio)) {
|
|
||||||
childCrossSize = fmaxf(
|
|
||||||
isMainAxisRow
|
|
||||||
? (childMainSize - marginMain) / currentRelativeChild->style.aspectRatio
|
|
||||||
: (childMainSize - marginMain) * currentRelativeChild->style.aspectRatio,
|
|
||||||
YGNodePaddingAndBorderForAxis(currentRelativeChild, crossAxis, availableInnerWidth));
|
|
||||||
childCrossMeasureMode = YGMeasureModeExactly;
|
|
||||||
|
|
||||||
// Parent size constraint should have higher priority than flex
|
|
||||||
if (YGNodeIsFlex(currentRelativeChild)) {
|
|
||||||
childCrossSize = fminf(childCrossSize - marginCross, availableInnerCrossDim);
|
|
||||||
childMainSize =
|
|
||||||
marginMain + (isMainAxisRow
|
|
||||||
? childCrossSize * currentRelativeChild->style.aspectRatio
|
|
||||||
: childCrossSize / currentRelativeChild->style.aspectRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
childCrossSize += marginCross;
|
|
||||||
}
|
|
||||||
|
|
||||||
YGConstrainMaxSizeForMode(currentRelativeChild,
|
YGConstrainMaxSizeForMode(currentRelativeChild,
|
||||||
mainAxis,
|
mainAxis,
|
||||||
availableInnerMainDim,
|
availableInnerMainDim,
|
||||||
@@ -2749,12 +2892,15 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
// top/left/bottom/right
|
// top/left/bottom/right
|
||||||
// set, override all the previously computed positions to set it
|
// set, override all the previously computed positions to set it
|
||||||
// correctly.
|
// correctly.
|
||||||
if (YGNodeIsLeadingPosDefined(child, crossAxis)) {
|
const bool isChildLeadingPosDefined = YGNodeIsLeadingPosDefined(child, crossAxis);
|
||||||
|
if (isChildLeadingPosDefined) {
|
||||||
child->layout.position[pos[crossAxis]] =
|
child->layout.position[pos[crossAxis]] =
|
||||||
YGNodeLeadingPosition(child, crossAxis, availableInnerCrossDim) +
|
YGNodeLeadingPosition(child, crossAxis, availableInnerCrossDim) +
|
||||||
YGNodeLeadingBorder(node, crossAxis) +
|
YGNodeLeadingBorder(node, crossAxis) +
|
||||||
YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
|
YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
|
||||||
} else {
|
}
|
||||||
|
// If leading position is not defined or calculations result in Nan, default to border + margin
|
||||||
|
if (!isChildLeadingPosDefined || YGFloatIsUndefined(child->layout.position[pos[crossAxis]])) {
|
||||||
child->layout.position[pos[crossAxis]] =
|
child->layout.position[pos[crossAxis]] =
|
||||||
YGNodeLeadingBorder(node, crossAxis) +
|
YGNodeLeadingBorder(node, crossAxis) +
|
||||||
YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
|
YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
|
||||||
@@ -3158,21 +3304,25 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM
|
|||||||
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static float YGRoundValueToPixelGrid(const float value,
|
float YGRoundValueToPixelGrid(const float value,
|
||||||
const float pointScaleFactor,
|
const float pointScaleFactor,
|
||||||
const bool forceCeil,
|
const bool forceCeil,
|
||||||
const bool forceFloor) {
|
const bool forceFloor) {
|
||||||
float scaledValue = value * pointScaleFactor;
|
float scaledValue = value * pointScaleFactor;
|
||||||
float fractial = fmodf(scaledValue, 1.0);
|
float fractial = fmodf(scaledValue, 1.0);
|
||||||
if (YGFloatsEqual(fractial, 0)) {
|
if (YGFloatsEqual(fractial, 0)) {
|
||||||
// Still remove fractial as fractial could be extremely small.
|
// First we check if the value is already rounded
|
||||||
scaledValue = scaledValue - fractial;
|
scaledValue = scaledValue - fractial;
|
||||||
} else if (forceCeil) {
|
} else if (YGFloatsEqual(fractial, 1.0)) {
|
||||||
scaledValue = scaledValue - fractial + 1.0;
|
scaledValue = scaledValue - fractial + 1.0;
|
||||||
|
} else if (forceCeil) {
|
||||||
|
// Next we check if we need to use forced rounding
|
||||||
|
scaledValue = scaledValue - fractial + 1.0f;
|
||||||
} else if (forceFloor) {
|
} else if (forceFloor) {
|
||||||
scaledValue = scaledValue - fractial;
|
scaledValue = scaledValue - fractial;
|
||||||
} else {
|
} else {
|
||||||
scaledValue = scaledValue - fractial + (fractial >= 0.5f ? 1.0 : 0);
|
// Finally we just round the value
|
||||||
|
scaledValue = scaledValue - fractial + (fractial >= 0.5f ? 1.0f : 0.0f);
|
||||||
}
|
}
|
||||||
return scaledValue / pointScaleFactor;
|
return scaledValue / pointScaleFactor;
|
||||||
}
|
}
|
||||||
@@ -3194,13 +3344,25 @@ bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool useRoundedComparison = config != NULL && config->pointScaleFactor != 0;
|
bool useRoundedComparison = config != NULL && config->pointScaleFactor != 0;
|
||||||
const float effectiveWidth = useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) : width;
|
const float effectiveWidth =
|
||||||
const float effectiveHeight = useRoundedComparison ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false) : height;
|
useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false)
|
||||||
const float effectiveLastWidth = useRoundedComparison ? YGRoundValueToPixelGrid(lastWidth, config->pointScaleFactor, false, false) : lastWidth;
|
: width;
|
||||||
const float effectiveLastHeight = useRoundedComparison ? YGRoundValueToPixelGrid(lastHeight, config->pointScaleFactor, false, false) : lastHeight;
|
const float effectiveHeight =
|
||||||
|
useRoundedComparison ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false)
|
||||||
|
: height;
|
||||||
|
const float effectiveLastWidth =
|
||||||
|
useRoundedComparison
|
||||||
|
? YGRoundValueToPixelGrid(lastWidth, config->pointScaleFactor, false, false)
|
||||||
|
: lastWidth;
|
||||||
|
const float effectiveLastHeight =
|
||||||
|
useRoundedComparison
|
||||||
|
? YGRoundValueToPixelGrid(lastHeight, config->pointScaleFactor, false, false)
|
||||||
|
: lastHeight;
|
||||||
|
|
||||||
const bool hasSameWidthSpec = lastWidthMode == widthMode && YGFloatsEqual(effectiveLastWidth, effectiveWidth);
|
const bool hasSameWidthSpec =
|
||||||
const bool hasSameHeightSpec = lastHeightMode == heightMode && YGFloatsEqual(effectiveLastHeight, effectiveHeight);
|
lastWidthMode == widthMode && YGFloatsEqual(effectiveLastWidth, effectiveWidth);
|
||||||
|
const bool hasSameHeightSpec =
|
||||||
|
lastHeightMode == heightMode && YGFloatsEqual(effectiveLastHeight, effectiveHeight);
|
||||||
|
|
||||||
const bool widthIsCompatible =
|
const bool widthIsCompatible =
|
||||||
hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode,
|
hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode,
|
||||||
@@ -3474,7 +3636,8 @@ static void YGRoundToPixelGrid(const YGNodeRef node,
|
|||||||
node->layout.position[YGEdgeTop] =
|
node->layout.position[YGEdgeTop] =
|
||||||
YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding);
|
YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding);
|
||||||
|
|
||||||
// We multiply dimension by scale factor and if the result is close to the whole number, we don't have any fraction
|
// We multiply dimension by scale factor and if the result is close to the whole number, we don't
|
||||||
|
// have any fraction
|
||||||
// To verify if the result is close to whole number we want to check both floor and ceil numbers
|
// To verify if the result is close to whole number we want to check both floor and ceil numbers
|
||||||
const bool hasFractionalWidth = !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) &&
|
const bool hasFractionalWidth = !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) &&
|
||||||
!YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0);
|
!YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0);
|
||||||
@@ -3482,18 +3645,16 @@ static void YGRoundToPixelGrid(const YGNodeRef node,
|
|||||||
!YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0);
|
!YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0);
|
||||||
|
|
||||||
node->layout.dimensions[YGDimensionWidth] =
|
node->layout.dimensions[YGDimensionWidth] =
|
||||||
YGRoundValueToPixelGrid(
|
YGRoundValueToPixelGrid(absoluteNodeRight,
|
||||||
absoluteNodeRight,
|
pointScaleFactor,
|
||||||
pointScaleFactor,
|
(textRounding && hasFractionalWidth),
|
||||||
(textRounding && hasFractionalWidth),
|
(textRounding && !hasFractionalWidth)) -
|
||||||
(textRounding && !hasFractionalWidth)) -
|
|
||||||
YGRoundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor, false, textRounding);
|
YGRoundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor, false, textRounding);
|
||||||
node->layout.dimensions[YGDimensionHeight] =
|
node->layout.dimensions[YGDimensionHeight] =
|
||||||
YGRoundValueToPixelGrid(
|
YGRoundValueToPixelGrid(absoluteNodeBottom,
|
||||||
absoluteNodeBottom,
|
pointScaleFactor,
|
||||||
pointScaleFactor,
|
(textRounding && hasFractionalHeight),
|
||||||
(textRounding && hasFractionalHeight),
|
(textRounding && !hasFractionalHeight)) -
|
||||||
(textRounding && !hasFractionalHeight)) -
|
|
||||||
YGRoundValueToPixelGrid(absoluteNodeTop, pointScaleFactor, false, textRounding);
|
YGRoundValueToPixelGrid(absoluteNodeTop, pointScaleFactor, false, textRounding);
|
||||||
|
|
||||||
const uint32_t childCount = YGNodeListCount(node->children);
|
const uint32_t childCount = YGNodeListCount(node->children);
|
||||||
@@ -3652,6 +3813,10 @@ void *YGConfigGetContext(const YGConfigRef config) {
|
|||||||
return config->context;
|
return config->context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void YGConfigSetNodeClonedFunc(const YGConfigRef config, const YGNodeClonedFunc callback) {
|
||||||
|
config->cloneNodeCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree) {
|
void YGSetMemoryFuncs(YGMalloc ygmalloc, YGCalloc yccalloc, YGRealloc ygrealloc, YGFree ygfree) {
|
||||||
YGAssert(gNodeInstanceCount == 0 && gConfigInstanceCount == 0,
|
YGAssert(gNodeInstanceCount == 0 && gConfigInstanceCount == 0,
|
||||||
"Cannot set memory functions: all node must be freed first");
|
"Cannot set memory functions: all node must be freed first");
|
||||||
|
11
yoga/Yoga.h
11
yoga/Yoga.h
@@ -60,6 +60,10 @@ typedef int (*YGLogger)(const YGConfigRef config,
|
|||||||
YGLogLevel level,
|
YGLogLevel level,
|
||||||
const char *format,
|
const char *format,
|
||||||
va_list args);
|
va_list args);
|
||||||
|
typedef void (*YGNodeClonedFunc)(YGNodeRef oldNode,
|
||||||
|
YGNodeRef newNode,
|
||||||
|
YGNodeRef parent,
|
||||||
|
int childIndex);
|
||||||
|
|
||||||
typedef void *(*YGMalloc)(size_t size);
|
typedef void *(*YGMalloc)(size_t size);
|
||||||
typedef void *(*YGCalloc)(size_t count, size_t size);
|
typedef void *(*YGCalloc)(size_t count, size_t size);
|
||||||
@@ -69,6 +73,7 @@ typedef void (*YGFree)(void *ptr);
|
|||||||
// YGNode
|
// YGNode
|
||||||
WIN_EXPORT YGNodeRef YGNodeNew(void);
|
WIN_EXPORT YGNodeRef YGNodeNew(void);
|
||||||
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config);
|
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config);
|
||||||
|
WIN_EXPORT YGNodeRef YGNodeClone(const YGNodeRef node);
|
||||||
WIN_EXPORT void YGNodeFree(const YGNodeRef node);
|
WIN_EXPORT void YGNodeFree(const YGNodeRef node);
|
||||||
WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node);
|
WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node);
|
||||||
WIN_EXPORT void YGNodeReset(const YGNodeRef node);
|
WIN_EXPORT void YGNodeReset(const YGNodeRef node);
|
||||||
@@ -78,6 +83,7 @@ WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node,
|
|||||||
const YGNodeRef child,
|
const YGNodeRef child,
|
||||||
const uint32_t index);
|
const uint32_t index);
|
||||||
WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child);
|
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 YGNodeGetChild(const YGNodeRef node, const uint32_t index);
|
||||||
WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node);
|
WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node);
|
||||||
WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node);
|
WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node);
|
||||||
@@ -112,7 +118,7 @@ WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
|
|||||||
const float lastComputedHeight,
|
const float lastComputedHeight,
|
||||||
const float marginRow,
|
const float marginRow,
|
||||||
const float marginColumn,
|
const float marginColumn,
|
||||||
YGConfigRef config);
|
const YGConfigRef config);
|
||||||
|
|
||||||
WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode);
|
WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode);
|
||||||
|
|
||||||
@@ -264,6 +270,9 @@ WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
|
|||||||
WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);
|
WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);
|
||||||
WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);
|
WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);
|
||||||
|
|
||||||
|
WIN_EXPORT void YGConfigSetNodeClonedFunc(const YGConfigRef config,
|
||||||
|
const YGNodeClonedFunc callback);
|
||||||
|
|
||||||
// Export only for C#
|
// Export only for C#
|
||||||
WIN_EXPORT YGConfigRef YGConfigGetDefault(void);
|
WIN_EXPORT YGConfigRef YGConfigGetDefault(void);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user