Compare commits

...

51 Commits

Author SHA1 Message Date
Lukas Wöhrl
999bd723d8 fix margin auto lead to negativ positioning 2020-06-09 13:01:50 +02:00
Steven Koeber
ede65bbce4 Buckification of Yoga build script
Reviewed By: liorisraeli87, k21

Differential Revision: D21429174

fbshipit-source-id: f12c8349cc59398553773df7bc15f0f83bd571b4
2020-06-04 06:54:18 -07:00
Jon Janzen
4135420cba Fix GitHub Actions secrets access (#1005)
Summary:
Ref: [Secrets documentation](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#using-encrypted-secrets-in-a-workflow)

In combination with setting the secrets in the GitHub settings, this should fully migrate yoga to GH actions.

Pull Request resolved: https://github.com/facebook/yoga/pull/1005

Test Plan: GitHub Actions CI on the PR attached to this diff

Reviewed By: SidharthGuglani

Differential Revision: D21574995

Pulled By: bigfootjon

fbshipit-source-id: e9ee6d7cf1ae131afdc3aa3778667f1e9b9de833
2020-05-14 12:21:28 -07:00
Sidharth Guglani
07c0d539bd throw std::logic_error instead of aborting the process and convert to java exception
Summary: Changelog: [Internal][Yoga] throw std::logic_error instead of aborting the process and convert to java exception for jni layer

Reviewed By: pasqualeanatriello

Differential Revision: D21301235

fbshipit-source-id: 148b27920e62990a271e1d0df8c85a2cc42f4fd4
2020-05-14 06:39:25 -07:00
Jon Janzen
ac7c85c0a6 Migrate CI from TravisCI to GitHub Actions (#1004)
Summary:
Migrate from TravisCI to GitHub Actions. Facebook employees can read about this migration [here](https://fburl.com/rfp033ou).

CC: wittgenst
Pull Request resolved: https://github.com/facebook/yoga/pull/1004

Test Plan: GitHub Actions CI on my personal GitHub: https://github.com/bigfootjon/yoga/runs/653755729

Reviewed By: passy

Differential Revision: D21431309

Pulled By: bigfootjon

fbshipit-source-id: 490a8679bc0cfec26b13c8c584a928f03c6e26e7
2020-05-12 12:01:53 -07:00
Sidharth Guglani
83b27417ae Fix rounding error using double instead of float
Summary: Changelog: [Internal] [Yoga] Use double instead of float during rounding process to prevent loss of precision.

Reviewed By: mdvacca

Differential Revision: D21227565

fbshipit-source-id: 380b57535a356624cda8dc2017871a4ef3c882d1
2020-04-27 14:48:15 -07:00
Valentin Shergin
884f147742 Fixed incorrect owner assignment in YGNode move constructor
Summary:
Assigning self as an owner makes a cycle which is obviously a bug.

Changelog: [Internal] Small change in Yoga (should not affect RN).

Reviewed By: SidharthGuglani

Differential Revision: D21111423

fbshipit-source-id: 1835561c055ac827f5ce98a044f25aed0d1845a5
2020-04-20 12:05:55 -07:00
Gavin Weng
a96a36ef59 Link yogacore statically into yoga
Summary: A revert of D20879886.

Reviewed By: iliagore

Differential Revision: D20979490

fbshipit-source-id: cb37f931654450c408e72578abcc549f35727b07
2020-04-17 17:34:17 -07:00
acton393
1bd4123df1 fix typo as there is no file called YGJNI.cpp (#990)
Summary:
fix typo in `YogaJNIBase.java` as there is no such file called `YGJNI.cpp`
Pull Request resolved: https://github.com/facebook/yoga/pull/990

Reviewed By: pasqualeanatriello

Differential Revision: D20735102

Pulled By: SidharthGuglani

fbshipit-source-id: 3f9f4d78ba390feae3451330f997a221ab4ec70e
2020-04-17 05:45:41 -07:00
Sidharth Guglani
92b76447b7 use default value of enums YGDirection and YGMeasureMode instead of -1
Summary:
Changelog:
[Internal][Yoga] YGDirection variable was initialized incorrectly by casting -1 to YGDirection. Changing it to default value of direction

Same for YGMeasureMode.

Reviewed By: pasqualeanatriello

Differential Revision: D20869042

fbshipit-source-id: 7bfe490193321baae875ef6fb49a938851950c9f
2020-04-17 05:32:05 -07:00
Sidharth Guglani
e637cf2d72 Add Yoga also as a dependency of testutil-jni
Summary:
`scripts/deploy_jcenter.sh` was failing

{F234018047}

Added `yoga` also as a dependency of `testutil-jni`

Reviewed By: gavinweng

Differential Revision: D21017796

fbshipit-source-id: 0c34e7fc2373906441bd7805f5687b2c5dab6242
2020-04-15 00:49:53 -07:00
empyrical
9b96a5362a Yoga Podspec: Export YGNode and YGStyle headers (#997)
Summary:
This pull request adds `YGNode.h` and `YGStyle.h` to the headers exported by Yoga's podspec. They are required by the new Fabric architecture of React Native.

The modulemap and its umbrella header automatically generated by Cocoapods adds all exported headers to the `modulemap`. Having YGNode and YGStyle exported through here has problems, because they are only available in environments that have C++ available, and will produce errors otherwise.

This pull request fences off the contents of those headers in an `#ifdef __cplusplus` block, so they will not cause errors when imported into environments where C++ isn't available.

I had considered adding a custom modulemap to the podspec as part of this pull request, but this way seems the least "invasive", and this way you are able to add and remove exported headers in the podspec without needing to worry about updating the umbrella header at the same time.

Changelog:

[Internal] - Yoga Podspec: Export YGNore and YGStyle headers

Pull Request resolved: https://github.com/facebook/yoga/pull/997

Reviewed By: hramos

Differential Revision: D20966075

Pulled By: mdvacca

fbshipit-source-id: 5f5caa6b639d11e660b968d681da9a4de6c0eb8e
2020-04-14 16:42:27 -07:00
Sidharth Guglani
e5743e851b Set width/height also to Undefined when we change the measure mode to Undefined
Summary:
Make sure width/height is always passed as Undefined when measure mode is changed to Undefined.

Changelog: [Internal][Yoga] Set width and height as Undefined when we change measure mode to Undefined

Reviewed By: alickbass

Differential Revision: D20029838

fbshipit-source-id: b9931f6ddb13ffd1565889535ade5bbffbe0c304
2020-04-14 02:09:29 -07:00
George Zahariev
f7bc0ad248 Upgrade Prettier in Xplat to version 1.19.1: format files
Summary:
Part two of D20879147 where we update the versions of Prettier used in Xplat. I will stack land the diffs.
Here, we format all the files, and use the drop conflicts flag. After this lands, I will go and format the files which had conflicts again.

Changelog: [Internal]

drop-conflicts
bypass-lint
allow-large-files

Reviewed By: gkz

Differential Revision: D20929844

fbshipit-source-id: 2c1df8966a48b5db4f890e2cc494cb1c69422b7d
2020-04-09 11:06:06 -07:00
George Zahariev
8c53c2dcca Upgrade Prettier in Xplat to version 1.19.1
Summary:
Upgrades Prettier in Xplat to 1.19.1
Ignores upgrading packages on already on versions greater than 1.19.1

Changelog: [Internal]

allow-large-files
bypass-lint

(Note: this ignores all push blocking failures!)

Reviewed By: gkz, cpojer

Differential Revision: D20879147

fbshipit-source-id: 0deee7ac941e91e1c3c3a1e7d3d3ed20de1d657d
2020-04-09 11:06:04 -07:00
Gavin Weng
be51bc44a4 Revert Name Change for FBLite
Summary: To unblock

Reviewed By: Arieg419

Differential Revision: D20879886

fbshipit-source-id: 428f9147e540b94dec7f72a7f844949722165a07
2020-04-06 19:53:50 -07:00
Gavin Weng
5eba2d42bd Enhance build process (#994)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/994

After building yoga aar, we found several issues:
1. More dynamic so files. This is bad as lower-end Android devices cannot load that many sos.
2. Size increase.
3. (Minor) The libs are stored in asset folder rather than "libs/".

We apply the following optimizations:
1. Remove dependency on memalign16 (this is brought in by a pure header dependency jni-hack);
2. Enable native relinker to remove unused symbols in the so files.
3. Link yogacore statically to reduce size churn.

Reviewed By: SidharthGuglani

Differential Revision: D20808623

fbshipit-source-id: 6c6bbd4f71b6bf6ad272ec05dd56696ddb14a8e0
2020-04-06 11:51:16 -07:00
Sidharth Guglani
2049c85a6c Unit tests for flexshrink min width cases
Reviewed By: pasqualeanatriello

Differential Revision: D20219428

fbshipit-source-id: 8cbd028627095d9f7b393489ddba1f31c3207b67
2020-04-01 14:56:49 -07:00
Sidharth Guglani
ecd7790dd8 Fix Yoga flexshrink with min-width sizing issue
Summary:
While resolving the flexible items we calculate totalFlexShrinkScaledFactors which uses the flexBasis or initial width of node (Not min-width).

At a later stage during distribution of space we are subtracting value from this which also takes care of min-width.

For example
If node has flexShrink 1 and width 100 and min-width 301  then totalFlexShrinkScaledFactors will become -1*100 = -100
but later we are subtracting -1 * 301 (min-width) = -301 which is ambiguous and causing layout inconsistencies with how web behaves.

Fixed this by only using the flexBasis or width for these calculations.

Changelog:
[Internal][Yoga] Fix layout issue when flexShrink and min-width are used together

Reviewed By: pasqualeanatriello

Differential Revision: D20219419

fbshipit-source-id: 948fbc06ca541d4ad307c88c8a2df65d157778b1
2020-04-01 14:56:45 -07:00
Michael Bolin
0f08aa53da Back out "Upgrade Prettier from 1.17 to 2.0.2."
Differential Revision: D20639755

fbshipit-source-id: 5028563f9cf0527a30b4259daac50cdc03934bfd
2020-03-24 21:41:08 -07:00
Michael Bolin
5bf93e81ba Upgrade Prettier from 1.17 to 2.0.2.
Summary:
This gets us on the latest Prettier 2.x:
https://prettier.io/blog/2020/03/21/2.0.0.html

Notably, this adds support for TypeScript 3.8,
which introduces new syntax, such as `import type`.

Reviewed By: zertosh

Differential Revision: D20636268

fbshipit-source-id: fca5833d003804333a05ba16325bbbe0e06d6c8a
2020-03-24 20:26:19 -07:00
Lior Israeli
4f1231f411 Fix typo in buck targets
Summary: Proguard is spelled wrong

Reviewed By: SidharthGuglani

Differential Revision: D20619173

fbshipit-source-id: 463788454ad7e72337121ed63ab79129db45113e
2020-03-24 05:37:47 -07:00
Adam Ernst
b280a19b0a Run 'arc lint-deps'
Reviewed By: d16r

Differential Revision: D20362505

fbshipit-source-id: f3b7e62f7665d20a32788042772b731d6ed53f36
2020-03-10 10:58:46 -07:00
Nate Stedman
63a463d011 Mark YogaKit as modular
Differential Revision: D20364340

fbshipit-source-id: ce4bc1f474177ffc9c77eb2f10bdb7cb549dd6d8
2020-03-10 09:38:56 -07:00
Jesse Katsumata
adb87e347f chore: fix typo in comments (#28269)
Summary:
Fixed some typos in the comment.

## Changelog

[Internal] [Fixed] - Fixed typo in the comments
Pull Request resolved: https://github.com/facebook/react-native/pull/28269

Test Plan: Changes are only made in the comments, so test is not necessary.

Reviewed By: cpojer

Differential Revision: D20342637

Pulled By: shergin

fbshipit-source-id: f6e7dd538ee54c43e1570c35e1f8c4502054e328
2020-03-09 16:03:44 -07:00
Sidharth Guglani
2d52b5a873 fix layout tab height issue in playground on home page
Summary: Fixed layout tab height issue properly

Reviewed By: danielbuechele

Differential Revision: D20003594

fbshipit-source-id: 6d9ce89a5d82a83937e5cb0f989bb028e07d576f
2020-02-25 07:34:37 -08:00
Sidharth Guglani
6c61cd5f05 Fix layout tab scrolling in playground
Summary: Add a scroll bar to layout tab in playground to fix the UI issue where margin, border were not accessible.

Reviewed By: danielbuechele

Differential Revision: D19906128

fbshipit-source-id: 2c2d7695f731b2d312b78eab31c66d737915eaae
2020-02-19 11:12:41 -08:00
Sidharth Guglani
bfc3b2f86f fix lint errors
Summary:
Changelog: [Internal][Yoga] Fixed lint errors

```arc lint --apply-patches --take CLANGFORMAT --paths-cmd 'hg files xplat/yoga'
```
Added .clang-tidy file

Reviewed By: zertosh

Differential Revision: D19948702

fbshipit-source-id: f77a16d6f2c532267597a84a9caded0aae68c3aa
2020-02-18 08:24:46 -08:00
Christoph Purrer
a1278cee05 Make YGValue.h compile with Clang on Windows
Summary:
- We use a fork of Microsoft's react-native-windows which uses a fork of Facebook's react-native
- YGValue.h does not compile with Clang on Windows
- This change should fix that
- I want to put the change here so that it bubbles back to our fork > https://our.intern.facebook.com/intern/diff/D19656093/

#Changelog:
[General][Fixed] Make YGValue.h compile with Clang on Windows

Reviewed By: SidharthGuglani

Differential Revision: D19717489

fbshipit-source-id: ad867ecaf910bb64a777a06c656a1867bb15484b
2020-02-05 13:44:21 -08:00
Pasquale Anatriello
e983c4a5ef Swap child Yoga
Summary:
Changelog: [Internal]

Expose the replaceChild Yoga call to Java

Reviewed By: SidharthGuglani

Differential Revision: D19497193

fbshipit-source-id: 153243cc1d8c23dcaf2c772ca794bd59a230f652
2020-01-30 04:32:20 -08:00
Amir Shalem
7f97e8b232 Allow redex to optimize more of yoga by removing unneeded @DoNotStrip marks
Summary:
There are multiple `DoNotStrip` in Yoga java binding, they aren't needed.

##Changelog:
[Internal][Yoga] Allow redex to optimize more of yoga by removing unneeded DoNotStrip marks

Reviewed By: SidharthGuglani

Differential Revision: D17519844

fbshipit-source-id: 8b26800d720f34cae87754d85460abf88acbe713
2019-12-04 01:34:54 -08:00
Sidharth Guglani
089095f532 create global ref properly in YogaJNIException
Summary:
##Changelog:
[Internal][Yoga] create global ref properly in YogaJNIException

Reviewed By: astreet

Differential Revision: D18775982

fbshipit-source-id: ee529d6178d40b5f887fa1327fe156fa466f154f
2019-12-03 16:02:13 -08:00
Sidharth Guglani
ac8eb111a9 Add defensive check for result returned after JNI function calls
Summary:
Added method which checks if value(methodId, fieldId, class ...) returned by JNI functions (getMethod, getField, getClass ...) is valid or not and throw exception if they are not valid

##Changelog:
[Internal][Yoga] Add defensive check for result returned after JNI calls

Reviewed By: astreet

Differential Revision: D18745718

fbshipit-source-id: 2af26eda15fbe7834e1c9b274deeed4f106274ab
2019-12-02 05:24:54 -08:00
Sidharth Guglani
073f49d0d0 Use YogaJniException in jni call exception handling
Summary:
##Changelog:
[Internal][Yoga] Use YogaJniException in jni call exception handling

Reviewed By: astreet

Differential Revision: D18745615

fbshipit-source-id: 5fcf4c31f04fade94ef98a5349782ed3d43805b0
2019-12-02 05:24:54 -08:00
Sidharth Guglani
67915b5905 Add YogaJniException class
Summary:
## Changelog:
[Internal][Yoga] Add YogaJniException class to be used later for jni exceptions

Reviewed By: astreet

Differential Revision: D18745609

fbshipit-source-id: 53503b54dbc59e9fe47f599dee6be9cb68134cb2
2019-12-02 05:24:53 -08:00
Sidharth Guglani
015df9c512 Remove bitfield.h
Summary:
##Changelog:

[Internal][Yoga] Remove Bitfield.h

Reviewed By: astreet

Differential Revision: D18519647

fbshipit-source-id: b46fe585d3ef5f1da7d2726b2d9f759a649be121
2019-11-27 14:19:47 -08:00
Sidharth Guglani
f7f134274c Remove bitfield from YGNode.h
Summary:
##Changelog:

[Internal][Yoga] remove Bitfield from YGNode.h

Reviewed By: astreet

Differential Revision: D18519633

fbshipit-source-id: b5a7d8d5ee960c5618df382900c4ded3da0587a6
2019-11-27 14:19:46 -08:00
Sergey Ryabov
aeb9549af7 Fix javadocs
Summary: Changelog: [Internal]

Reviewed By: muraziz

Differential Revision: D15538725

fbshipit-source-id: 5cf60f47b07ce355e40d5b064add1df980beed89
2019-11-22 10:25:41 -08:00
Sidharth Guglani
f3498a2959 Remove BItfield from YGLayout.h
Summary:
##Changelog:

[Internal][Yoga] Remove Bitfield from YGLayout

Reviewed By: astreet

Differential Revision: D18519623

fbshipit-source-id: 950b8cb1ca2cd0424b8d8748c4b71336b40fc15f
2019-11-22 04:51:14 -08:00
Sidharth Guglani
9d2ca758fa Remove Bitfield from YGStyle
Summary:
##Changelog:

[Internal][Yoga] Remove Bitfield from YGStyle

Reviewed By: astreet

Differential Revision: D18519614

fbshipit-source-id: 70f18bc679b62712d40d76bd793cf85906b067a1
2019-11-22 04:51:13 -08:00
Sidharth Guglani
9650c1903d converts BitfieldTests to BitUtilsTest
Summary: Use BitUtils for testing bit operations

Reviewed By: astreet

Differential Revision: D18596312

fbshipit-source-id: 83f93cd7f1f056b3f64070debbc452877b44ac7a
2019-11-22 04:51:13 -08:00
Sidharth Guglani
f4840a0148 Added BitUtils
Summary:
Adds BitUtils to be used later instead of Bitfield.h

##Changelog:
[Internal][Yoga] : Adds BitUtils to be used later instead of Bitfield.h

Reviewed By: astreet

Differential Revision: D18519609

fbshipit-source-id: 8353929543505a7d80d66281adb801d34372beed
2019-11-22 04:51:12 -08:00
Sidharth Guglani
198e99d30c Back out "not using templates for updating styles which are used via bitfield"
Reviewed By: astreet

Differential Revision: D18628090

fbshipit-source-id: 9d006534111f10ec25a0d56214792aeb96fbdef9
2019-11-22 04:51:11 -08:00
Sidharth Guglani
cd0191c247 not using templates for updating styles which are used via bitfield
Summary:
We want completely remove usages of Bitfield as it uses templates which bloats binary size
This stack will reduce 2.2 Kb in binary size bringing it down to 61.3KB on armv7

In this diff we are removing usage of template while updating styles.

## Changelog:
[Internal][Yoga] : Not using templates for updating styles

Reviewed By: astreet

Differential Revision: D18519570

fbshipit-source-id: 2324088b8c63154f818b1da1edf24c0533e10082
2019-11-15 06:39:29 -08:00
Sidharth Guglani
7ec0ef8470 add test for margin and padding percent applied on leaf nodes with measure function
Summary: Add tests for using margin and padding percent on nodes with measure function set on them

Reviewed By: alickbass

Differential Revision: D17130693

fbshipit-source-id: 9a5c963671f7649dead459969b008335f15e45ce
2019-11-15 05:13:35 -08:00
Sidharth Guglani
b88cf7ff67 use owner's width for resolving the margin and padding for node
Summary:
The margin and padding are resolved incorrectly for leaf nodes (nodes with measure function set) if margin and padding are used in percentages.
Here we were using node's width instead of container width to calculate the margin and padding.

Fixed this to use container's width.

## Changelog:

[General][Yoga] : Fixed an issue where margin and padding were resolved incorrectly for leaf nodes (nodes with measure function set) if margin and padding are used in percentages.

Reviewed By: alickbass

Differential Revision: D17130520

fbshipit-source-id: ac904d432f121973e7739debd9136909b5ca1427
2019-11-15 05:13:34 -08:00
Sidharth Guglani
20fe53b254 Add --version-script
Summary: Adds version script to exclude all exported symbols and export only JNI_onLoad

Reviewed By: Andrey-Mishanin

Differential Revision: D18076602

fbshipit-source-id: cac4ef9c800de6a3b2081a1f847fa918687896fe
2019-11-13 16:46:09 -08:00
Sidharth Guglani
f99da09716 Remove useVanillaJNI flag and usage of fbjni in yoga build
Summary:
## Changelog:

[General] [Yoga] - Use vanilla jni instead of fbjni for all the jni communication

Reviewed By: astreet

Differential Revision: D17808005

fbshipit-source-id: 5e9a1ed73978f519c71c248774a28e5a294e7c7f
2019-11-13 15:16:37 -08:00
Sidharth Guglani
5960dd888d Add test for margin top not calculated correctly if defined in percentage
Summary:
Unit tests for margin percent scenario where height was being used instead of width

## Changelog:

[Internal] [Yoga] - Added unit tests for margin percent

Reviewed By: alickbass

Differential Revision: D18448365

fbshipit-source-id: f4404b0c493938fc04dc685e97effa08bfd553b0
2019-11-13 07:25:59 -08:00
Sidharth Guglani
b0a0007d6e using width for calculating margin top percent
Summary:
In Yoga, margin is not calculated correctly when defined in terms of percentage at one place.
According to CSS docs , margin percentage should be calculated according to width of container's block in case of horizontal writing mode. (https://fburl.com/5imus0it)
We were using height of container causing some issues in both android and iOS.

## Changelog:

[Yoga] [Fixed] - margin if defined in percentage should use container's width in horizontal writing mode

Reviewed By: alickbass

Differential Revision: D18395285

fbshipit-source-id: 87ebd013e3cba36da45f6548e4dff1bce69cce9b
2019-11-13 05:29:36 -08:00
Pritesh Nandgaonkar
73a4a6d29f Fixes the Yogakit compilation bug for xcode11
Summary:
This fixes the yogakit compilation bug for xcode 11, where it fails to find swift core frameworks for pure objc project.

https://github.com/Carthage/Carthage/issues/2825
https://twitter.com/krzyzanowskim/status/1151549874653081601?s=21

Also published this podspec on cocoapods and deleted .swift-version file as it was not required, because swift version is mentioned in podspec

Reviewed By: SidharthGuglani

Differential Revision: D18420963

fbshipit-source-id: d617bf643ac6481d6add86e6a4bfadd6e0d0c229
2019-11-11 10:18:52 -08:00
101 changed files with 2231 additions and 2621 deletions

56
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: CI
on: [push, pull_request]
jobs:
website:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 8.x
- name: Install dependencies
run: yarn install --frozen-lockfile --ignore-scripts
working-directory: website
- name: Build
run: yarn build
working-directory: website
- name: Deploy
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: website/public
cname: yogalayout.com
keep_files: true
user_name: 'Yoga-bot'
user_email: 'yogabot@fb.com'
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: |
if [[ -n "${{ secrets.encrypted_d27e803291ff_iv }}" ]]; then
openssl aes-256-cbc -K ${{ secrets.encrypted_d27e803291ff_key }} -iv {{ secrets.encrypted_d27e803291ff_iv }} -in scripts/setup-keys.enc -d >> gradle.properties;
fi
sudo apt-get update
sudo apt-get install -y ninja-build
pushd $HOME
git clone --depth 1 https://github.com/facebook/buck.git
cd buck
ant
popd
echo "::set-env name=PATH::$PATH:$HOME/buck/bin/"
export PATH=$PATH:$HOME/buck/bin/
buck --version
export TERMINAL=dumb
source scripts/android-setup.sh && installAndroidSDK
echo "::set-env name=ANDROID_SDK::$ANDROID_HOME"
echo "::set-env name=ANDROID_NDK_REPOSITORY::$HOME/android-ndk"
echo "::set-env name=ANDROID_NDK_HOME::$ANDROID_NDK_REPOSITORY/android-ndk-r15c"
- name: Build
run: ./gradlew testDebugUnit && scripts/publish-snapshot.sh

View File

@@ -1 +0,0 @@
4.0

View File

@@ -1,77 +0,0 @@
language: java
os: linux
dist: trusty
addons:
apt:
sources:
- llvm-toolchain-trusty-6.0
- ubuntu-toolchain-r-test
packages:
- clang-6.0
env:
- TARGET: website
- TARGET: android
install:
- cd website
- yarn --ignore-scripts
- cd ..
cache:
directories:
- $HOME/buck
- $HOME/.gradle
before_install:
- |
if [[ -n "$encrypted_d27e803291ff_iv" ]]; then
openssl aes-256-cbc -K $encrypted_d27e803291ff_key -iv $encrypted_d27e803291ff_iv -in scripts/setup-keys.enc -d >> gradle.properties;
fi
# Android
- |
if [[ $TARGET = "android" ]]; then
pushd $HOME
git clone --depth 1 https://github.com/facebook/buck.git
cd buck
ant
popd
export PATH=$PATH:$HOME/buck/bin/
buck --version
export TERMINAL=dumb
source scripts/android-setup.sh && installAndroidSDK
export ANDROID_SDK=$ANDROID_HOME
export ANDROID_NDK_REPOSITORY=$HOME/android-ndk
export ANDROID_NDK_HOME=$ANDROID_NDK_REPOSITORY/android-ndk-r15c
fi
# Website
- |
if [[ $TARGET = "website" ]]; then
nvm install 8
nvm use 8
fi
script:
- |
if [[ $TARGET = "android" ]]; then
./gradlew testDebugUnit && scripts/publish-snapshot.sh
fi
- |
if [[ $TARGET = "website" ]]; then
pushd website
yarn build
popd
fi
deploy:
provider: pages
skip-cleanup: true
github-token: $GITHUB_TOKEN
fqdn: yogalayout.com
local-dir: website/public
email: yogabot@fb.com
name: Yoga-bot
keep-history: true
on:
branch: master
condition: $TARGET = website

31
BUCK
View File

@@ -2,7 +2,7 @@
# #
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep") load("//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep", "yoga_prebuilt_cxx_library")
GMOCK_OVERRIDE_FLAGS = [ GMOCK_OVERRIDE_FLAGS = [
# gmock does not mark mocked methods as override, ignore the warnings in tests # gmock does not mark mocked methods as override, ignore the warnings in tests
@@ -14,6 +14,18 @@ TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + [
"-DYG_ENABLE_EVENTS", "-DYG_ENABLE_EVENTS",
] ]
yoga_prebuilt_cxx_library(
name = "ndklog",
exported_platform_linker_flags = [
(
"^android.*",
["-llog"],
),
],
header_only = True,
visibility = YOGA_ROOTS,
)
yoga_cxx_library( yoga_cxx_library(
name = "yoga", name = "yoga",
srcs = glob(["yoga/**/*.cpp"]), srcs = glob(["yoga/**/*.cpp"]),
@@ -24,7 +36,21 @@ yoga_cxx_library(
tests = [":YogaTests"], tests = [":YogaTests"],
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
yoga_dep("lib/fb:ndklog"), ":ndklog",
],
)
yoga_cxx_library(
name = "yoga-static",
srcs = glob(["yoga/**/*.cpp"]),
compiler_flags = LIBRARY_COMPILER_FLAGS,
preferred_linkage = "static",
public_include_directories = ["."],
raw_headers = glob(["yoga/**/*.h"]),
tests = [":YogaTests"],
visibility = ["PUBLIC"],
deps = [
":ndklog",
], ],
) )
@@ -39,7 +65,6 @@ yoga_cxx_library(
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
":yoga", ":yoga",
yoga_dep("lib/fb:ndklog"),
], ],
) )

View File

@@ -33,6 +33,6 @@ Pod::Spec.new do |spec|
'-fPIC' '-fPIC'
] ]
spec.source_files = 'yoga/**/*.{c,h,cpp}' spec.source_files = 'yoga/**/*.{c,h,cpp}'
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h' spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h'
end end

View File

@@ -5,7 +5,7 @@
podspec = Pod::Spec.new do |spec| podspec = Pod::Spec.new do |spec|
spec.name = 'YogaKit' spec.name = 'YogaKit'
spec.version = '1.17.0' spec.version = '1.18.1'
spec.license = { :type => 'MIT', :file => "LICENSE" } spec.license = { :type => 'MIT', :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/' spec.documentation_url = 'https://facebook.github.io/yoga/docs/'
@@ -16,26 +16,22 @@ 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 => spec.version.to_s, :tag => "1.18.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.default_subspec = "Core"
spec.dependency 'Yoga', '~> 1.14'
spec.module_name = 'YogaKit' spec.module_name = 'YogaKit'
spec.dependency 'Yoga', '~> 1.14'
spec.subspec "Core" do |ss| # Fixes the bug related the xcode 11 not able to find swift related frameworks.
ss.source_files = 'YogaKit/Source/*.{h,m}' # https://github.com/Carthage/Carthage/issues/2825
ss.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h' # https://twitter.com/krzyzanowskim/status/1151549874653081601?s=21
ss.private_header_files = 'YogaKit/Source/YGLayout+Private.h' spec.pod_target_xcconfig = {"LD_VERIFY_BITCODE": "NO"}
end spec.source_files = 'YogaKit/Source/*.{h,m,swift}'
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
spec.subspec 'SwiftExtension' do |ss| spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
ss.source_files = 'YogaKit/Source/*.{swift}' spec.swift_version = '5.1'
end
end end
# See https://github.com/facebook/yoga/pull/366 # See https://github.com/facebook/yoga/pull/366

View File

@@ -37,11 +37,14 @@ yoga_apple_library(
), ),
compiler_flags = COMPILER_FLAGS, compiler_flags = COMPILER_FLAGS,
frameworks = [ frameworks = [
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
"$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework",
], ],
header_path_prefix = "", header_path_prefix = "",
link_whole = True, link_whole = True,
modular = True,
module_name = "YogaKit",
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
yoga_dep(":yoga"), yoga_dep(":yoga"),

View File

@@ -5,28 +5,29 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "YGLayout.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef void (^YGLayoutConfigurationBlock)(YGLayout *layout); typedef void (^YGLayoutConfigurationBlock)(YGLayout* layout);
@interface UIView (Yoga) @interface UIView (Yoga)
/** /**
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 Indicates whether or not Yoga is enabled
*/ */
@property (nonatomic, readonly, assign) BOOL isYogaEnabled; @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
to your code. If you plan on making multiple changes to YGLayout, it's more performant `objc_msgSend` to your code. If you plan on making multiple changes to
to use this method, which uses a single objc_msgSend call. YGLayout, it's more performant to use this method, which uses a single
objc_msgSend call.
*/ */
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block
NS_SWIFT_NAME(configureLayout(block:)); NS_SWIFT_NAME(configureLayout(block:));

View File

@@ -5,32 +5,30 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import <objc/runtime.h>
#import "UIView+Yoga.h" #import "UIView+Yoga.h"
#import "YGLayout+Private.h" #import "YGLayout+Private.h"
#import <objc/runtime.h>
static const void *kYGYogaAssociatedKey = &kYGYogaAssociatedKey; static const void* kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
@implementation UIView (YogaKit) @implementation UIView (YogaKit)
- (YGLayout *)yoga - (YGLayout*)yoga {
{ YGLayout* yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
YGLayout *yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey);
if (!yoga) { if (!yoga) {
yoga = [[YGLayout alloc] initWithView:self]; yoga = [[YGLayout alloc] initWithView:self];
objc_setAssociatedObject(self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(
self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} }
return yoga; return yoga;
} }
- (BOOL)isYogaEnabled - (BOOL)isYogaEnabled {
{
return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil; return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil;
} }
- (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block {
{
if (block != nil) { if (block != nil) {
block(self.yoga); block(self.yoga);
} }

View File

@@ -5,13 +5,13 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout.h"
#import <yoga/Yoga.h> #import <yoga/Yoga.h>
#import "YGLayout.h"
@interface YGLayout () @interface YGLayout ()
@property (nonatomic, assign, readonly) YGNodeRef node; @property(nonatomic, assign, readonly) YGNodeRef node;
- (instancetype)initWithView:(UIView *)view; - (instancetype)initWithView:(UIView*)view;
@end @end

View File

@@ -7,15 +7,15 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <yoga/YGEnums.h> #import <yoga/YGEnums.h>
#import <yoga/Yoga.h>
#import <yoga/YGMacros.h> #import <yoga/YGMacros.h>
#import <yoga/Yoga.h>
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
extern YGValue YGPointValue(CGFloat value) extern YGValue YGPointValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead"); "Use the swift Int and FloatingPoint extensions instead");
extern YGValue YGPercentValue(CGFloat value) extern YGValue YGPercentValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
NS_SWIFT_UNAVAILABLE("Use the swift Int and FloatingPoint extensions instead"); "Use the swift Int and FloatingPoint extensions instead");
YG_EXTERN_C_END YG_EXTERN_C_END
@@ -44,103 +44,107 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
The property that decides if we should include this view when calculating The property that decides if we should include this view when calculating
layout. Defaults to YES. layout. Defaults to YES.
*/ */
@property (nonatomic, readwrite, assign, setter=setIncludedInLayout:) BOOL isIncludedInLayout; @property(nonatomic, readwrite, assign, setter=setIncludedInLayout:)
BOOL isIncludedInLayout;
/** /**
The property that decides during layout/sizing whether or not styling properties should be applied. The property that decides during layout/sizing whether or not styling
Defaults to NO. properties should be applied. Defaults to NO.
*/ */
@property (nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled; @property(nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;
@property (nonatomic, readwrite, assign) YGDirection direction; @property(nonatomic, readwrite, assign) YGDirection direction;
@property (nonatomic, readwrite, assign) YGFlexDirection flexDirection; @property(nonatomic, readwrite, assign) YGFlexDirection flexDirection;
@property (nonatomic, readwrite, assign) YGJustify justifyContent; @property(nonatomic, readwrite, assign) YGJustify justifyContent;
@property (nonatomic, readwrite, assign) YGAlign alignContent; @property(nonatomic, readwrite, assign) YGAlign alignContent;
@property (nonatomic, readwrite, assign) YGAlign alignItems; @property(nonatomic, readwrite, assign) YGAlign alignItems;
@property (nonatomic, readwrite, assign) YGAlign alignSelf; @property(nonatomic, readwrite, assign) YGAlign alignSelf;
@property (nonatomic, readwrite, assign) YGPositionType position; @property(nonatomic, readwrite, assign) YGPositionType position;
@property (nonatomic, readwrite, assign) YGWrap flexWrap; @property(nonatomic, readwrite, assign) YGWrap flexWrap;
@property (nonatomic, readwrite, assign) YGOverflow overflow; @property(nonatomic, readwrite, assign) YGOverflow overflow;
@property (nonatomic, readwrite, assign) YGDisplay display; @property(nonatomic, readwrite, assign) YGDisplay display;
@property (nonatomic, readwrite, assign) CGFloat flex; @property(nonatomic, readwrite, assign) CGFloat flex;
@property (nonatomic, readwrite, assign) CGFloat flexGrow; @property(nonatomic, readwrite, assign) CGFloat flexGrow;
@property (nonatomic, readwrite, assign) CGFloat flexShrink; @property(nonatomic, readwrite, assign) CGFloat flexShrink;
@property (nonatomic, readwrite, assign) YGValue flexBasis; @property(nonatomic, readwrite, assign) YGValue flexBasis;
@property (nonatomic, readwrite, assign) YGValue left; @property(nonatomic, readwrite, assign) YGValue left;
@property (nonatomic, readwrite, assign) YGValue top; @property(nonatomic, readwrite, assign) YGValue top;
@property (nonatomic, readwrite, assign) YGValue right; @property(nonatomic, readwrite, assign) YGValue right;
@property (nonatomic, readwrite, assign) YGValue bottom; @property(nonatomic, readwrite, assign) YGValue bottom;
@property (nonatomic, readwrite, assign) YGValue start; @property(nonatomic, readwrite, assign) YGValue start;
@property (nonatomic, readwrite, assign) YGValue end; @property(nonatomic, readwrite, assign) YGValue end;
@property (nonatomic, readwrite, assign) YGValue marginLeft; @property(nonatomic, readwrite, assign) YGValue marginLeft;
@property (nonatomic, readwrite, assign) YGValue marginTop; @property(nonatomic, readwrite, assign) YGValue marginTop;
@property (nonatomic, readwrite, assign) YGValue marginRight; @property(nonatomic, readwrite, assign) YGValue marginRight;
@property (nonatomic, readwrite, assign) YGValue marginBottom; @property(nonatomic, readwrite, assign) YGValue marginBottom;
@property (nonatomic, readwrite, assign) YGValue marginStart; @property(nonatomic, readwrite, assign) YGValue marginStart;
@property (nonatomic, readwrite, assign) YGValue marginEnd; @property(nonatomic, readwrite, assign) YGValue marginEnd;
@property (nonatomic, readwrite, assign) YGValue marginHorizontal; @property(nonatomic, readwrite, assign) YGValue marginHorizontal;
@property (nonatomic, readwrite, assign) YGValue marginVertical; @property(nonatomic, readwrite, assign) YGValue marginVertical;
@property (nonatomic, readwrite, assign) YGValue margin; @property(nonatomic, readwrite, assign) YGValue margin;
@property (nonatomic, readwrite, assign) YGValue paddingLeft; @property(nonatomic, readwrite, assign) YGValue paddingLeft;
@property (nonatomic, readwrite, assign) YGValue paddingTop; @property(nonatomic, readwrite, assign) YGValue paddingTop;
@property (nonatomic, readwrite, assign) YGValue paddingRight; @property(nonatomic, readwrite, assign) YGValue paddingRight;
@property (nonatomic, readwrite, assign) YGValue paddingBottom; @property(nonatomic, readwrite, assign) YGValue paddingBottom;
@property (nonatomic, readwrite, assign) YGValue paddingStart; @property(nonatomic, readwrite, assign) YGValue paddingStart;
@property (nonatomic, readwrite, assign) YGValue paddingEnd; @property(nonatomic, readwrite, assign) YGValue paddingEnd;
@property (nonatomic, readwrite, assign) YGValue paddingHorizontal; @property(nonatomic, readwrite, assign) YGValue paddingHorizontal;
@property (nonatomic, readwrite, assign) YGValue paddingVertical; @property(nonatomic, readwrite, assign) YGValue paddingVertical;
@property (nonatomic, readwrite, assign) YGValue padding; @property(nonatomic, readwrite, assign) YGValue padding;
@property (nonatomic, readwrite, assign) CGFloat borderLeftWidth; @property(nonatomic, readwrite, assign) CGFloat borderLeftWidth;
@property (nonatomic, readwrite, assign) CGFloat borderTopWidth; @property(nonatomic, readwrite, assign) CGFloat borderTopWidth;
@property (nonatomic, readwrite, assign) CGFloat borderRightWidth; @property(nonatomic, readwrite, assign) CGFloat borderRightWidth;
@property (nonatomic, readwrite, assign) CGFloat borderBottomWidth; @property(nonatomic, readwrite, assign) CGFloat borderBottomWidth;
@property (nonatomic, readwrite, assign) CGFloat borderStartWidth; @property(nonatomic, readwrite, assign) CGFloat borderStartWidth;
@property (nonatomic, readwrite, assign) CGFloat borderEndWidth; @property(nonatomic, readwrite, assign) CGFloat borderEndWidth;
@property (nonatomic, readwrite, assign) CGFloat borderWidth; @property(nonatomic, readwrite, assign) CGFloat borderWidth;
@property (nonatomic, readwrite, assign) YGValue width; @property(nonatomic, readwrite, assign) YGValue width;
@property (nonatomic, readwrite, assign) YGValue height; @property(nonatomic, readwrite, assign) YGValue height;
@property (nonatomic, readwrite, assign) YGValue minWidth; @property(nonatomic, readwrite, assign) YGValue minWidth;
@property (nonatomic, readwrite, assign) YGValue minHeight; @property(nonatomic, readwrite, assign) YGValue minHeight;
@property (nonatomic, readwrite, assign) YGValue maxWidth; @property(nonatomic, readwrite, assign) YGValue maxWidth;
@property (nonatomic, readwrite, assign) YGValue maxHeight; @property(nonatomic, readwrite, assign) YGValue maxHeight;
// Yoga specific properties, not compatible with flexbox specification // Yoga specific properties, not compatible with flexbox specification
@property (nonatomic, readwrite, assign) CGFloat aspectRatio; @property(nonatomic, readwrite, assign) CGFloat aspectRatio;
/** /**
Get the resolved direction of this node. This won't be YGDirectionInherit Get the resolved direction of this node. This won't be YGDirectionInherit
*/ */
@property (nonatomic, readonly, assign) YGDirection resolvedDirection; @property(nonatomic, readonly, assign) YGDirection resolvedDirection;
/** /**
Perform a layout calculation and update the frames of the views in the hierarchy with the results. Perform a layout calculation and update the frames of the views in the
If the origin is not preserved, the root view's layout results will applied from {0,0}. hierarchy with the results. If the origin is not preserved, the root view's
layout results will applied from {0,0}.
*/ */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
NS_SWIFT_NAME(applyLayout(preservingOrigin:)); NS_SWIFT_NAME(applyLayout(preservingOrigin:));
/** /**
Perform a layout calculation and update the frames of the views in the hierarchy with the results. Perform a layout calculation and update the frames of the views in the
If the origin is not preserved, the root view's layout results will applied from {0,0}. hierarchy with the results. If the origin is not preserved, the root view's
layout results will applied from {0,0}.
*/ */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:)); NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:));
/** /**
Returns the size of the view if no constraints were given. This could equivalent to calling [self Returns the size of the view if no constraints were given. This could
sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
*/ */
@property (nonatomic, readonly, assign) CGSize intrinsicSize; @property(nonatomic, readonly, assign) CGSize intrinsicSize;
/** /**
Returns the size of the view based on provided constraints. Pass NaN for an unconstrained dimension. Returns the size of the view based on provided constraints. Pass NaN for an
unconstrained dimension.
*/ */
- (CGSize)calculateLayoutWithSize:(CGSize)size - (CGSize)calculateLayoutWithSize:(CGSize)size
NS_SWIFT_NAME(calculateLayout(with:)); NS_SWIFT_NAME(calculateLayout(with:));
@@ -148,19 +152,19 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
/** /**
Returns the number of children that are using Flexbox. Returns the number of children that are using Flexbox.
*/ */
@property (nonatomic, readonly, assign) NSUInteger numberOfChildren; @property(nonatomic, readonly, assign) NSUInteger numberOfChildren;
/** /**
Return a BOOL indiciating whether or not we this node contains any subviews that are included in Return a BOOL indiciating whether or not we this node contains any subviews
Yoga's layout. that are included in Yoga's layout.
*/ */
@property (nonatomic, readonly, assign) BOOL isLeaf; @property(nonatomic, readonly, assign) BOOL isLeaf;
/** /**
Return's a BOOL indicating if a view is dirty. When a node is dirty Return's a BOOL indicating if a view is dirty. When a node is dirty
it usually indicates that it will be remeasured on the next layout pass. it usually indicates that it will be remeasured on the next layout pass.
*/ */
@property (nonatomic, readonly, assign) BOOL isDirty; @property(nonatomic, readonly, assign) BOOL isDirty;
/** /**
Mark that a view's layout needs to be recalculated. Only works for leaf views. Mark that a view's layout needs to be recalculated. Only works for leaf views.

View File

@@ -5,153 +5,184 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import "YGLayout+Private.h"
#import "UIView+Yoga.h" #import "UIView+Yoga.h"
#import "YGLayout+Private.h"
#define YG_PROPERTY(type, lowercased_name, capitalized_name) \ #define YG_PROPERTY(type, lowercased_name, capitalized_name) \
- (type)lowercased_name \ -(type)lowercased_name { \
{ \ return YGNodeStyleGet##capitalized_name(self.node); \
return YGNodeStyleGet##capitalized_name(self.node); \ } \
} \ \
\ -(void)set##capitalized_name : (type)lowercased_name { \
- (void)set##capitalized_name:(type)lowercased_name \ YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
{ \ }
YGNodeStyleSet##capitalized_name(self.node, lowercased_name); \
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \
-(YGValue)lowercased_name { \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
-(void)set##capitalized_name : (YGValue)lowercased_name { \
switch (lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent( \
self.node, lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
-(YGValue)lowercased_name { \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
-(void)set##capitalized_name : (YGValue)lowercased_name { \
switch (lowercased_name.unit) { \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent( \
self.node, lowercased_name.value); \
break; \
case YGUnitAuto: \
YGNodeStyleSet##capitalized_name##Auto(self.node); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_EDGE_PROPERTY_GETTER( \
type, lowercased_name, capitalized_name, property, edge) \
-(type)lowercased_name { \
return YGNodeStyleGet##property(self.node, edge); \
}
#define YG_EDGE_PROPERTY_SETTER( \
lowercased_name, capitalized_name, property, edge) \
-(void)set##capitalized_name : (CGFloat)lowercased_name { \
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
}
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER( \
CGFloat, lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGE_PROPERTY_SETTER( \
objc_lowercased_name, objc_capitalized_name, c_name, edge) \
-(void)set##objc_capitalized_name : (YGValue)objc_lowercased_name { \
switch (objc_lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##c_name##Percent( \
self.node, edge, objc_lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_VALUE_EDGE_PROPERTY( \
lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER( \
YGValue, lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_SETTER( \
lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Left, \
capitalized_name##Left, \
capitalized_name, \
YGEdgeLeft) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Top, \
capitalized_name##Top, \
capitalized_name, \
YGEdgeTop) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Right, \
capitalized_name##Right, \
capitalized_name, \
YGEdgeRight) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Bottom, \
capitalized_name##Bottom, \
capitalized_name, \
YGEdgeBottom) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Start, \
capitalized_name##Start, \
capitalized_name, \
YGEdgeStart) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##End, \
capitalized_name##End, \
capitalized_name, \
YGEdgeEnd) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Horizontal, \
capitalized_name##Horizontal, \
capitalized_name, \
YGEdgeHorizontal) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name##Vertical, \
capitalized_name##Vertical, \
capitalized_name, \
YGEdgeVertical) \
YG_VALUE_EDGE_PROPERTY( \
lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
YGValue YGPointValue(CGFloat value) {
return (YGValue){.value = value, .unit = YGUnitPoint};
} }
#define YG_VALUE_PROPERTY(lowercased_name, capitalized_name) \ YGValue YGPercentValue(CGFloat value) {
- (YGValue)lowercased_name \ return (YGValue){.value = value, .unit = YGUnitPercent};
{ \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
- (void)set##capitalized_name:(YGValue)lowercased_name \
{ \
switch (lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_AUTO_VALUE_PROPERTY(lowercased_name, capitalized_name) \
- (YGValue)lowercased_name \
{ \
return YGNodeStyleGet##capitalized_name(self.node); \
} \
\
- (void)set##capitalized_name:(YGValue)lowercased_name \
{ \
switch (lowercased_name.unit) { \
case YGUnitPoint: \
YGNodeStyleSet##capitalized_name(self.node, lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##capitalized_name##Percent(self.node, lowercased_name.value); \
break; \
case YGUnitAuto: \
YGNodeStyleSet##capitalized_name##Auto(self.node); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_EDGE_PROPERTY_GETTER(type, lowercased_name, capitalized_name, property, edge) \
- (type)lowercased_name \
{ \
return YGNodeStyleGet##property(self.node, edge); \
}
#define YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge) \
- (void)set##capitalized_name:(CGFloat)lowercased_name \
{ \
YGNodeStyleSet##property(self.node, edge, lowercased_name); \
}
#define YG_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER(CGFloat, lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGE_PROPERTY_SETTER(objc_lowercased_name, objc_capitalized_name, c_name, edge) \
- (void)set##objc_capitalized_name:(YGValue)objc_lowercased_name \
{ \
switch (objc_lowercased_name.unit) { \
case YGUnitUndefined: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPoint: \
YGNodeStyleSet##c_name(self.node, edge, objc_lowercased_name.value); \
break; \
case YGUnitPercent: \
YGNodeStyleSet##c_name##Percent(self.node, edge, objc_lowercased_name.value); \
break; \
default: \
NSAssert(NO, @"Not implemented"); \
} \
}
#define YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, property, edge) \
YG_EDGE_PROPERTY_GETTER(YGValue, lowercased_name, capitalized_name, property, edge) \
YG_VALUE_EDGE_PROPERTY_SETTER(lowercased_name, capitalized_name, property, edge)
#define YG_VALUE_EDGES_PROPERTIES(lowercased_name, capitalized_name) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Left, capitalized_name##Left, capitalized_name, YGEdgeLeft) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Top, capitalized_name##Top, capitalized_name, YGEdgeTop) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Right, capitalized_name##Right, capitalized_name, YGEdgeRight) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Bottom, capitalized_name##Bottom, capitalized_name, YGEdgeBottom) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Start, capitalized_name##Start, capitalized_name, YGEdgeStart) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##End, capitalized_name##End, capitalized_name, YGEdgeEnd) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Horizontal, capitalized_name##Horizontal, capitalized_name, YGEdgeHorizontal) \
YG_VALUE_EDGE_PROPERTY(lowercased_name##Vertical, capitalized_name##Vertical, capitalized_name, YGEdgeVertical) \
YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, capitalized_name, YGEdgeAll)
YGValue YGPointValue(CGFloat value)
{
return (YGValue) { .value = value, .unit = YGUnitPoint };
}
YGValue YGPercentValue(CGFloat value)
{
return (YGValue) { .value = value, .unit = YGUnitPercent };
} }
static YGConfigRef globalConfig; static YGConfigRef globalConfig;
@interface YGLayout () @interface YGLayout ()
@property (nonatomic, weak, readonly) UIView *view; @property(nonatomic, weak, readonly) UIView* view;
@property(nonatomic, assign, readonly) BOOL isUIView; @property(nonatomic, assign, readonly) BOOL isUIView;
@end @end
@implementation YGLayout @implementation YGLayout
@synthesize isEnabled=_isEnabled; @synthesize isEnabled = _isEnabled;
@synthesize isIncludedInLayout=_isIncludedInLayout; @synthesize isIncludedInLayout = _isIncludedInLayout;
@synthesize node=_node; @synthesize node = _node;
+ (void)initialize + (void)initialize {
{
globalConfig = YGConfigNew(); globalConfig = YGConfigNew();
YGConfigSetExperimentalFeatureEnabled(globalConfig, YGExperimentalFeatureWebFlexBasis, true); YGConfigSetExperimentalFeatureEnabled(
globalConfig, YGExperimentalFeatureWebFlexBasis, true);
YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale); YGConfigSetPointScaleFactor(globalConfig, [UIScreen mainScreen].scale);
} }
- (instancetype)initWithView:(UIView*)view - (instancetype)initWithView:(UIView*)view {
{
if (self = [super init]) { if (self = [super init]) {
_view = view; _view = view;
_node = YGNodeNewWithConfig(globalConfig); _node = YGNodeNewWithConfig(globalConfig);
YGNodeSetContext(_node, (__bridge void *) view); YGNodeSetContext(_node, (__bridge void*)view);
_isEnabled = NO; _isEnabled = NO;
_isIncludedInLayout = YES; _isIncludedInLayout = YES;
_isUIView = [view isMemberOfClass:[UIView class]]; _isUIView = [view isMemberOfClass:[UIView class]];
@@ -160,18 +191,15 @@ static YGConfigRef globalConfig;
return self; return self;
} }
- (void)dealloc - (void)dealloc {
{
YGNodeFree(self.node); YGNodeFree(self.node);
} }
- (BOOL)isDirty - (BOOL)isDirty {
{
return YGNodeIsDirty(self.node); return YGNodeIsDirty(self.node);
} }
- (void)markDirty - (void)markDirty {
{
if (self.isDirty || !self.isLeaf) { if (self.isDirty || !self.isLeaf) {
return; return;
} }
@@ -187,17 +215,17 @@ static YGConfigRef globalConfig;
YGNodeMarkDirty(node); YGNodeMarkDirty(node);
} }
- (NSUInteger)numberOfChildren - (NSUInteger)numberOfChildren {
{
return YGNodeGetChildCount(self.node); return YGNodeGetChildCount(self.node);
} }
- (BOOL)isLeaf - (BOOL)isLeaf {
{ NSAssert(
NSAssert([NSThread isMainThread], @"This method must be called on the main thread."); [NSThread isMainThread],
@"This method must be called on the main thread.");
if (self.isEnabled) { if (self.isEnabled) {
for (UIView *subview in self.view.subviews) { for (UIView* subview in self.view.subviews) {
YGLayout *const yoga = subview.yoga; YGLayout* const yoga = subview.yoga;
if (yoga.isEnabled && yoga.isIncludedInLayout) { if (yoga.isEnabled && yoga.isIncludedInLayout) {
return NO; return NO;
} }
@@ -209,13 +237,11 @@ static YGConfigRef globalConfig;
#pragma mark - Style #pragma mark - Style
- (YGPositionType)position - (YGPositionType)position {
{
return YGNodeStyleGetPositionType(self.node); return YGNodeStyleGetPositionType(self.node);
} }
- (void)setPosition:(YGPositionType)position - (void)setPosition:(YGPositionType)position {
{
YGNodeStyleSetPositionType(self.node, position); YGNodeStyleSetPositionType(self.node, position);
} }
@@ -261,25 +287,23 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
#pragma mark - Layout and Sizing #pragma mark - Layout and Sizing
- (YGDirection)resolvedDirection - (YGDirection)resolvedDirection {
{
return YGNodeLayoutGetDirection(self.node); return YGNodeLayoutGetDirection(self.node);
} }
- (void)applyLayout - (void)applyLayout {
{
[self calculateLayoutWithSize:self.view.bounds.size]; [self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, NO); YGApplyLayoutToViewHierarchy(self.view, NO);
} }
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin {
{
[self calculateLayoutWithSize:self.view.bounds.size]; [self calculateLayoutWithSize:self.view.bounds.size];
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin); YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
} }
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility - (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
{ dimensionFlexibility:
(YGDimensionFlexibility)dimensionFlexibility {
CGSize size = self.view.bounds.size; CGSize size = self.view.bounds.size;
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) { if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
size.width = YGUndefined; size.width = YGUndefined;
@@ -291,18 +315,15 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin); YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
} }
- (CGSize)intrinsicSize {
- (CGSize)intrinsicSize
{
const CGSize constrainedSize = { const CGSize constrainedSize = {
.width = YGUndefined, .width = YGUndefined,
.height = YGUndefined, .height = YGUndefined,
}; };
return [self calculateLayoutWithSize:constrainedSize]; return [self calculateLayoutWithSize:constrainedSize];
} }
- (CGSize)calculateLayoutWithSize:(CGSize)size - (CGSize)calculateLayoutWithSize:(CGSize)size {
{
NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main."); NSAssert([NSThread isMainThread], @"Yoga calculation must be done on main.");
NSAssert(self.isEnabled, @"Yoga is not enabled for this view."); NSAssert(self.isEnabled, @"Yoga is not enabled for this view.");
@@ -310,30 +331,28 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
const YGNodeRef node = self.node; const YGNodeRef node = self.node;
YGNodeCalculateLayout( YGNodeCalculateLayout(
node, node, size.width, size.height, YGNodeStyleGetDirection(node));
size.width,
size.height,
YGNodeStyleGetDirection(node));
return (CGSize) { return (CGSize){
.width = YGNodeLayoutGetWidth(node), .width = YGNodeLayoutGetWidth(node),
.height = YGNodeLayoutGetHeight(node), .height = YGNodeLayoutGetHeight(node),
}; };
} }
#pragma mark - Private #pragma mark - Private
static YGSize YGMeasureView( static YGSize YGMeasureView(
YGNodeRef node, YGNodeRef node,
float width, float width,
YGMeasureMode widthMode, YGMeasureMode widthMode,
float height, float height,
YGMeasureMode heightMode) YGMeasureMode heightMode) {
{ const CGFloat constrainedWidth =
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width; (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height; const CGFloat constrainedHeight =
(heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : height;
UIView *view = (__bridge UIView*) YGNodeGetContext(node); UIView* view = (__bridge UIView*)YGNodeGetContext(node);
CGSize sizeThatFits = CGSizeZero; CGSize sizeThatFits = CGSizeZero;
// The default implementation of sizeThatFits: returns the existing size of // The default implementation of sizeThatFits: returns the existing size of
@@ -349,17 +368,18 @@ static YGSize YGMeasureView(
}]; }];
} }
return (YGSize) { return (YGSize){
.width = YGSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode), .width = YGSanitizeMeasurement(
.height = YGSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode), constrainedWidth, sizeThatFits.width, widthMode),
.height = YGSanitizeMeasurement(
constrainedHeight, sizeThatFits.height, heightMode),
}; };
} }
static CGFloat YGSanitizeMeasurement( static CGFloat YGSanitizeMeasurement(
CGFloat constrainedSize, CGFloat constrainedSize,
CGFloat measuredSize, CGFloat measuredSize,
YGMeasureMode measureMode) YGMeasureMode measureMode) {
{
CGFloat result; CGFloat result;
if (measureMode == YGMeasureModeExactly) { if (measureMode == YGMeasureModeExactly) {
result = constrainedSize; result = constrainedSize;
@@ -372,13 +392,14 @@ static CGFloat YGSanitizeMeasurement(
return result; return result;
} }
static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *subviews) static BOOL YGNodeHasExactSameChildren(
{ const YGNodeRef node,
NSArray<UIView*>* subviews) {
if (YGNodeGetChildCount(node) != subviews.count) { if (YGNodeGetChildCount(node) != subviews.count) {
return NO; return NO;
} }
for (int i=0; i<subviews.count; i++) { for (int i = 0; i < subviews.count; i++) {
if (YGNodeGetChild(node, i) != subviews[i].yoga.node) { if (YGNodeGetChild(node, i) != subviews[i].yoga.node) {
return NO; return NO;
} }
@@ -387,9 +408,8 @@ static BOOL YGNodeHasExactSameChildren(const YGNodeRef node, NSArray<UIView *> *
return YES; return YES;
} }
static void YGAttachNodesFromViewHierachy(UIView *const view) static void YGAttachNodesFromViewHierachy(UIView* const view) {
{ YGLayout* const yoga = view.yoga;
YGLayout *const yoga = view.yoga;
const YGNodeRef node = yoga.node; const YGNodeRef node = yoga.node;
// Only leaf nodes should have a measure function // Only leaf nodes should have a measure function
@@ -399,8 +419,9 @@ static void YGAttachNodesFromViewHierachy(UIView *const view)
} else { } else {
YGNodeSetMeasureFunc(node, NULL); YGNodeSetMeasureFunc(node, NULL);
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count]; NSMutableArray<UIView*>* subviewsToInclude =
for (UIView *subview in view.subviews) { [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
for (UIView* subview in view.subviews) {
if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) { if (subview.yoga.isEnabled && subview.yoga.isIncludedInLayout) {
[subviewsToInclude addObject:subview]; [subviewsToInclude addObject:subview];
} }
@@ -408,19 +429,18 @@ static void YGAttachNodesFromViewHierachy(UIView *const view)
if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) { if (!YGNodeHasExactSameChildren(node, subviewsToInclude)) {
YGRemoveAllChildren(node); YGRemoveAllChildren(node);
for (int i=0; i<subviewsToInclude.count; i++) { for (int i = 0; i < subviewsToInclude.count; i++) {
YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i); YGNodeInsertChild(node, subviewsToInclude[i].yoga.node, i);
} }
} }
for (UIView *const subview in subviewsToInclude) { for (UIView* const subview in subviewsToInclude) {
YGAttachNodesFromViewHierachy(subview); YGAttachNodesFromViewHierachy(subview);
} }
} }
} }
static void YGRemoveAllChildren(const YGNodeRef node) static void YGRemoveAllChildren(const YGNodeRef node) {
{
if (node == NULL) { if (node == NULL) {
return; return;
} }
@@ -428,52 +448,56 @@ static void YGRemoveAllChildren(const YGNodeRef node)
YGNodeRemoveAllChildren(node); YGNodeRemoveAllChildren(node);
} }
static CGFloat YGRoundPixelValue(CGFloat value) static CGFloat YGRoundPixelValue(CGFloat value) {
{
static CGFloat scale; static CGFloat scale;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(){ dispatch_once(&onceToken, ^() {
scale = [UIScreen mainScreen].scale; scale = [UIScreen mainScreen].scale;
}); });
return roundf(value * scale) / scale; return roundf(value * scale) / scale;
} }
static void YGApplyLayoutToViewHierarchy(UIView *view, BOOL preserveOrigin) static void YGApplyLayoutToViewHierarchy(UIView* view, BOOL preserveOrigin) {
{ NSCAssert(
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread."); [NSThread isMainThread],
@"Framesetting should only be done on the main thread.");
const YGLayout *yoga = view.yoga; const YGLayout* yoga = view.yoga;
if (!yoga.isIncludedInLayout) { if (!yoga.isIncludedInLayout) {
return; return;
} }
YGNodeRef node = yoga.node; YGNodeRef node = yoga.node;
const CGPoint topLeft = { const CGPoint topLeft = {
YGNodeLayoutGetLeft(node), YGNodeLayoutGetLeft(node),
YGNodeLayoutGetTop(node), YGNodeLayoutGetTop(node),
}; };
const CGPoint bottomRight = { const CGPoint bottomRight = {
topLeft.x + YGNodeLayoutGetWidth(node), topLeft.x + YGNodeLayoutGetWidth(node),
topLeft.y + YGNodeLayoutGetHeight(node), topLeft.y + YGNodeLayoutGetHeight(node),
}; };
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero; const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
view.frame = (CGRect) { view.frame = (CGRect){
.origin = { .origin =
.x = YGRoundPixelValue(topLeft.x + origin.x), {
.y = YGRoundPixelValue(topLeft.y + origin.y), .x = YGRoundPixelValue(topLeft.x + origin.x),
}, .y = YGRoundPixelValue(topLeft.y + origin.y),
.size = { },
.width = YGRoundPixelValue(bottomRight.x) - YGRoundPixelValue(topLeft.x), .size =
.height = YGRoundPixelValue(bottomRight.y) - YGRoundPixelValue(topLeft.y), {
}, .width = YGRoundPixelValue(bottomRight.x) -
YGRoundPixelValue(topLeft.x),
.height = YGRoundPixelValue(bottomRight.y) -
YGRoundPixelValue(topLeft.y),
},
}; };
if (!yoga.isLeaf) { if (!yoga.isLeaf) {
for (NSUInteger i=0; i<view.subviews.count; i++) { for (NSUInteger i = 0; i < view.subviews.count; i++) {
YGApplyLayoutToViewHierarchy(view.subviews[i], NO); YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
} }
} }

View File

@@ -16,17 +16,15 @@
@implementation YogaKitTests @implementation YogaKitTests
- (void)testConfigureLayoutIsNoOpWithNilBlock - (void)testConfigureLayoutIsNoOpWithNilBlock {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
id block = nil; id block = nil;
XCTAssertNoThrow([view configureLayoutWithBlock:block]); XCTAssertNoThrow([view configureLayoutWithBlock:block]);
} }
- (void)testConfigureLayoutBlockWorksWithValidBlock - (void)testConfigureLayoutBlockWorksWithValidBlock {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; [view configureLayoutWithBlock:^(YGLayout* layout) {
[view configureLayoutWithBlock:^(YGLayout *layout){
XCTAssertNotNil(layout); XCTAssertNotNil(layout);
layout.isEnabled = YES; layout.isEnabled = YES;
layout.width = YGPointValue(25); layout.width = YGPointValue(25);
@@ -36,12 +34,11 @@
XCTAssertEqual(view.yoga.width.value, 25); XCTAssertEqual(view.yoga.width.value, 25);
} }
- (void)testNodesAreDeallocedWithSingleView - (void)testNodesAreDeallocedWithSingleView {
{ __weak YGLayout* layoutRef = nil;
__weak YGLayout *layoutRef = nil;
@autoreleasepool { @autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.flexBasis = YGPointValue(1); view.yoga.flexBasis = YGPointValue(1);
layoutRef = view.yoga; layoutRef = view.yoga;
@@ -53,17 +50,16 @@
XCTAssertNil(layoutRef); XCTAssertNil(layoutRef);
} }
- (void)testNodesAreDeallocedCascade - (void)testNodesAreDeallocedCascade {
{ __weak YGLayout* topLayout = nil;
__weak YGLayout *topLayout = nil; __weak YGLayout* subviewLayout = nil;
__weak YGLayout *subviewLayout = nil;
@autoreleasepool { @autoreleasepool {
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
topLayout = view.yoga; topLayout = view.yoga;
topLayout.flexBasis = YGPointValue(1); topLayout.flexBasis = YGPointValue(1);
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
subviewLayout = subview.yoga; subviewLayout = subview.yoga;
subviewLayout.flexBasis = YGPointValue(1); subviewLayout.flexBasis = YGPointValue(1);
@@ -74,9 +70,8 @@
XCTAssertNil(subviewLayout); XCTAssertNil(subviewLayout);
} }
- (void)testIsEnabled - (void)testIsEnabled {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertFalse(view.yoga.isEnabled); XCTAssertFalse(view.yoga.isEnabled);
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
@@ -86,30 +81,31 @@
XCTAssertFalse(view.yoga.isEnabled); XCTAssertFalse(view.yoga.isEnabled);
} }
- (void)testSizeThatFitsAsserts - (void)testSizeThatFitsAsserts {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; dispatch_sync(
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){ dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL),
XCTAssertThrows(view.yoga.intrinsicSize); ^(void) {
}); XCTAssertThrows(view.yoga.intrinsicSize);
});
} }
- (void)testSizeThatFitsSmoke - (void)testSizeThatFitsSmoke {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart; container.yoga.alignItems = YGAlignFlexStart;
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero]; UILabel* longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
longTextLabel.text = @"This is a very very very very very very very very long piece of text."; longTextLabel.text =
@"This is a very very very very very very very very long piece of text.";
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail; longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
longTextLabel.numberOfLines = 1; longTextLabel.numberOfLines = 1;
longTextLabel.yoga.isEnabled = YES; longTextLabel.yoga.isEnabled = YES;
longTextLabel.yoga.flexShrink = 1; longTextLabel.yoga.flexShrink = 1;
[container addSubview:longTextLabel]; [container addSubview:longTextLabel];
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
textBadgeView.yoga.isEnabled = YES; textBadgeView.yoga.isEnabled = YES;
textBadgeView.yoga.margin = YGPointValue(0); textBadgeView.yoga.margin = YGPointValue(0);
textBadgeView.yoga.width = YGPointValue(10); textBadgeView.yoga.width = YGPointValue(10);
@@ -124,7 +120,9 @@
const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize; const CGSize longTextLabelSize = longTextLabel.yoga.intrinsicSize;
XCTAssertEqual(longTextLabelSize.height, containerSize.height); XCTAssertEqual(longTextLabelSize.height, containerSize.height);
XCTAssertEqual(longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width, containerSize.width); XCTAssertEqual(
longTextLabelSize.width + textBadgeView.yoga.intrinsicSize.width,
containerSize.width);
} }
- (void)testSizeThatFitsEmptyView { - (void)testSizeThatFitsEmptyView {
@@ -136,18 +134,17 @@
XCTAssertEqual(viewSize.width, 0); XCTAssertEqual(viewSize.width, 0);
} }
- (void)testPreservingOrigin - (void)testPreservingOrigin {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 75)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,75)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.flexBasis = YGPointValue(0); view.yoga.flexBasis = YGPointValue(0);
view.yoga.flexGrow = 1; view.yoga.flexGrow = 1;
[container addSubview:view]; [container addSubview:view];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* view2 = [[UIView alloc] initWithFrame:CGRectZero];
view2.yoga.isEnabled = YES; view2.yoga.isEnabled = YES;
view2.yoga.marginTop = YGPointValue(25); view2.yoga.marginTop = YGPointValue(25);
view2.yoga.flexBasis = YGPointValue(0); view2.yoga.flexBasis = YGPointValue(0);
@@ -161,28 +158,28 @@
XCTAssertEqual(25, view2.frame.origin.y); XCTAssertEqual(25, view2.frame.origin.y);
} }
- (void)testContainerWithFlexibleWidthGetsCorrectlySized - (void)testContainerWithFlexibleWidthGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
[container addSubview:view]; [container addSubview:view];
[container.yoga applyLayoutPreservingOrigin:YES dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth]; [container.yoga
applyLayoutPreservingOrigin:YES
dimensionFlexibility:YGDimensionFlexibilityFlexibleWidth];
XCTAssertEqual(100, container.frame.size.width); XCTAssertEqual(100, container.frame.size.width);
XCTAssertEqual(200, container.frame.size.height); XCTAssertEqual(200, container.frame.size.height);
} }
- (void)testContainerWithFlexibleHeightGetsCorrectlySized - (void)testContainerWithFlexibleHeightGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
@@ -195,12 +192,11 @@
XCTAssertEqual(100, container.frame.size.height); XCTAssertEqual(100, container.frame.size.height);
} }
- (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized - (void)testContainerWithFlexibleWidthAndHeightGetsCorrectlySized {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
view.yoga.width = YGPointValue(100); view.yoga.width = YGPointValue(100);
view.yoga.height = YGPointValue(100); view.yoga.height = YGPointValue(100);
@@ -214,12 +210,11 @@
XCTAssertEqual(100, container.frame.size.height); XCTAssertEqual(100, container.frame.size.height);
} }
- (void)testMarkingDirtyOnlyWorksOnLeafNodes - (void)testMarkingDirtyOnlyWorksOnLeafNodes {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
subview.yoga.isEnabled = YES; subview.yoga.isEnabled = YES;
[container addSubview:subview]; [container addSubview:subview];
@@ -232,14 +227,13 @@
XCTAssertTrue(subview.yoga.isDirty); XCTAssertTrue(subview.yoga.isDirty);
} }
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation - (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
container.yoga.alignItems = YGAlignFlexStart; container.yoga.alignItems = YGAlignFlexStart;
UILabel *view = [[UILabel alloc] initWithFrame:CGRectZero]; UILabel* view = [[UILabel alloc] initWithFrame:CGRectZero];
view.text = @"This is a short text."; view.text = @"This is a short text.";
view.numberOfLines = 1; view.numberOfLines = 1;
view.yoga.isEnabled = YES; view.yoga.isEnabled = YES;
@@ -257,61 +251,70 @@
XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass)); XCTAssertFalse(CGSizeEqualToSize(view.frame.size, viewSizeAfterFirstPass));
} }
- (void)testFrameAndOriginPlacement - (void)testFrameAndOriginPlacement {
{
const CGSize containerSize = CGSizeMake(320, 50); const CGSize containerSize = CGSizeMake(320, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqualWithAccuracy(subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON); XCTAssertEqualWithAccuracy(
XCTAssertEqualWithAccuracy(subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON); subview2.frame.origin.x, CGRectGetMaxX(subview1.frame), FLT_EPSILON);
XCTAssertEqualWithAccuracy(
subview3.frame.origin.x, CGRectGetMaxX(subview2.frame), FLT_EPSILON);
CGFloat totalWidth = 0; CGFloat totalWidth = 0;
for (UIView *view in container.subviews) { for (UIView* view in container.subviews) {
totalWidth += view.bounds.size.width; totalWidth += view.bounds.size.width;
} }
XCTAssertEqual(containerSize.width, totalWidth, @"The container's width is %.6f, the subviews take up %.6f", containerSize.width, totalWidth); XCTAssertEqual(
containerSize.width,
totalWidth,
@"The container's width is %.6f, the subviews take up %.6f",
containerSize.width,
totalWidth);
} }
- (void)testThatLayoutIsCorrectWhenWeSwapViewOrder - (void)testThatLayoutIsCorrectWhenWeSwapViewOrder {
{
const CGSize containerSize = CGSizeMake(300, 50); const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
@@ -333,32 +336,33 @@
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50))); XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
} }
- (void)testThatWeRespectIncludeInLayoutFlag - (void)testThatWeRespectIncludeInLayoutFlag {
{
const CGSize containerSize = CGSizeMake(300, 50); const CGSize containerSize = CGSizeMake(300, 50);
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)]; UIView* container = [[UIView alloc]
initWithFrame:CGRectMake(
0, 0, containerSize.width, containerSize.height)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
[container addSubview:subview3]; [container addSubview:subview3];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
for (UIView *subview in container.subviews) { for (UIView* subview in container.subviews) {
XCTAssertEqual(subview.bounds.size.width, 100); XCTAssertEqual(subview.bounds.size.width, 100);
} }
@@ -368,27 +372,27 @@
XCTAssertEqual(subview1.bounds.size.width, 150); XCTAssertEqual(subview1.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.width, 150); XCTAssertEqual(subview2.bounds.size.width, 150);
// We don't set the frame to zero, so, it should be set to what it was previously at. // We don't set the frame to zero, so, it should be set to what it was
// previously at.
XCTAssertEqual(subview3.bounds.size.width, 100); XCTAssertEqual(subview3.bounds.size.width, 100);
} }
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews - (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectZero];
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.isIncludedInLayout = NO; subview1.yoga.isIncludedInLayout = NO;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.isIncludedInLayout = NO; subview2.yoga.isIncludedInLayout = NO;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.isIncludedInLayout = YES; subview3.yoga.isIncludedInLayout = YES;
[container addSubview:subview3]; [container addSubview:subview3];
@@ -401,23 +405,22 @@
XCTAssertEqual(container.yoga.numberOfChildren, 2); XCTAssertEqual(container.yoga.numberOfChildren, 2);
} }
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond - (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
container.yoga.isEnabled = YES; container.yoga.isEnabled = YES;
container.yoga.flexDirection = YGFlexDirectionRow; container.yoga.flexDirection = YGFlexDirectionRow;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
[container addSubview:subview2]; [container addSubview:subview2];
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview3 = [[UIView alloc] initWithFrame:CGRectZero];
subview3.yoga.isEnabled = YES; subview3.yoga.isEnabled = YES;
subview3.yoga.flexGrow = 1; subview3.yoga.flexGrow = 1;
subview3.yoga.isIncludedInLayout = NO; subview3.yoga.isIncludedInLayout = NO;
@@ -437,13 +440,12 @@
XCTAssertEqual(subview3.bounds.size.width, 100); XCTAssertEqual(subview3.bounds.size.width, 100);
} }
- (void)testIsLeafFlag - (void)testIsLeafFlag {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
for (int i=0; i<10; i++) { for (int i = 0; i < 10; i++) {
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview = [[UIView alloc] initWithFrame:CGRectZero];
[view addSubview:subview]; [view addSubview:subview];
} }
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
@@ -452,99 +454,95 @@
view.yoga.width = YGPointValue(50); view.yoga.width = YGPointValue(50);
XCTAssertTrue(view.yoga.isLeaf); XCTAssertTrue(view.yoga.isLeaf);
UIView *const subview = view.subviews[0]; UIView* const subview = view.subviews[0];
subview.yoga.isEnabled = YES; subview.yoga.isEnabled = YES;
subview.yoga.width = YGPointValue(50); subview.yoga.width = YGPointValue(50);
XCTAssertFalse(view.yoga.isLeaf); XCTAssertFalse(view.yoga.isLeaf);
} }
- (void)testThatWeCorrectlyAttachNestedViews - (void)testThatWeCorrectlyAttachNestedViews {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)]; container.yoga.isEnabled = YES;
container.yoga.isEnabled = YES; container.yoga.flexDirection = YGFlexDirectionColumn;
container.yoga.flexDirection = YGFlexDirectionColumn;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
subview1.yoga.width = YGPointValue(100); subview1.yoga.width = YGPointValue(100);
subview1.yoga.flexGrow = 1; subview1.yoga.flexGrow = 1;
subview1.yoga.flexDirection = YGFlexDirectionColumn; subview1.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
subview2.yoga.width = YGPointValue(150); subview2.yoga.width = YGPointValue(150);
subview2.yoga.flexGrow = 1; subview2.yoga.flexGrow = 1;
subview2.yoga.flexDirection = YGFlexDirectionColumn; subview2.yoga.flexDirection = YGFlexDirectionColumn;
[container addSubview:subview2]; [container addSubview:subview2];
for (UIView *view in @[subview1, subview2]) { for (UIView* view in @[ subview1, subview2 ]) {
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* someView = [[UIView alloc] initWithFrame:CGRectZero];
someView.yoga.isEnabled = YES; someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1; someView.yoga.flexGrow = 1;
[view addSubview:someView]; [view addSubview:someView];
} }
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
// Add the same amount of new views, reapply layout. // Add the same amount of new views, reapply layout.
for (UIView *view in @[subview1, subview2]) { for (UIView* view in @[ subview1, subview2 ]) {
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; UIView* someView = [[UIView alloc] initWithFrame:CGRectZero];
someView.yoga.isEnabled = YES; someView.yoga.isEnabled = YES;
someView.yoga.flexGrow = 1; someView.yoga.flexGrow = 1;
[view addSubview:someView]; [view addSubview:someView];
} }
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
XCTAssertEqual(subview1.bounds.size.width, 100); XCTAssertEqual(subview1.bounds.size.width, 100);
XCTAssertEqual(subview1.bounds.size.height, 25); XCTAssertEqual(subview1.bounds.size.height, 25);
for (UIView *subview in subview1.subviews) { for (UIView* subview in subview1.subviews) {
const CGSize subviewSize = subview.bounds.size; const CGSize subviewSize = subview.bounds.size;
XCTAssertNotEqual(subviewSize.width, 0); XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0); XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height)); XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width)); XCTAssertFalse(isnan(subviewSize.width));
} }
XCTAssertEqual(subview2.bounds.size.width, 150); XCTAssertEqual(subview2.bounds.size.width, 150);
XCTAssertEqual(subview2.bounds.size.height, 25); XCTAssertEqual(subview2.bounds.size.height, 25);
for (UIView *subview in subview2.subviews) { for (UIView* subview in subview2.subviews) {
const CGSize subviewSize = subview.bounds.size; const CGSize subviewSize = subview.bounds.size;
XCTAssertNotEqual(subviewSize.width, 0); XCTAssertNotEqual(subviewSize.width, 0);
XCTAssertNotEqual(subviewSize.height, 0); XCTAssertNotEqual(subviewSize.height, 0);
XCTAssertFalse(isnan(subviewSize.height)); XCTAssertFalse(isnan(subviewSize.height));
XCTAssertFalse(isnan(subviewSize.width)); XCTAssertFalse(isnan(subviewSize.width));
} }
} }
- (void)testThatANonLeafNodeCanBecomeALeafNode - (void)testThatANonLeafNodeCanBecomeALeafNode {
{ UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)]; container.yoga.isEnabled = YES;
container.yoga.isEnabled = YES;
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview1 = [[UIView alloc] initWithFrame:CGRectZero];
subview1.yoga.isEnabled = YES; subview1.yoga.isEnabled = YES;
[container addSubview:subview1]; [container addSubview:subview1];
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; UIView* subview2 = [[UIView alloc] initWithFrame:CGRectZero];
subview2.yoga.isEnabled = YES; subview2.yoga.isEnabled = YES;
[subview1 addSubview:subview2]; [subview1 addSubview:subview2];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
[subview2 removeFromSuperview]; [subview2 removeFromSuperview];
[container.yoga applyLayoutPreservingOrigin:YES]; [container.yoga applyLayoutPreservingOrigin:YES];
} }
- (void)testPointPercent - (void)testPointPercent {
{
XCTAssertEqual(YGPointValue(1).value, 1); XCTAssertEqual(YGPointValue(1).value, 1);
XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint); XCTAssertEqual(YGPointValue(1).unit, YGUnitPoint);
XCTAssertEqual(YGPercentValue(2).value, 2); XCTAssertEqual(YGPercentValue(2).value, 2);
XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent); XCTAssertEqual(YGPercentValue(2).unit, YGUnitPercent);
} }
- (void)testPositionalPropertiesWork - (void)testPositionalPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.left = YGPointValue(1); view.yoga.left = YGPointValue(1);
XCTAssertEqual(view.yoga.left.value, 1); XCTAssertEqual(view.yoga.left.value, 1);
@@ -589,9 +587,8 @@
XCTAssertEqual(view.yoga.end.unit, YGUnitPercent); XCTAssertEqual(view.yoga.end.unit, YGUnitPercent);
} }
- (void)testMarginPropertiesWork - (void)testMarginPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.margin = YGPointValue(1); view.yoga.margin = YGPointValue(1);
XCTAssertEqual(view.yoga.margin.value, 1); XCTAssertEqual(view.yoga.margin.value, 1);
@@ -657,9 +654,8 @@
XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent); XCTAssertEqual(view.yoga.marginEnd.unit, YGUnitPercent);
} }
- (void)testPaddingPropertiesWork - (void)testPaddingPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.padding = YGPointValue(1); view.yoga.padding = YGPointValue(1);
XCTAssertEqual(view.yoga.padding.value, 1); XCTAssertEqual(view.yoga.padding.value, 1);
@@ -725,9 +721,8 @@
XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent); XCTAssertEqual(view.yoga.paddingEnd.unit, YGUnitPercent);
} }
- (void)testBorderWidthPropertiesWork - (void)testBorderWidthPropertiesWork {
{ UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.yoga.borderWidth = 1; view.yoga.borderWidth = 1;
XCTAssertEqual(view.yoga.borderWidth, 1); XCTAssertEqual(view.yoga.borderWidth, 1);

View File

@@ -11,45 +11,39 @@
@implementation ViewController @implementation ViewController
- (void)viewDidLoad - (void)viewDidLoad {
{ UIView* root = self.view;
UIView *root = self.view; root.backgroundColor = [UIColor redColor];
root.backgroundColor = [UIColor redColor]; root.yoga.isEnabled = YES;
root.yoga.isEnabled = YES; root.yoga.width = YGPointValue(self.view.bounds.size.width);
root.yoga.width = YGPointValue(self.view.bounds.size.width); root.yoga.height = YGPointValue(self.view.bounds.size.height);
root.yoga.height = YGPointValue(self.view.bounds.size.height); root.yoga.alignItems = YGAlignCenter;
root.yoga.alignItems = YGAlignCenter; root.yoga.justifyContent = YGJustifyCenter;
root.yoga.justifyContent = YGJustifyCenter;
UIView *child1 = [UIView new]; UIView* child1 = [UIView new];
child1.backgroundColor = [UIColor blueColor]; child1.backgroundColor = [UIColor blueColor];
child1.yoga.isEnabled = YES; child1.yoga.isEnabled = YES;
child1.yoga.width = YGPointValue(100); child1.yoga.width = YGPointValue(100);
child1.yoga.height = YGPointValue(100); child1.yoga.height = YGPointValue(100);
UIView *child2 = [UIView new]; UIView* child2 = [UIView new];
child2.backgroundColor = [UIColor greenColor]; child2.backgroundColor = [UIColor greenColor];
child2.frame = (CGRect) { child2.frame = (CGRect){.size = {
.size = { .width = 200,
.width = 200, .height = 100,
.height = 100, }};
}
};
UIView *child3 = [UIView new]; UIView* child3 = [UIView new];
child3.backgroundColor = [UIColor yellowColor]; child3.backgroundColor = [UIColor yellowColor];
child3.frame = (CGRect) { child3.frame = (CGRect){.size = {
.size = { .width = 100,
.width = 100, .height = 100,
.height = 100, }};
}
};
[child2 addSubview:child3]; [child2 addSubview:child3];
[root addSubview:child1]; [root addSubview:child1];
[root addSubview:child2]; [root addSubview:child2];
[root.yoga applyLayoutPreservingOrigin:NO]; [root.yoga applyLayoutPreservingOrigin:NO];
} }
@end @end

View File

@@ -3,10 +3,11 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "JAVA_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "JAVA_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource")
yoga_android_aar( yoga_android_aar(
name = "android", name = "android",
enable_relinker = True,
manifest_skeleton = "src/main/AndroidManifest.xml", manifest_skeleton = "src/main/AndroidManifest.xml",
visibility = [ visibility = [
"PUBLIC", "PUBLIC",
@@ -15,7 +16,7 @@ yoga_android_aar(
ANDROID_JAVA_TARGET, ANDROID_JAVA_TARGET,
ANDROID_RES_TARGET, ANDROID_RES_TARGET,
JAVA_TARGET, JAVA_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
], ],
) )

View File

@@ -9,11 +9,12 @@
static YGInteropLogger gManagedLogger; static YGInteropLogger gManagedLogger;
static int unmanagedLogger(const YGConfigRef config, static int unmanagedLogger(
const YGNodeRef node, const YGConfigRef config,
YGLogLevel level, const YGNodeRef node,
const char *format, YGLogLevel level,
va_list args) { const char* format,
va_list args) {
int result = 0; int result = 0;
if (gManagedLogger) { if (gManagedLogger) {
char message[8192]; char message[8192];

View File

@@ -11,10 +11,11 @@
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
typedef int (*YGInteropLogger)(const void *unmanagedConfigPtr, typedef int (*YGInteropLogger)(
const void *unmanagedNodePtr, const void* unmanagedConfigPtr,
YGLogLevel level, const void* unmanagedNodePtr,
const char *message); YGLogLevel level,
const char* message);
WIN_EXPORT YGConfigRef YGConfigGetDefault(); WIN_EXPORT YGConfigRef YGConfigGetDefault();

View File

@@ -8,7 +8,8 @@
// dllmain.cpp : Defines the entry point for the DLL application. // dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h" #include "stdafx.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { BOOL APIENTRY
DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) { switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:

View File

@@ -9,7 +9,8 @@
// Including SDKDDKVer.h defines the highest available Windows platform. // Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // If you wish to build your application for a previous Windows platform,
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. // include WinSDKVer.h and set the _WIN32_WINNT macro to the platform you wish
// to support before including SDKDDKVer.h.
#include <SDKDDKVer.h> #include <SDKDDKVer.h>

View File

@@ -150,3 +150,13 @@
<div style="flex: 1; margin-left:auto;"></div> <div style="flex: 1; margin-left:auto;"></div>
<div style="width: 50px; height: 50px;"></div> <div style="width: 50px; height: 50px;"></div>
</div> </div>
<div id="margin_top_auto_overflow_parent" style="flex-direction:column; height: 500px; width: 20px;">
<div style="height: 300px;"></div>
<div style="margin-top: auto; height: 300px;"></div>
</div>
<div id="margin_bottom_auto_overflow_parent" style="flex-direction:column; height: 500px; width: 20px;">
<div style="height: 300px;"></div>
<div style="margin-top: auto; height: 300px;"></div>
</div>

View File

@@ -3,11 +3,11 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "FBJNI_JAVA_TARGET", "FBJNI_TARGET", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_cxx_lib", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "YOGA_ROOTS", "yoga_cxx_lib", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test", "yoga_prebuilt_cxx_library")
CXX_LIBRARY_WHITELIST_FOR_TESTS = CXX_LIBRARY_WHITELIST + [ CXX_LIBRARY_WHITELIST_FOR_TESTS = CXX_LIBRARY_WHITELIST + [
yoga_cxx_lib("testutil:jni"), yoga_cxx_lib("testutil:jni"),
yoga_cxx_lib("testutil:testutil"), yoga_cxx_lib("testutil:testutil-jni"),
] ]
YOGA_JAVA_IMPLEMENTATION_FILES = [ YOGA_JAVA_IMPLEMENTATION_FILES = [
@@ -16,6 +16,18 @@ YOGA_JAVA_IMPLEMENTATION_FILES = [
"com/facebook/yoga/YogaNative.java", "com/facebook/yoga/YogaNative.java",
] ]
yoga_prebuilt_cxx_library(
name = "ndklog",
exported_platform_linker_flags = [
(
"^android.*",
["-llog"],
),
],
header_only = True,
visibility = YOGA_ROOTS,
)
yoga_cxx_library( yoga_cxx_library(
name = "jni", name = "jni",
srcs = glob(["jni/*.cpp"]), srcs = glob(["jni/*.cpp"]),
@@ -41,9 +53,9 @@ yoga_cxx_library(
soname = "libyoga.$(ext)", soname = "libyoga.$(ext)",
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
FBJNI_TARGET,
JNI_TARGET, JNI_TARGET,
yoga_dep(":yoga"), yoga_dep(":yoga-static"),
":ndklog",
], ],
) )
@@ -59,7 +71,7 @@ yoga_java_library(
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
JSR_305_TARGET, JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
], ],
) )
@@ -72,9 +84,8 @@ yoga_java_library(
deps = [ deps = [
":java-interface", ":java-interface",
":jni", ":jni",
FBJNI_JAVA_TARGET,
JSR_305_TARGET, JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
SOLOADER_TARGET, SOLOADER_TARGET,
], ],
) )
@@ -111,6 +122,5 @@ yoga_java_binary(
name = "yoga", name = "yoga",
deps = [ deps = [
":java", ":java",
FBJNI_JAVA_TARGET,
], ],
) )

View File

@@ -8,17 +8,13 @@ cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on) set(CMAKE_VERBOSE_MAKEFILE on)
# configure import libs # configure import libs
set(libfb_DIR ${CMAKE_SOURCE_DIR}/../lib/fb/src/main/cpp)
set(yogacore_DIR ${CMAKE_SOURCE_DIR}/..) set(yogacore_DIR ${CMAKE_SOURCE_DIR}/..)
set(build_DIR ${CMAKE_SOURCE_DIR}/build) set(build_DIR ${CMAKE_SOURCE_DIR}/build)
set(libfb_build_DIR ${build_DIR}/libfb/${ANDROID_ABI})
set(yogacore_build_DIR ${build_DIR}/yogacore/${ANDROID_ABI}) set(yogacore_build_DIR ${build_DIR}/yogacore/${ANDROID_ABI})
file(MAKE_DIRECTORY ${build_DIR}) file(MAKE_DIRECTORY ${build_DIR})
add_subdirectory(${libfb_DIR} ${libfb_build_DIR})
add_subdirectory(${yogacore_DIR} ${yogacore_build_DIR}) add_subdirectory(${yogacore_DIR} ${yogacore_build_DIR})
add_compile_options( add_compile_options(
@@ -33,10 +29,12 @@ add_compile_options(
file(GLOB jni_SRC file(GLOB jni_SRC
jni/*.cpp) jni/*.cpp)
file(GLOB yogajni_version_script
yogajni.version)
add_library(yoga SHARED ${jni_SRC}) add_library(yoga SHARED ${jni_SRC})
target_include_directories(yoga PRIVATE target_include_directories(yoga PRIVATE
${libfb_DIR}/include
${yogacore_DIR}) ${yogacore_DIR})
target_link_libraries(yoga -Wl,--gc-sections yogacore fb) target_link_libraries(yoga -Wl,--gc-sections,--version-script=${yogajni_version_script} yogacore)

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaAlign { public enum YogaAlign {
AUTO(0), AUTO(0),
FLEX_START(1), FLEX_START(1),

View File

@@ -7,14 +7,10 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public interface YogaBaselineFunction { public interface YogaBaselineFunction {
/** /**
* Return the baseline of the node in points. When no baseline function is set the baseline * Return the baseline of the node in points. When no baseline function is set the baseline
* default to the computed height of the node. * default to the computed height of the node.
*/ */
@DoNotStrip
float baseline(YogaNode node, float width, float height); float baseline(YogaNode node, float width, float height);
} }

View File

@@ -38,8 +38,4 @@ public abstract class YogaConfig {
public abstract YogaLogger getLogger(); public abstract YogaLogger getLogger();
abstract long getNativePointer(); abstract long getNativePointer();
public abstract void setUseVanillaJNI(boolean useVanillaJNI);
public abstract boolean useVanillaJNI();
} }

View File

@@ -11,8 +11,4 @@ public abstract class YogaConfigFactory {
public static YogaConfig create() { public static YogaConfig create() {
return new YogaConfigJNIFinalizer(); return new YogaConfigJNIFinalizer();
} }
public static YogaConfig create(boolean useVanillaJNI) {
return new YogaConfigJNIFinalizer(useVanillaJNI);
}
} }

View File

@@ -11,7 +11,6 @@ public abstract class YogaConfigJNIBase extends YogaConfig {
long mNativePointer; long mNativePointer;
private YogaLogger mLogger; private YogaLogger mLogger;
protected boolean useVanillaJNI = false;
private YogaConfigJNIBase(long nativePointer) { private YogaConfigJNIBase(long nativePointer) {
if (nativePointer == 0) { if (nativePointer == 0) {
@@ -21,40 +20,27 @@ public abstract class YogaConfigJNIBase extends YogaConfig {
} }
YogaConfigJNIBase() { YogaConfigJNIBase() {
this(YogaNative.jni_YGConfigNew()); this(YogaNative.jni_YGConfigNewJNI());
} }
YogaConfigJNIBase(boolean useVanillaJNI) { YogaConfigJNIBase(boolean useVanillaJNI) {
this(useVanillaJNI ? YogaNative.jni_YGConfigNewJNI() : YogaNative.jni_YGConfigNew()); this(YogaNative.jni_YGConfigNewJNI());
this.useVanillaJNI = useVanillaJNI;
} }
public void setExperimentalFeatureEnabled(YogaExperimentalFeature feature, boolean enabled) { public void setExperimentalFeatureEnabled(YogaExperimentalFeature feature, boolean enabled) {
if (useVanillaJNI) YogaNative.jni_YGConfigSetExperimentalFeatureEnabledJNI(mNativePointer, feature.intValue(), enabled);
YogaNative.jni_YGConfigSetExperimentalFeatureEnabledJNI(mNativePointer, feature.intValue(), enabled);
else
YogaNative.jni_YGConfigSetExperimentalFeatureEnabled(mNativePointer, feature.intValue(), enabled);
} }
public void setUseWebDefaults(boolean useWebDefaults) { public void setUseWebDefaults(boolean useWebDefaults) {
if (useVanillaJNI) YogaNative.jni_YGConfigSetUseWebDefaultsJNI(mNativePointer, useWebDefaults);
YogaNative.jni_YGConfigSetUseWebDefaultsJNI(mNativePointer, useWebDefaults);
else
YogaNative.jni_YGConfigSetUseWebDefaults(mNativePointer, useWebDefaults);
} }
public void setPrintTreeFlag(boolean enable) { public void setPrintTreeFlag(boolean enable) {
if (useVanillaJNI) YogaNative.jni_YGConfigSetPrintTreeFlagJNI(mNativePointer, enable);
YogaNative.jni_YGConfigSetPrintTreeFlagJNI(mNativePointer, enable);
else
YogaNative.jni_YGConfigSetPrintTreeFlag(mNativePointer, enable);
} }
public void setPointScaleFactor(float pixelsInPoint) { public void setPointScaleFactor(float pixelsInPoint) {
if (useVanillaJNI) YogaNative.jni_YGConfigSetPointScaleFactorJNI(mNativePointer, pixelsInPoint);
YogaNative.jni_YGConfigSetPointScaleFactorJNI(mNativePointer, pixelsInPoint);
else
YogaNative.jni_YGConfigSetPointScaleFactor(mNativePointer, pixelsInPoint);
} }
/** /**
@@ -63,10 +49,7 @@ public abstract class YogaConfigJNIBase extends YogaConfig {
* Because this was such a long-standing bug we must allow legacy users to switch back to this behaviour. * Because this was such a long-standing bug we must allow legacy users to switch back to this behaviour.
*/ */
public void setUseLegacyStretchBehaviour(boolean useLegacyStretchBehaviour) { public void setUseLegacyStretchBehaviour(boolean useLegacyStretchBehaviour) {
if (useVanillaJNI) YogaNative.jni_YGConfigSetUseLegacyStretchBehaviourJNI(mNativePointer, useLegacyStretchBehaviour);
YogaNative.jni_YGConfigSetUseLegacyStretchBehaviourJNI(mNativePointer, useLegacyStretchBehaviour);
else
YogaNative.jni_YGConfigSetUseLegacyStretchBehaviour(mNativePointer, useLegacyStretchBehaviour);
} }
/** /**
@@ -76,20 +59,13 @@ public abstract class YogaConfigJNIBase extends YogaConfig {
*/ */
public void setShouldDiffLayoutWithoutLegacyStretchBehaviour( public void setShouldDiffLayoutWithoutLegacyStretchBehaviour(
boolean shouldDiffLayoutWithoutLegacyStretchBehaviour) { boolean shouldDiffLayoutWithoutLegacyStretchBehaviour) {
if (useVanillaJNI)
YogaNative.jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviourJNI( YogaNative.jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviourJNI(
mNativePointer, shouldDiffLayoutWithoutLegacyStretchBehaviour); mNativePointer, shouldDiffLayoutWithoutLegacyStretchBehaviour);
else
YogaNative.jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(
mNativePointer, shouldDiffLayoutWithoutLegacyStretchBehaviour);
} }
public void setLogger(YogaLogger logger) { public void setLogger(YogaLogger logger) {
mLogger = logger; mLogger = logger;
if (useVanillaJNI) YogaNative.jni_YGConfigSetLoggerJNI(mNativePointer, logger);
YogaNative.jni_YGConfigSetLoggerJNI(mNativePointer, logger);
else
YogaNative.jni_YGConfigSetLogger(mNativePointer, logger);
} }
public YogaLogger getLogger() { public YogaLogger getLogger() {
@@ -99,14 +75,4 @@ public abstract class YogaConfigJNIBase extends YogaConfig {
long getNativePointer() { long getNativePointer() {
return mNativePointer; return mNativePointer;
} }
@Override
public void setUseVanillaJNI(boolean useVanillaJNI) {
this.useVanillaJNI = useVanillaJNI;
}
@Override
public boolean useVanillaJNI() {
return this.useVanillaJNI;
}
} }

View File

@@ -12,10 +12,6 @@ public class YogaConfigJNIFinalizer extends YogaConfigJNIBase {
super(); super();
} }
public YogaConfigJNIFinalizer(boolean useVanillaJNI) {
super(useVanillaJNI);
}
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
try { try {
@@ -29,10 +25,7 @@ public class YogaConfigJNIFinalizer extends YogaConfigJNIBase {
if (mNativePointer != 0) { if (mNativePointer != 0) {
long nativePointer = mNativePointer; long nativePointer = mNativePointer;
mNativePointer = 0; mNativePointer = 0;
if (useVanillaJNI) YogaNative.jni_YGConfigFreeJNI(nativePointer);
YogaNative.jni_YGConfigFreeJNI(nativePointer);
else
YogaNative.jni_YGConfigFree(nativePointer);
} }
} }
} }

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDimension { public enum YogaDimension {
WIDTH(0), WIDTH(0),
HEIGHT(1); HEIGHT(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDirection { public enum YogaDirection {
INHERIT(0), INHERIT(0),
LTR(1), LTR(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaDisplay { public enum YogaDisplay {
FLEX(0), FLEX(0),
NONE(1); NONE(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaEdge { public enum YogaEdge {
LEFT(0), LEFT(0),
TOP(1), TOP(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaExperimentalFeature { public enum YogaExperimentalFeature {
WEB_FLEX_BASIS(0); WEB_FLEX_BASIS(0);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaFlexDirection { public enum YogaFlexDirection {
COLUMN(0), COLUMN(0),
COLUMN_REVERSE(1), COLUMN_REVERSE(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaJustify { public enum YogaJustify {
FLEX_START(0), FLEX_START(0),
CENTER(1), CENTER(1),

View File

@@ -28,6 +28,7 @@ public enum YogaLogLevel {
return mIntValue; return mIntValue;
} }
@DoNotStrip
public static YogaLogLevel fromInt(int value) { public static YogaLogLevel fromInt(int value) {
switch (value) { switch (value) {
case 0: return ERROR; case 0: return ERROR;

View File

@@ -7,14 +7,10 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public interface YogaMeasureFunction { public interface YogaMeasureFunction {
/** /**
* Return a value created by YogaMeasureOutput.make(width, height); * Return a value created by YogaMeasureOutput.make(width, height);
*/ */
@DoNotStrip
long measure( long measure(
YogaNode node, YogaNode node,
float width, float width,

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaMeasureMode { public enum YogaMeasureMode {
UNDEFINED(0), UNDEFINED(0),
EXACTLY(1), EXACTLY(1),

View File

@@ -16,104 +16,6 @@ public class YogaNative {
SoLoader.loadLibrary("yoga"); SoLoader.loadLibrary("yoga");
} }
// YGConfig related
static native long jni_YGConfigNew();
static native void jni_YGConfigFree(long nativePointer);
static native void jni_YGConfigSetExperimentalFeatureEnabled(long nativePointer, int feature, boolean enabled);
static native void jni_YGConfigSetUseWebDefaults(long nativePointer, boolean useWebDefaults);
static native void jni_YGConfigSetPrintTreeFlag(long nativePointer, boolean enable);
static native void jni_YGConfigSetPointScaleFactor(long nativePointer, float pixelsInPoint);
static native void jni_YGConfigSetUseLegacyStretchBehaviour(long nativePointer, boolean useLegacyStretchBehaviour);
static native void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(long nativePointer, boolean shouldDiffLayoutWithoutLegacyStretchBehaviour);
static native void jni_YGConfigSetLogger(long nativePointer, Object logger);
// YGNode related
static native long jni_YGNodeNew();
static native long jni_YGNodeNewWithConfig(long configPointer);
static native void jni_YGNodeFree(long nativePointer);
static native void jni_YGNodeReset(long nativePointer);
static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline);
static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer);
static native void jni_YGNodeClearChildren(long nativePointer);
static native void jni_YGNodeRemoveChild(long nativePointer, long childPointer);
static native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height, long[] nativePointers, YogaNodeJNIBase[] nodes);
static native void jni_YGNodeMarkDirty(long nativePointer);
static native void jni_YGNodeMarkDirtyAndPropogateToDescendants(long nativePointer);
static native boolean jni_YGNodeIsDirty(long nativePointer);
static native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer);
static native int jni_YGNodeStyleGetDirection(long nativePointer);
static native void jni_YGNodeStyleSetDirection(long nativePointer, int direction);
static native int jni_YGNodeStyleGetFlexDirection(long nativePointer);
static native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection);
static native int jni_YGNodeStyleGetJustifyContent(long nativePointer);
static native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent);
static native int jni_YGNodeStyleGetAlignItems(long nativePointer);
static native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems);
static native int jni_YGNodeStyleGetAlignSelf(long nativePointer);
static native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf);
static native int jni_YGNodeStyleGetAlignContent(long nativePointer);
static native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent);
static native int jni_YGNodeStyleGetPositionType(long nativePointer);
static native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType);
static native int jni_YGNodeStyleGetFlexWrap(long nativePointer);
static native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType);
static native int jni_YGNodeStyleGetOverflow(long nativePointer);
static native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow);
static native int jni_YGNodeStyleGetDisplay(long nativePointer);
static native void jni_YGNodeStyleSetDisplay(long nativePointer, int display);
static native float jni_YGNodeStyleGetFlex(long nativePointer);
static native void jni_YGNodeStyleSetFlex(long nativePointer, float flex);
static native float jni_YGNodeStyleGetFlexGrow(long nativePointer);
static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow);
static native float jni_YGNodeStyleGetFlexShrink(long nativePointer);
static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink);
static native long jni_YGNodeStyleGetFlexBasis(long nativePointer);
static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis);
static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer);
static native long jni_YGNodeStyleGetMargin(long nativePointer, int edge);
static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin);
static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent);
static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge);
static native long jni_YGNodeStyleGetPadding(long nativePointer, int edge);
static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding);
static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent);
static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge);
static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border);
static native long jni_YGNodeStyleGetPosition(long nativePointer, int edge);
static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position);
static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent);
static native long jni_YGNodeStyleGetWidth(long nativePointer);
static native void jni_YGNodeStyleSetWidth(long nativePointer, float width);
static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetWidthAuto(long nativePointer);
static native long jni_YGNodeStyleGetHeight(long nativePointer);
static native void jni_YGNodeStyleSetHeight(long nativePointer, float height);
static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetHeightAuto(long nativePointer);
static native long jni_YGNodeStyleGetMinWidth(long nativePointer);
static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth);
static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent);
static native long jni_YGNodeStyleGetMinHeight(long nativePointer);
static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight);
static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent);
static native long jni_YGNodeStyleGetMaxWidth(long nativePointer);
static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth);
static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent);
static native long jni_YGNodeStyleGetMaxHeight(long nativePointer);
static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight);
static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent);
static native float jni_YGNodeStyleGetAspectRatio(long nativePointer);
static native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio);
static native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc);
static native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc);
static native void jni_YGNodePrint(long nativePointer);
static native void jni_YGNodeSetStyleInputs(long nativePointer, float[] styleInputsArray, int size);
static native long jni_YGNodeClone(long nativePointer);
// JNI methods that use Vanilla JNI // JNI methods that use Vanilla JNI
// YGConfig related // YGConfig related
static native long jni_YGConfigNewJNI(); static native long jni_YGConfigNewJNI();
@@ -132,6 +34,7 @@ public class YogaNative {
static native void jni_YGNodeFreeJNI(long nativePointer); static native void jni_YGNodeFreeJNI(long nativePointer);
static native void jni_YGNodeResetJNI(long nativePointer); static native void jni_YGNodeResetJNI(long nativePointer);
static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index); static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSwapChildJNI(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline); static native void jni_YGNodeSetIsReferenceBaselineJNI(long nativePointer, boolean isReferenceBaseline);
static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer); static native boolean jni_YGNodeIsReferenceBaselineJNI(long nativePointer);
static native void jni_YGNodeClearChildrenJNI(long nativePointer); static native void jni_YGNodeClearChildrenJNI(long nativePointer);

View File

@@ -214,4 +214,6 @@ public abstract class YogaNode {
public abstract void print(); public abstract void print();
public abstract YogaNode cloneWithoutChildren(); public abstract YogaNode cloneWithoutChildren();
public abstract YogaNode cloneWithChildren();
} }

View File

@@ -12,10 +12,6 @@ public abstract class YogaNodeFactory {
return new YogaNodeJNIFinalizer(); return new YogaNodeJNIFinalizer();
} }
public static YogaNode create(boolean useVanillaJNI) {
return new YogaNodeJNIFinalizer(useVanillaJNI);
}
public static YogaNode create(YogaConfig config) { public static YogaNode create(YogaConfig config) {
return new YogaNodeJNIFinalizer(config); return new YogaNodeJNIFinalizer(config);
} }

View File

@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
@DoNotStrip @DoNotStrip
public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
/* Those flags needs be in sync with YGJNI.cpp */ /* Those flags needs be in sync with YGJNI.h */
private static final byte MARGIN = 1; private static final byte MARGIN = 1;
private static final byte PADDING = 2; private static final byte PADDING = 2;
private static final byte BORDER = 4; private static final byte BORDER = 4;
@@ -39,16 +39,12 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
protected long mNativePointer; protected long mNativePointer;
@Nullable private Object mData; @Nullable private Object mData;
@DoNotStrip @DoNotStrip private @Nullable float[] arr = null;
private @Nullable float[] arr = null;
@DoNotStrip @DoNotStrip private int mLayoutDirection = 0;
private int mLayoutDirection = 0;
private boolean mHasNewLayout = true; private boolean mHasNewLayout = true;
protected boolean useVanillaJNI = false;
private YogaNodeJNIBase(long nativePointer) { private YogaNodeJNIBase(long nativePointer) {
if (nativePointer == 0) { if (nativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory"); throw new IllegalStateException("Failed to allocate native memory");
@@ -57,17 +53,11 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
YogaNodeJNIBase() { YogaNodeJNIBase() {
this(YogaNative.jni_YGNodeNew()); this(YogaNative.jni_YGNodeNewJNI());
}
YogaNodeJNIBase(boolean useVanillaJNI) {
this(useVanillaJNI ? YogaNative.jni_YGNodeNewJNI() : YogaNative.jni_YGNodeNew());
this.useVanillaJNI = useVanillaJNI;
} }
YogaNodeJNIBase(YogaConfig config) { YogaNodeJNIBase(YogaConfig config) {
this(config.useVanillaJNI() ? YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase)config).mNativePointer) : YogaNative.jni_YGNodeNewWithConfig(((YogaConfigJNIBase)config).mNativePointer)); this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase) config).mNativePointer));
this.useVanillaJNI = config.useVanillaJNI();
} }
public void reset() { public void reset() {
@@ -78,10 +68,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
mHasNewLayout = true; mHasNewLayout = true;
mLayoutDirection = 0; mLayoutDirection = 0;
if (useVanillaJNI) YogaNative.jni_YGNodeResetJNI(mNativePointer);
YogaNative.jni_YGNodeResetJNI(mNativePointer);
else
YogaNative.jni_YGNodeReset(mNativePointer);
} }
public int getChildCount() { public int getChildCount() {
@@ -106,28 +93,48 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
mChildren.add(i, child); mChildren.add(i, child);
child.mOwner = this; child.mOwner = this;
if (useVanillaJNI) YogaNative.jni_YGNodeInsertChildJNI(mNativePointer, child.mNativePointer, i);
YogaNative.jni_YGNodeInsertChildJNI(mNativePointer, child.mNativePointer, i);
else
YogaNative.jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i);
} }
public void setIsReferenceBaseline(boolean isReferenceBaseline) { public void setIsReferenceBaseline(boolean isReferenceBaseline) {
if (useVanillaJNI) YogaNative.jni_YGNodeSetIsReferenceBaselineJNI(mNativePointer, isReferenceBaseline);
YogaNative.jni_YGNodeSetIsReferenceBaselineJNI(mNativePointer, isReferenceBaseline);
else
YogaNative.jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline);
} }
public boolean isReferenceBaseline() { public boolean isReferenceBaseline() {
return useVanillaJNI ? YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer) : YogaNative.jni_YGNodeIsReferenceBaseline(mNativePointer); return YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer);
}
public void swapChildAt(YogaNode newChild, int position) {
YogaNodeJNIBase child = (YogaNodeJNIBase) newChild;
mChildren.remove(position);
mChildren.add(position, child);
child.mOwner = this;
YogaNative.jni_YGNodeSwapChildJNI(mNativePointer, child.mNativePointer, position);
}
@Override
public YogaNodeJNIBase cloneWithChildren() {
try {
YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone();
long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer);
clonedYogaNode.mOwner = null;
clonedYogaNode.mNativePointer = clonedNativePointer;
for (int i = 0; i < clonedYogaNode.getChildCount(); i++) {
clonedYogaNode.swapChildAt(clonedYogaNode.getChildAt(i).cloneWithChildren(), i);
}
return clonedYogaNode;
} catch (CloneNotSupportedException ex) {
// This class implements Cloneable, this should not happen
throw new RuntimeException(ex);
}
} }
@Override @Override
public YogaNodeJNIBase cloneWithoutChildren() { public YogaNodeJNIBase cloneWithoutChildren() {
try { try {
YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone(); YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone();
long clonedNativePointer = useVanillaJNI ? YogaNative.jni_YGNodeCloneJNI(mNativePointer) : YogaNative.jni_YGNodeClone(mNativePointer);; long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer);
clonedYogaNode.mOwner = null; clonedYogaNode.mOwner = null;
clonedYogaNode.mNativePointer = clonedNativePointer; clonedYogaNode.mNativePointer = clonedNativePointer;
clonedYogaNode.clearChildren(); clonedYogaNode.clearChildren();
@@ -140,10 +147,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
private void clearChildren() { private void clearChildren() {
mChildren = null; mChildren = null;
if (useVanillaJNI) YogaNative.jni_YGNodeClearChildrenJNI(mNativePointer);
YogaNative.jni_YGNodeClearChildrenJNI(mNativePointer);
else
YogaNative.jni_YGNodeClearChildren(mNativePointer);
} }
public YogaNodeJNIBase removeChildAt(int i) { public YogaNodeJNIBase removeChildAt(int i) {
@@ -153,20 +157,16 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
final YogaNodeJNIBase child = mChildren.remove(i); final YogaNodeJNIBase child = mChildren.remove(i);
child.mOwner = null; child.mOwner = null;
if (useVanillaJNI) YogaNative.jni_YGNodeRemoveChildJNI(mNativePointer, child.mNativePointer);
YogaNative.jni_YGNodeRemoveChildJNI(mNativePointer, child.mNativePointer);
else
YogaNative.jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer);
return child; return child;
} }
/** /**
* @returns the {@link YogaNode} that owns this {@link YogaNode}. * The owner is used to identify the YogaTree that a {@link YogaNode} belongs to. This method will
* The owner is used to identify the YogaTree that a {@link YogaNode} belongs * return the parent of the {@link YogaNode} when the {@link YogaNode} only belongs to one
* to. * YogaTree or null when the {@link YogaNode} is shared between two or more YogaTrees.
* This method will return the parent of the {@link YogaNode} when the *
* {@link YogaNode} only belongs to one YogaTree or null when the * @return the {@link YogaNode} that owns this {@link YogaNode}.
* {@link YogaNode} is shared between two or more YogaTrees.
*/ */
@Nullable @Nullable
public YogaNodeJNIBase getOwner() { public YogaNodeJNIBase getOwner() {
@@ -191,7 +191,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
ArrayList<YogaNodeJNIBase> n = new ArrayList<>(); ArrayList<YogaNodeJNIBase> n = new ArrayList<>();
n.add(this); n.add(this);
for (int i = 0; i < n.size(); ++i) { for (int i = 0; i < n.size(); ++i) {
List<YogaNodeJNIBase> children = n.get(i).mChildren; List<YogaNodeJNIBase> children = n.get(i).mChildren;
if (children != null) { if (children != null) {
n.addAll(children); n.addAll(children);
} }
@@ -203,418 +203,285 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
nativePointers[i] = nodes[i].mNativePointer; nativePointers[i] = nodes[i].mNativePointer;
} }
if (useVanillaJNI) YogaNative.jni_YGNodeCalculateLayoutJNI(mNativePointer, width, height, nativePointers, nodes);
YogaNative.jni_YGNodeCalculateLayoutJNI(mNativePointer, width, height, nativePointers, nodes);
else
YogaNative.jni_YGNodeCalculateLayout(mNativePointer, width, height, nativePointers, nodes);
} }
public void dirty() { public void dirty() {
if (useVanillaJNI) YogaNative.jni_YGNodeMarkDirtyJNI(mNativePointer);
YogaNative.jni_YGNodeMarkDirtyJNI(mNativePointer);
else
YogaNative.jni_YGNodeMarkDirty(mNativePointer);
} }
public void dirtyAllDescendants() { public void dirtyAllDescendants() {
if (useVanillaJNI) YogaNative.jni_YGNodeMarkDirtyAndPropogateToDescendantsJNI(mNativePointer);
YogaNative.jni_YGNodeMarkDirtyAndPropogateToDescendantsJNI(mNativePointer);
else
YogaNative.jni_YGNodeMarkDirtyAndPropogateToDescendants(mNativePointer);
} }
public boolean isDirty() { public boolean isDirty() {
return useVanillaJNI ? YogaNative.jni_YGNodeIsDirtyJNI(mNativePointer) : YogaNative.jni_YGNodeIsDirty(mNativePointer); return YogaNative.jni_YGNodeIsDirtyJNI(mNativePointer);
} }
@Override @Override
public void copyStyle(YogaNode srcNode) { public void copyStyle(YogaNode srcNode) {
if (useVanillaJNI) YogaNative.jni_YGNodeCopyStyleJNI(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer);
YogaNative.jni_YGNodeCopyStyleJNI(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer);
else
YogaNative.jni_YGNodeCopyStyle(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer);
} }
public YogaDirection getStyleDirection() { public YogaDirection getStyleDirection() {
return YogaDirection.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetDirectionJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetDirection(mNativePointer)); return YogaDirection.fromInt(YogaNative.jni_YGNodeStyleGetDirectionJNI(mNativePointer));
} }
public void setDirection(YogaDirection direction) { public void setDirection(YogaDirection direction) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetDirectionJNI(mNativePointer, direction.intValue());
YogaNative.jni_YGNodeStyleSetDirectionJNI(mNativePointer, direction.intValue());
else
YogaNative.jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue());
} }
public YogaFlexDirection getFlexDirection() { public YogaFlexDirection getFlexDirection() {
return YogaFlexDirection.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexDirectionJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlexDirection(mNativePointer)); return YogaFlexDirection.fromInt(YogaNative.jni_YGNodeStyleGetFlexDirectionJNI(mNativePointer));
} }
public void setFlexDirection(YogaFlexDirection flexDirection) { public void setFlexDirection(YogaFlexDirection flexDirection) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexDirectionJNI(mNativePointer, flexDirection.intValue());
YogaNative.jni_YGNodeStyleSetFlexDirectionJNI(mNativePointer, flexDirection.intValue());
else
YogaNative.jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue());
} }
public YogaJustify getJustifyContent() { public YogaJustify getJustifyContent() {
return YogaJustify.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetJustifyContentJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetJustifyContent(mNativePointer)); return YogaJustify.fromInt(YogaNative.jni_YGNodeStyleGetJustifyContentJNI(mNativePointer));
} }
public void setJustifyContent(YogaJustify justifyContent) { public void setJustifyContent(YogaJustify justifyContent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetJustifyContentJNI(mNativePointer, justifyContent.intValue());
YogaNative.jni_YGNodeStyleSetJustifyContentJNI(mNativePointer, justifyContent.intValue());
else
YogaNative.jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue());
} }
public YogaAlign getAlignItems() { public YogaAlign getAlignItems() {
return YogaAlign.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetAlignItemsJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetAlignItems(mNativePointer)); return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignItemsJNI(mNativePointer));
} }
public void setAlignItems(YogaAlign alignItems) { public void setAlignItems(YogaAlign alignItems) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetAlignItemsJNI(mNativePointer, alignItems.intValue());
YogaNative.jni_YGNodeStyleSetAlignItemsJNI(mNativePointer, alignItems.intValue());
else
YogaNative.jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue());
} }
public YogaAlign getAlignSelf() { public YogaAlign getAlignSelf() {
return YogaAlign.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetAlignSelfJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetAlignSelf(mNativePointer)); return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignSelfJNI(mNativePointer));
} }
public void setAlignSelf(YogaAlign alignSelf) { public void setAlignSelf(YogaAlign alignSelf) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetAlignSelfJNI(mNativePointer, alignSelf.intValue());
YogaNative.jni_YGNodeStyleSetAlignSelfJNI(mNativePointer, alignSelf.intValue());
else
YogaNative.jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue());
} }
public YogaAlign getAlignContent() { public YogaAlign getAlignContent() {
return YogaAlign.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetAlignContentJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetAlignContent(mNativePointer)); return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignContentJNI(mNativePointer));
} }
public void setAlignContent(YogaAlign alignContent) { public void setAlignContent(YogaAlign alignContent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetAlignContentJNI(mNativePointer, alignContent.intValue());
YogaNative.jni_YGNodeStyleSetAlignContentJNI(mNativePointer, alignContent.intValue());
else
YogaNative.jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue());
} }
public YogaPositionType getPositionType() { public YogaPositionType getPositionType() {
return YogaPositionType.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetPositionTypeJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetPositionType(mNativePointer)); return YogaPositionType.fromInt(YogaNative.jni_YGNodeStyleGetPositionTypeJNI(mNativePointer));
} }
public void setPositionType(YogaPositionType positionType) { public void setPositionType(YogaPositionType positionType) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetPositionTypeJNI(mNativePointer, positionType.intValue());
YogaNative.jni_YGNodeStyleSetPositionTypeJNI(mNativePointer, positionType.intValue());
else
YogaNative.jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue());
} }
public YogaWrap getWrap() { public YogaWrap getWrap() {
return YogaWrap.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexWrapJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlexWrap(mNativePointer)); return YogaWrap.fromInt(YogaNative.jni_YGNodeStyleGetFlexWrapJNI(mNativePointer));
} }
public void setWrap(YogaWrap flexWrap) { public void setWrap(YogaWrap flexWrap) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexWrapJNI(mNativePointer, flexWrap.intValue());
YogaNative.jni_YGNodeStyleSetFlexWrapJNI(mNativePointer, flexWrap.intValue());
else
YogaNative.jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue());
} }
public YogaOverflow getOverflow() { public YogaOverflow getOverflow() {
return YogaOverflow.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetOverflowJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetOverflow(mNativePointer)); return YogaOverflow.fromInt(YogaNative.jni_YGNodeStyleGetOverflowJNI(mNativePointer));
} }
public void setOverflow(YogaOverflow overflow) { public void setOverflow(YogaOverflow overflow) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetOverflowJNI(mNativePointer, overflow.intValue());
YogaNative.jni_YGNodeStyleSetOverflowJNI(mNativePointer, overflow.intValue());
else
YogaNative.jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue());
} }
public YogaDisplay getDisplay() { public YogaDisplay getDisplay() {
return YogaDisplay.fromInt(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetDisplayJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetDisplay(mNativePointer)); return YogaDisplay.fromInt(YogaNative.jni_YGNodeStyleGetDisplayJNI(mNativePointer));
} }
public void setDisplay(YogaDisplay display) { public void setDisplay(YogaDisplay display) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetDisplayJNI(mNativePointer, display.intValue());
YogaNative.jni_YGNodeStyleSetDisplayJNI(mNativePointer, display.intValue());
else
YogaNative.jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue());
} }
public float getFlex() { public float getFlex() {
return useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlex(mNativePointer); return YogaNative.jni_YGNodeStyleGetFlexJNI(mNativePointer);
} }
public void setFlex(float flex) { public void setFlex(float flex) {
if (useVanillaJNI) { YogaNative.jni_YGNodeStyleSetFlexJNI(mNativePointer, flex);
YogaNative.jni_YGNodeStyleSetFlexJNI(mNativePointer, flex);
} else {
YogaNative.jni_YGNodeStyleSetFlex(mNativePointer, flex);
}
} }
public float getFlexGrow() { public float getFlexGrow() {
return useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexGrowJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlexGrow(mNativePointer); return YogaNative.jni_YGNodeStyleGetFlexGrowJNI(mNativePointer);
} }
public void setFlexGrow(float flexGrow) { public void setFlexGrow(float flexGrow) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexGrowJNI(mNativePointer, flexGrow);
YogaNative.jni_YGNodeStyleSetFlexGrowJNI(mNativePointer, flexGrow);
else
YogaNative.jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow);
} }
public float getFlexShrink() { public float getFlexShrink() {
return useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexShrinkJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlexShrink(mNativePointer); return YogaNative.jni_YGNodeStyleGetFlexShrinkJNI(mNativePointer);
} }
public void setFlexShrink(float flexShrink) { public void setFlexShrink(float flexShrink) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexShrinkJNI(mNativePointer, flexShrink);
YogaNative.jni_YGNodeStyleSetFlexShrinkJNI(mNativePointer, flexShrink);
else
YogaNative.jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink);
} }
public YogaValue getFlexBasis() { public YogaValue getFlexBasis() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetFlexBasisJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetFlexBasis(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetFlexBasisJNI(mNativePointer));
} }
public void setFlexBasis(float flexBasis) { public void setFlexBasis(float flexBasis) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexBasisJNI(mNativePointer, flexBasis);
YogaNative.jni_YGNodeStyleSetFlexBasisJNI(mNativePointer, flexBasis);
else
YogaNative.jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis);
} }
public void setFlexBasisPercent(float percent) { public void setFlexBasisPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexBasisPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetFlexBasisPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent);
} }
public void setFlexBasisAuto() { public void setFlexBasisAuto() {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetFlexBasisAutoJNI(mNativePointer);
YogaNative.jni_YGNodeStyleSetFlexBasisAutoJNI(mNativePointer);
else
YogaNative.jni_YGNodeStyleSetFlexBasisAuto(mNativePointer);
} }
public YogaValue getMargin(YogaEdge edge) { public YogaValue getMargin(YogaEdge edge) {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetMarginJNI(mNativePointer, edge.intValue()) : YogaNative.jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue())); return valueFromLong(YogaNative.jni_YGNodeStyleGetMarginJNI(mNativePointer, edge.intValue()));
} }
public void setMargin(YogaEdge edge, float margin) { public void setMargin(YogaEdge edge, float margin) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMarginJNI(mNativePointer, edge.intValue(), margin);
YogaNative.jni_YGNodeStyleSetMarginJNI(mNativePointer, edge.intValue(), margin);
else
YogaNative.jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin);
} }
public void setMarginPercent(YogaEdge edge, float percent) { public void setMarginPercent(YogaEdge edge, float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMarginPercentJNI(mNativePointer, edge.intValue(), percent);
YogaNative.jni_YGNodeStyleSetMarginPercentJNI(mNativePointer, edge.intValue(), percent);
else
YogaNative.jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent);
} }
public void setMarginAuto(YogaEdge edge) { public void setMarginAuto(YogaEdge edge) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMarginAutoJNI(mNativePointer, edge.intValue());
YogaNative.jni_YGNodeStyleSetMarginAutoJNI(mNativePointer, edge.intValue());
else
YogaNative.jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue());
} }
public YogaValue getPadding(YogaEdge edge) { public YogaValue getPadding(YogaEdge edge) {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetPaddingJNI(mNativePointer, edge.intValue()) : YogaNative.jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue())); return valueFromLong(YogaNative.jni_YGNodeStyleGetPaddingJNI(mNativePointer, edge.intValue()));
} }
public void setPadding(YogaEdge edge, float padding) { public void setPadding(YogaEdge edge, float padding) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetPaddingJNI(mNativePointer, edge.intValue(), padding);
YogaNative.jni_YGNodeStyleSetPaddingJNI(mNativePointer, edge.intValue(), padding);
else
YogaNative.jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding);
} }
public void setPaddingPercent(YogaEdge edge, float percent) { public void setPaddingPercent(YogaEdge edge, float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetPaddingPercentJNI(mNativePointer, edge.intValue(), percent);
YogaNative.jni_YGNodeStyleSetPaddingPercentJNI(mNativePointer, edge.intValue(), percent);
else
YogaNative.jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent);
} }
public float getBorder(YogaEdge edge) { public float getBorder(YogaEdge edge) {
return useVanillaJNI ? YogaNative.jni_YGNodeStyleGetBorderJNI(mNativePointer, edge.intValue()) : YogaNative.jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); return YogaNative.jni_YGNodeStyleGetBorderJNI(mNativePointer, edge.intValue());
} }
public void setBorder(YogaEdge edge, float border) { public void setBorder(YogaEdge edge, float border) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetBorderJNI(mNativePointer, edge.intValue(), border);
YogaNative.jni_YGNodeStyleSetBorderJNI(mNativePointer, edge.intValue(), border);
else
YogaNative.jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border);
} }
public YogaValue getPosition(YogaEdge edge) { public YogaValue getPosition(YogaEdge edge) {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetPositionJNI(mNativePointer, edge.intValue()) : YogaNative.jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue())); return valueFromLong(YogaNative.jni_YGNodeStyleGetPositionJNI(mNativePointer, edge.intValue()));
} }
public void setPosition(YogaEdge edge, float position) { public void setPosition(YogaEdge edge, float position) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetPositionJNI(mNativePointer, edge.intValue(), position);
YogaNative.jni_YGNodeStyleSetPositionJNI(mNativePointer, edge.intValue(), position);
else
YogaNative.jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position);
} }
public void setPositionPercent(YogaEdge edge, float percent) { public void setPositionPercent(YogaEdge edge, float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetPositionPercentJNI(mNativePointer, edge.intValue(), percent);
YogaNative.jni_YGNodeStyleSetPositionPercentJNI(mNativePointer, edge.intValue(), percent);
else
YogaNative.jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent);
} }
public YogaValue getWidth() { public YogaValue getWidth() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetWidthJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetWidth(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetWidthJNI(mNativePointer));
} }
public void setWidth(float width) { public void setWidth(float width) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetWidthJNI(mNativePointer, width);
YogaNative.jni_YGNodeStyleSetWidthJNI(mNativePointer, width);
else
YogaNative.jni_YGNodeStyleSetWidth(mNativePointer, width);
} }
public void setWidthPercent(float percent) { public void setWidthPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetWidthPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetWidthPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetWidthPercent(mNativePointer, percent);
} }
public void setWidthAuto() { public void setWidthAuto() {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetWidthAutoJNI(mNativePointer);
YogaNative.jni_YGNodeStyleSetWidthAutoJNI(mNativePointer);
else
YogaNative.jni_YGNodeStyleSetWidthAuto(mNativePointer);
} }
public YogaValue getHeight() { public YogaValue getHeight() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetHeightJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetHeight(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetHeightJNI(mNativePointer));
} }
public void setHeight(float height) { public void setHeight(float height) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetHeightJNI(mNativePointer, height);
YogaNative.jni_YGNodeStyleSetHeightJNI(mNativePointer, height);
else
YogaNative.jni_YGNodeStyleSetHeight(mNativePointer, height);
} }
public void setHeightPercent(float percent) { public void setHeightPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetHeightPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetHeightPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetHeightPercent(mNativePointer, percent);
} }
public void setHeightAuto() { public void setHeightAuto() {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetHeightAutoJNI(mNativePointer);
YogaNative.jni_YGNodeStyleSetHeightAutoJNI(mNativePointer);
else
YogaNative.jni_YGNodeStyleSetHeightAuto(mNativePointer);
} }
public YogaValue getMinWidth() { public YogaValue getMinWidth() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetMinWidthJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetMinWidth(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidthJNI(mNativePointer));
} }
public void setMinWidth(float minWidth) { public void setMinWidth(float minWidth) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMinWidthJNI(mNativePointer, minWidth);
YogaNative.jni_YGNodeStyleSetMinWidthJNI(mNativePointer, minWidth);
else
YogaNative.jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth);
} }
public void setMinWidthPercent(float percent) { public void setMinWidthPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMinWidthPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetMinWidthPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent);
} }
public YogaValue getMinHeight() { public YogaValue getMinHeight() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetMinHeightJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetMinHeight(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeightJNI(mNativePointer));
} }
public void setMinHeight(float minHeight) { public void setMinHeight(float minHeight) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMinHeightJNI(mNativePointer, minHeight);
YogaNative.jni_YGNodeStyleSetMinHeightJNI(mNativePointer, minHeight);
else
YogaNative.jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight);
} }
public void setMinHeightPercent(float percent) { public void setMinHeightPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMinHeightPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetMinHeightPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent);
} }
public YogaValue getMaxWidth() { public YogaValue getMaxWidth() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetMaxWidthJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetMaxWidth(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidthJNI(mNativePointer));
} }
public void setMaxWidth(float maxWidth) { public void setMaxWidth(float maxWidth) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMaxWidthJNI(mNativePointer, maxWidth);
YogaNative.jni_YGNodeStyleSetMaxWidthJNI(mNativePointer, maxWidth);
else
YogaNative.jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth);
} }
public void setMaxWidthPercent(float percent) { public void setMaxWidthPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMaxWidthPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetMaxWidthPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent);
} }
public YogaValue getMaxHeight() { public YogaValue getMaxHeight() {
return valueFromLong(useVanillaJNI ? YogaNative.jni_YGNodeStyleGetMaxHeightJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetMaxHeight(mNativePointer)); return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeightJNI(mNativePointer));
} }
public void setMaxHeight(float maxheight) { public void setMaxHeight(float maxheight) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMaxHeightJNI(mNativePointer, maxheight);
YogaNative.jni_YGNodeStyleSetMaxHeightJNI(mNativePointer, maxheight);
else
YogaNative.jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight);
} }
public void setMaxHeightPercent(float percent) { public void setMaxHeightPercent(float percent) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetMaxHeightPercentJNI(mNativePointer, percent);
YogaNative.jni_YGNodeStyleSetMaxHeightPercentJNI(mNativePointer, percent);
else
YogaNative.jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent);
} }
public float getAspectRatio() { public float getAspectRatio() {
return useVanillaJNI ? YogaNative.jni_YGNodeStyleGetAspectRatioJNI(mNativePointer) : YogaNative.jni_YGNodeStyleGetAspectRatio(mNativePointer); return YogaNative.jni_YGNodeStyleGetAspectRatioJNI(mNativePointer);
} }
public void setAspectRatio(float aspectRatio) { public void setAspectRatio(float aspectRatio) {
if (useVanillaJNI) YogaNative.jni_YGNodeStyleSetAspectRatioJNI(mNativePointer, aspectRatio);
YogaNative.jni_YGNodeStyleSetAspectRatioJNI(mNativePointer, aspectRatio);
else
YogaNative.jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio);
} }
public void setMeasureFunction(YogaMeasureFunction measureFunction) { public void setMeasureFunction(YogaMeasureFunction measureFunction) {
mMeasureFunction = measureFunction; mMeasureFunction = measureFunction;
if (useVanillaJNI) YogaNative.jni_YGNodeSetHasMeasureFuncJNI(mNativePointer, measureFunction != null);
YogaNative.jni_YGNodeSetHasMeasureFuncJNI(mNativePointer, measureFunction != null);
else
YogaNative.jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null);
} }
// Implementation Note: Why this method needs to stay final // Implementation Note: Why this method needs to stay final
@@ -638,10 +505,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
public void setBaselineFunction(YogaBaselineFunction baselineFunction) { public void setBaselineFunction(YogaBaselineFunction baselineFunction) {
mBaselineFunction = baselineFunction; mBaselineFunction = baselineFunction;
if (useVanillaJNI) YogaNative.jni_YGNodeSetHasBaselineFuncJNI(mNativePointer, baselineFunction != null);
YogaNative.jni_YGNodeSetHasBaselineFuncJNI(mNativePointer, baselineFunction != null);
else
YogaNative.jni_YGNodeSetHasBaselineFunc(mNativePointer, baselineFunction != null);
} }
@DoNotStrip @DoNotStrip
@@ -668,14 +532,11 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
/** /**
* Use the set logger (defaults to adb log) to print out the styles, children, and computed * Use the set logger (defaults to adb log) to print out the styles, children, and computed layout
* layout of the tree rooted at this node. * of the tree rooted at this node.
*/ */
public void print() { public void print() {
if (useVanillaJNI) YogaNative.jni_YGNodePrintJNI(mNativePointer);
YogaNative.jni_YGNodePrintJNI(mNativePointer);
else
YogaNative.jni_YGNodePrint(mNativePointer);
} }
/** /**
@@ -683,7 +544,7 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
* This is different than calling removeChildAt and addChildAt because this method ONLY replaces * This is different than calling removeChildAt and addChildAt because this method ONLY replaces
* the child in the mChildren datastructure. @DoNotStrip: called from JNI * the child in the mChildren datastructure. @DoNotStrip: called from JNI
* *
* @return the nativePointer of the newNode {@linl YogaNode} * @return the nativePointer of the newNode {@link YogaNode}
*/ */
@DoNotStrip @DoNotStrip
private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) { private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) {
@@ -721,7 +582,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
} }
public boolean getDoesLegacyStretchFlagAffectsLayout() { public boolean getDoesLegacyStretchFlagAffectsLayout() {
return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR); return arr != null
&& (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR)
== DOES_LEGACY_STRETCH_BEHAVIOUR);
} }
@Override @Override
@@ -737,9 +600,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[LAYOUT_MARGIN_START_INDEX + 3]; return arr[LAYOUT_MARGIN_START_INDEX + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX]; return getLayoutDirection() == YogaDirection.RTL
? arr[LAYOUT_MARGIN_START_INDEX + 2]
: arr[LAYOUT_MARGIN_START_INDEX];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[LAYOUT_MARGIN_START_INDEX]
: arr[LAYOUT_MARGIN_START_INDEX + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
} }
@@ -751,7 +618,9 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public float getLayoutPadding(YogaEdge edge) { public float getLayoutPadding(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) {
int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4); int paddingStartIndex =
LAYOUT_PADDING_START_INDEX
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4);
switch (edge) { switch (edge) {
case LEFT: case LEFT:
return arr[paddingStartIndex]; return arr[paddingStartIndex];
@@ -762,9 +631,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[paddingStartIndex + 3]; return arr[paddingStartIndex + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex]; return getLayoutDirection() == YogaDirection.RTL
? arr[paddingStartIndex + 2]
: arr[paddingStartIndex];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[paddingStartIndex]
: arr[paddingStartIndex + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
} }
@@ -776,7 +649,10 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public float getLayoutBorder(YogaEdge edge) { public float getLayoutBorder(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) { if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4); int borderStartIndex =
LAYOUT_BORDER_START_INDEX
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4)
- ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4);
switch (edge) { switch (edge) {
case LEFT: case LEFT:
return arr[borderStartIndex]; return arr[borderStartIndex];
@@ -787,9 +663,13 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
case BOTTOM: case BOTTOM:
return arr[borderStartIndex + 3]; return arr[borderStartIndex + 3];
case START: case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex]; return getLayoutDirection() == YogaDirection.RTL
? arr[borderStartIndex + 2]
: arr[borderStartIndex];
case END: case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2]; return getLayoutDirection() == YogaDirection.RTL
? arr[borderStartIndex]
: arr[borderStartIndex + 2];
default: default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
} }
@@ -800,7 +680,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Override @Override
public YogaDirection getLayoutDirection() { public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection); return YogaDirection.fromInt(
arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection);
} }
@Override @Override

View File

@@ -12,10 +12,6 @@ public class YogaNodeJNIFinalizer extends YogaNodeJNIBase {
super(); super();
} }
public YogaNodeJNIFinalizer(boolean useVanillaJNI) {
super(useVanillaJNI);
}
public YogaNodeJNIFinalizer(YogaConfig config) { public YogaNodeJNIFinalizer(YogaConfig config) {
super(config); super(config);
} }
@@ -33,10 +29,7 @@ public class YogaNodeJNIFinalizer extends YogaNodeJNIBase {
if (mNativePointer != 0) { if (mNativePointer != 0) {
long nativePointer = mNativePointer; long nativePointer = mNativePointer;
mNativePointer = 0; mNativePointer = 0;
if (useVanillaJNI) YogaNative.jni_YGNodeFreeJNI(nativePointer);
YogaNative.jni_YGNodeFreeJNI(nativePointer);
else
YogaNative.jni_YGNodeFree(nativePointer);
} }
} }
} }

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaNodeType { public enum YogaNodeType {
DEFAULT(0), DEFAULT(0),
TEXT(1); TEXT(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaOverflow { public enum YogaOverflow {
VISIBLE(0), VISIBLE(0),
HIDDEN(1), HIDDEN(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaPositionType { public enum YogaPositionType {
RELATIVE(0), RELATIVE(0),
ABSOLUTE(1); ABSOLUTE(1);

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaPrintOptions { public enum YogaPrintOptions {
LAYOUT(1), LAYOUT(1),
STYLE(2), STYLE(2),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public class YogaStyleInputs { public class YogaStyleInputs {
public static final short LAYOUT_DIRECTION = 0; public static final short LAYOUT_DIRECTION = 0;
public static final short FLEX_DIRECTION = 1; public static final short FLEX_DIRECTION = 1;

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaUnit { public enum YogaUnit {
UNDEFINED(0), UNDEFINED(0),
POINT(1), POINT(1),

View File

@@ -7,9 +7,6 @@
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaWrap { public enum YogaWrap {
NO_WRAP(0), NO_WRAP(0),
WRAP(1), WRAP(1),

View File

@@ -84,9 +84,7 @@ public:
return *this; return *this;
} }
~ScopedGlobalRef() { ~ScopedGlobalRef() { reset(); }
reset();
}
/** /**
* Deletes the currently held reference and reassigns a new one to the * Deletes the currently held reference and reassigns a new one to the
@@ -120,9 +118,7 @@ public:
/** /**
* Returns true if the underlying JNI reference is not NULL. * Returns true if the underlying JNI reference is not NULL.
*/ */
operator bool() const { operator bool() const { return mGlobalRef != NULL; }
return mGlobalRef != NULL;
}
ScopedGlobalRef(const ScopedGlobalRef& ref) = delete; ScopedGlobalRef(const ScopedGlobalRef& ref) = delete;
ScopedGlobalRef& operator=(const ScopedGlobalRef& other) = delete; ScopedGlobalRef& operator=(const ScopedGlobalRef& other) = delete;

View File

@@ -83,9 +83,7 @@ public:
return *this; return *this;
} }
~ScopedLocalRef() { ~ScopedLocalRef() { reset(); }
reset();
}
/** /**
* Deletes the currently held reference and reassigns a new one to the * Deletes the currently held reference and reassigns a new one to the
@@ -119,9 +117,7 @@ public:
/** /**
* Returns true if the underlying JNI reference is not NULL. * Returns true if the underlying JNI reference is not NULL.
*/ */
operator bool() const { operator bool() const { return mLocalRef != NULL; }
return mLocalRef != NULL;
}
ScopedLocalRef(const ScopedLocalRef& ref) = delete; ScopedLocalRef(const ScopedLocalRef& ref) = delete;
ScopedLocalRef& operator=(const ScopedLocalRef& other) = delete; ScopedLocalRef& operator=(const ScopedLocalRef& other) = delete;

View File

@@ -1,712 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fbjni/fbjni.h>
#include <yoga/YGNode.h>
#include <yoga/Yoga.h>
#include <yoga/Yoga-internal.h>
#include <yoga/log.h>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <map>
#include "YGJTypes.h"
#include "YGJNIVanilla.h"
#include "YGJNI.h"
#include "yogajni.h"
using namespace facebook::jni;
using namespace std;
using facebook::yoga::detail::Log;
static inline local_ref<JYogaNode> YGNodeJobject(
YGNodeRef node,
void* layoutContext) {
return reinterpret_cast<PtrJNodeMap*>(layoutContext)->ref(node);
}
static void YGTransferLayoutDirection(
YGNodeRef node,
alias_ref<jobject> javaNode) {
static auto layoutDirectionField =
javaNode->getClass()->getField<jint>("mLayoutDirection");
javaNode->setFieldValue(
layoutDirectionField, static_cast<jint>(YGNodeLayoutGetDirection(node)));
}
static void YGTransferLayoutOutputsRecursive(
YGNodeRef root,
void* layoutContext) {
if (!root->getHasNewLayout()) {
return;
}
auto obj = YGNodeJobject(root, layoutContext);
if (!obj) {
Log::log(
root,
YGLogLevelError,
nullptr,
"Java YGNode was GCed during layout calculation\n");
return;
}
auto edgesSet = YGNodeEdges{root};
bool marginFieldSet = edgesSet.has(YGNodeEdges::MARGIN);
bool paddingFieldSet = edgesSet.has(YGNodeEdges::PADDING);
bool borderFieldSet = edgesSet.has(YGNodeEdges::BORDER);
int fieldFlags = edgesSet.get();
fieldFlags |= HAS_NEW_LAYOUT;
if (YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)) {
fieldFlags |= DOES_LEGACY_STRETCH_BEHAVIOUR;
}
const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) +
(borderFieldSet ? 4 : 0);
float arr[18];
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags;
arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root);
arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root);
arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root);
arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root);
arr[LAYOUT_DIRECTION_INDEX] =
static_cast<jint>(YGNodeLayoutGetDirection(root));
if (marginFieldSet) {
arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft);
arr[LAYOUT_MARGIN_START_INDEX + 1] = YGNodeLayoutGetMargin(root, YGEdgeTop);
arr[LAYOUT_MARGIN_START_INDEX + 2] =
YGNodeLayoutGetMargin(root, YGEdgeRight);
arr[LAYOUT_MARGIN_START_INDEX + 3] =
YGNodeLayoutGetMargin(root, YGEdgeBottom);
}
if (paddingFieldSet) {
int paddingStartIndex =
LAYOUT_PADDING_START_INDEX - (marginFieldSet ? 0 : 4);
arr[paddingStartIndex] = YGNodeLayoutGetPadding(root, YGEdgeLeft);
arr[paddingStartIndex + 1] = YGNodeLayoutGetPadding(root, YGEdgeTop);
arr[paddingStartIndex + 2] = YGNodeLayoutGetPadding(root, YGEdgeRight);
arr[paddingStartIndex + 3] = YGNodeLayoutGetPadding(root, YGEdgeBottom);
}
if (borderFieldSet) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX -
(marginFieldSet ? 0 : 4) - (paddingFieldSet ? 0 : 4);
arr[borderStartIndex] = YGNodeLayoutGetBorder(root, YGEdgeLeft);
arr[borderStartIndex + 1] = YGNodeLayoutGetBorder(root, YGEdgeTop);
arr[borderStartIndex + 2] = YGNodeLayoutGetBorder(root, YGEdgeRight);
arr[borderStartIndex + 3] = YGNodeLayoutGetBorder(root, YGEdgeBottom);
}
static auto arrField = obj->getClass()->getField<jfloatArray>("arr");
local_ref<jfloatArray> arrFinal = make_float_array(arrSize);
arrFinal->setRegion(0, arrSize, arr);
obj->setFieldValue<jfloatArray>(arrField, arrFinal.get());
root->setHasNewLayout(false);
for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) {
YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i), layoutContext);
}
}
static void YGPrint(YGNodeRef node, void* layoutContext) {
if (auto obj = YGNodeJobject(node, layoutContext)) {
cout << obj->toString() << endl;
} else {
Log::log(
node,
YGLogLevelError,
nullptr,
"Java YGNode was GCed during layout calculation\n");
}
}
static float YGJNIBaselineFunc(
YGNodeRef node,
float width,
float height,
void* layoutContext) {
if (auto obj = YGNodeJobject(node, layoutContext)) {
return obj->baseline(width, height);
} else {
return height;
}
}
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
}
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
}
jlong jni_YGNodeClone(alias_ref<jobject> thiz, jlong nativePointer) {
auto node = _jlong2YGNodeRef(nativePointer);
const YGNodeRef clonedYogaNode = YGNodeClone(node);
clonedYogaNode->setContext(node->getContext());
return reinterpret_cast<jlong>(clonedYogaNode);
}
static YGSize YGJNIMeasureFunc(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode,
void* layoutContext) {
if (auto obj = YGNodeJobject(node, layoutContext)) {
YGTransferLayoutDirection(node, obj);
const auto measureResult =
obj->measure(width, widthMode, height, heightMode);
static_assert(
sizeof(measureResult) == 8,
"Expected measureResult to be 8 bytes, or two 32 bit ints");
int32_t wBits = 0xFFFFFFFF & (measureResult >> 32);
int32_t hBits = 0xFFFFFFFF & measureResult;
const float* measuredWidth = reinterpret_cast<float*>(&wBits);
const float* measuredHeight = reinterpret_cast<float*>(&hBits);
return YGSize{*measuredWidth, *measuredHeight};
} else {
Log::log(
node,
YGLogLevelError,
nullptr,
"Java YGNode was GCed during layout calculation\n");
return YGSize{
widthMode == YGMeasureModeUndefined ? 0 : width,
heightMode == YGMeasureModeUndefined ? 0 : height,
};
}
}
static int YGJNILogFunc(
const YGConfigRef config,
const YGNodeRef node,
YGLogLevel level,
void* layoutContext,
const char* format,
va_list args) {
int result = vsnprintf(NULL, 0, format, args);
std::vector<char> buffer(1 + result);
vsnprintf(buffer.data(), buffer.size(), format, args);
auto jloggerPtr =
static_cast<global_ref<JYogaLogger>*>(YGConfigGetContext(config));
if (jloggerPtr != nullptr) {
(*jloggerPtr)
->log(
JYogaLogLevel::fromInt(level),
Environment::current()->NewStringUTF(buffer.data()));
}
return result;
}
jlong jni_YGNodeNew(alias_ref<jobject> thiz) {
const YGNodeRef node = YGNodeNew();
node->setContext(YGNodeContext{}.asVoidPtr);
node->setPrintFunc(YGPrint);
return reinterpret_cast<jlong>(node);
}
jlong jni_YGNodeNewWithConfig(alias_ref<jclass>, jlong configPointer) {
const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer));
node->setContext(YGNodeContext{}.asVoidPtr);
return reinterpret_cast<jlong>(node);
}
void jni_YGNodeFree(alias_ref<jclass>, jlong nativePointer) {
if (nativePointer == 0) {
return;
}
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
YGNodeFree(node);
}
void jni_YGNodeClearChildren(jlong nativePointer) {
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
node->clearChildren();
}
void jni_YGNodeReset(jlong nativePointer) {
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
void* context = node->getContext();
YGNodeReset(node);
node->setContext(context);
}
void jni_YGNodePrint(jlong nativePointer) {
#ifdef DEBUG
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
YGNodePrint(
node,
(YGPrintOptions)(
YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren));
#endif
}
void jni_YGNodeInsertChild(
jlong nativePointer,
jlong childPointer,
jint index) {
YGNodeInsertChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
}
void jni_YGNodeRemoveChild(jlong nativePointer, jlong childPointer) {
YGNodeRemoveChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
}
void jni_YGNodeSetIsReferenceBaseline(
jlong nativePointer,
jboolean isReferenceBaseline) {
YGNodeSetIsReferenceBaseline(
_jlong2YGNodeRef(nativePointer), isReferenceBaseline);
}
jboolean jni_YGNodeIsReferenceBaseline(jlong nativePointer) {
return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer));
}
void jni_YGNodeCalculateLayout(
alias_ref<jclass>,
jlong nativePointer,
jfloat width,
jfloat height,
alias_ref<JArrayLong> nativePointers,
alias_ref<JArrayClass<JYogaNode::javaobject>> javaNodes) {
void* layoutContext = nullptr;
auto map = PtrJNodeMap{};
if (nativePointers) {
map = PtrJNodeMap{nativePointers, javaNodes};
layoutContext = &map;
}
const YGNodeRef root = _jlong2YGNodeRef(nativePointer);
YGNodeCalculateLayoutWithContext(
root,
static_cast<float>(width),
static_cast<float>(height),
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)),
layoutContext);
YGTransferLayoutOutputsRecursive(root, layoutContext);
}
void jni_YGNodeMarkDirty(jlong nativePointer) {
YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer));
}
void jni_YGNodeMarkDirtyAndPropogateToDescendants(jlong nativePointer) {
YGNodeMarkDirtyAndPropogateToDescendants(_jlong2YGNodeRef(nativePointer));
}
jboolean jni_YGNodeIsDirty(jlong nativePointer) {
return (jboolean) _jlong2YGNodeRef(nativePointer)->isDirty();
}
void jni_YGNodeSetHasMeasureFunc(jlong nativePointer, jboolean hasMeasureFunc) {
_jlong2YGNodeRef(nativePointer)
->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr);
}
void jni_YGNodeSetHasBaselineFunc(
jlong nativePointer,
jboolean hasBaselineFunc) {
_jlong2YGNodeRef(nativePointer)
->setBaselineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr);
}
void jni_YGNodeCopyStyle(jlong dstNativePointer, jlong srcNativePointer) {
YGNodeCopyStyle(
_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer));
}
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
javatype jni_YGNodeStyleGet##name(jlong nativePointer) { \
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
} \
\
void jni_YGNodeStyleSet##name(jlong nativePointer, javatype value) { \
YGNodeStyleSet##name( \
_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
}
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
jlong jni_YGNodeStyleGet##name(jlong nativePointer) { \
return YogaValue::asJavaLong( \
YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \
} \
\
void jni_YGNodeStyleSet##name(jlong nativePointer, jfloat value) { \
YGNodeStyleSet##name( \
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
} \
\
void jni_YGNodeStyleSet##name##Percent(jlong nativePointer, jfloat value) { \
YGNodeStyleSet##name##Percent( \
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
}
#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \
YG_NODE_JNI_STYLE_UNIT_PROP(name) \
void jni_YGNodeStyleSet##name##Auto(jlong nativePointer) { \
YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \
}
#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \
javatype jni_YGNodeStyleGet##name(jlong nativePointer, jint edge) { \
return (javatype) YGNodeStyleGet##name( \
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge)); \
} \
\
void jni_YGNodeStyleSet##name( \
jlong nativePointer, jint edge, javatype value) { \
YGNodeStyleSet##name( \
_jlong2YGNodeRef(nativePointer), \
static_cast<YGEdge>(edge), \
static_cast<type>(value)); \
}
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
jlong jni_YGNodeStyleGet##name(jlong nativePointer, jint edge) { \
return YogaValue::asJavaLong(YGNodeStyleGet##name( \
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \
} \
\
void jni_YGNodeStyleSet##name( \
jlong nativePointer, jint edge, jfloat value) { \
YGNodeStyleSet##name( \
_jlong2YGNodeRef(nativePointer), \
static_cast<YGEdge>(edge), \
static_cast<float>(value)); \
} \
\
void jni_YGNodeStyleSet##name##Percent( \
jlong nativePointer, jint edge, jfloat value) { \
YGNodeStyleSet##name##Percent( \
_jlong2YGNodeRef(nativePointer), \
static_cast<YGEdge>(edge), \
static_cast<float>(value)); \
}
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
void jni_YGNodeStyleSet##name##Auto(jlong nativePointer, jint edge) { \
YGNodeStyleSet##name##Auto( \
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge)); \
}
YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction);
YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection);
YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent);
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignItems);
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignSelf);
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignContent);
YG_NODE_JNI_STYLE_PROP(jint, YGPositionType, PositionType);
YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap);
YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow);
YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display);
jfloat jni_YGNodeStyleGetFlex(jlong nativePointer) {
return YGNodeStyleGetFlex(_jlong2YGNodeRef(nativePointer));
}
void jni_YGNodeStyleSetFlex(jlong nativePointer, jfloat value) {
YGNodeStyleSetFlex(
_jlong2YGNodeRef(nativePointer), static_cast<float>(value));
}
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow);
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(FlexBasis);
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Width);
YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth);
YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height);
YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight);
YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight);
// Yoga specific properties, not compatible with flexbox specification
YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
jlong jni_YGConfigNew(alias_ref<jclass>) {
return reinterpret_cast<jlong>(YGConfigNew());
}
void jni_YGConfigFree(alias_ref<jclass>, jlong nativePointer) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
// unique_ptr will destruct the underlying global_ref, if present.
auto context = std::unique_ptr<global_ref<JYogaLogger>>{
static_cast<global_ref<JYogaLogger>*>(YGConfigGetContext(config))};
YGConfigFree(config);
}
void jni_YGConfigSetExperimentalFeatureEnabled(
alias_ref<jclass>,
jlong nativePointer,
jint feature,
jboolean enabled) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetExperimentalFeatureEnabled(
config, static_cast<YGExperimentalFeature>(feature), enabled);
}
void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(
alias_ref<jclass>,
jlong nativePointer,
jboolean enabled) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(config, enabled);
}
void jni_YGConfigSetUseWebDefaults(
alias_ref<jclass>,
jlong nativePointer,
jboolean useWebDefaults) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetUseWebDefaults(config, useWebDefaults);
}
void jni_YGConfigSetPrintTreeFlag(
alias_ref<jclass>,
jlong nativePointer,
jboolean enable) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetPrintTreeFlag(config, enable);
}
void jni_YGConfigSetPointScaleFactor(
alias_ref<jclass>,
jlong nativePointer,
jfloat pixelsInPoint) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetPointScaleFactor(config, pixelsInPoint);
}
void jni_YGConfigSetUseLegacyStretchBehaviour(
alias_ref<jclass>,
jlong nativePointer,
jboolean useLegacyStretchBehaviour) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour);
}
void jni_YGConfigSetLogger(
alias_ref<jclass>,
jlong nativePointer,
alias_ref<jobject> logger) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
auto context =
reinterpret_cast<global_ref<JYogaLogger>*>(YGConfigGetContext(config));
if (logger) {
if (context == nullptr) {
context = new global_ref<JYogaLogger>{};
YGConfigSetContext(config, context);
}
*context = make_global(static_ref_cast<JYogaLogger::javaobject>(logger));
config->setLogger(YGJNILogFunc);
} else {
if (context != nullptr) {
delete context;
YGConfigSetContext(config, nullptr);
}
config->setLogger(nullptr);
}
}
jlong jni_YGNodeStyleGetMargin(jlong nativePointer, jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
return YogaValue::undefinedAsJavaLong();
}
return YogaValue::asJavaLong(
YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge)));
}
void jni_YGNodeStyleSetMargin(jlong nativePointer, jint edge, jfloat margin) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
YGNodeStyleSetMargin(
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(margin));
}
void jni_YGNodeStyleSetMarginPercent(
jlong nativePointer,
jint edge,
jfloat percent) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
YGNodeStyleSetMarginPercent(
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
}
void jni_YGNodeStyleSetMarginAuto(jlong nativePointer, jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge));
}
jlong jni_YGNodeStyleGetPadding(jlong nativePointer, jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) {
return YogaValue::undefinedAsJavaLong();
}
return YogaValue::asJavaLong(
YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge)));
}
void jni_YGNodeStyleSetPadding(jlong nativePointer, jint edge, jfloat padding) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
YGNodeStyleSetPadding(
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(padding));
}
void jni_YGNodeStyleSetPaddingPercent(
jlong nativePointer,
jint edge,
jfloat percent) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
YGNodeStyleSetPaddingPercent(
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
}
jfloat jni_YGNodeStyleGetBorder(jlong nativePointer, jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::BORDER)) {
return (jfloat) YGUndefined;
}
return (jfloat) YGNodeStyleGetBorder(yogaNodeRef, static_cast<YGEdge>(edge));
}
void jni_YGNodeStyleSetBorder(jlong nativePointer, jint edge, jfloat border) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::BORDER).setOn(yogaNodeRef);
YGNodeStyleSetBorder(
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(border));
}
#define YGMakeNativeMethod(name) makeNativeMethod(#name, name)
#define YGMakeCriticalNativeMethod(name) \
makeCriticalNativeMethod_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(#name, name)
jint YGJNI::registerNativeMethods(JavaVM* vm) {
jint ret = initialize(vm, [] {
registerNatives(
"com/facebook/yoga/YogaNative",
{
YGMakeNativeMethod(jni_YGNodeNew),
YGMakeNativeMethod(jni_YGNodeNewWithConfig),
YGMakeNativeMethod(jni_YGNodeFree),
YGMakeCriticalNativeMethod(jni_YGNodeReset),
YGMakeCriticalNativeMethod(jni_YGNodeClearChildren),
YGMakeCriticalNativeMethod(jni_YGNodeInsertChild),
YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild),
YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline),
YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline),
YGMakeNativeMethod(jni_YGNodeCalculateLayout),
YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty),
YGMakeCriticalNativeMethod(
jni_YGNodeMarkDirtyAndPropogateToDescendants),
YGMakeCriticalNativeMethod(jni_YGNodeIsDirty),
YGMakeCriticalNativeMethod(jni_YGNodeSetHasMeasureFunc),
YGMakeCriticalNativeMethod(jni_YGNodeSetHasBaselineFunc),
YGMakeCriticalNativeMethod(jni_YGNodeCopyStyle),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDirection),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDirection),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexDirection),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexDirection),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetJustifyContent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetJustifyContent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignItems),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignItems),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignSelf),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignSelf),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignContent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignContent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPositionType),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionType),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexWrap),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexWrap),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetOverflow),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetOverflow),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDisplay),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDisplay),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlex),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlex),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexGrow),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexGrow),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexShrink),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexShrink),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexBasis),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasis),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisAuto),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetMargin),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMargin),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginAuto),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPadding),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPadding),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPaddingPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetBorder),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetBorder),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPosition),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPosition),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthAuto),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightAuto),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetMinWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidthPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetMinHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeightPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetMaxWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidth),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidthPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetMaxHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeight),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio),
YGMakeCriticalNativeMethod(jni_YGNodePrint),
YGMakeNativeMethod(jni_YGNodeClone),
YGMakeNativeMethod(jni_YGConfigNew),
YGMakeNativeMethod(jni_YGConfigFree),
YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled),
YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults),
YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag),
YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor),
YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour),
YGMakeNativeMethod(jni_YGConfigSetLogger),
YGMakeNativeMethod(
jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour),
});
});
return ret;
}

View File

@@ -15,6 +15,7 @@
#include <yoga/log.h> #include <yoga/log.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include "YogaJniException.h"
using namespace facebook::yoga::vanillajni; using namespace facebook::yoga::vanillajni;
using facebook::yoga::detail::Log; using facebook::yoga::detail::Log;
@@ -224,6 +225,16 @@ static void jni_YGNodeInsertChildJNI(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
} }
static void jni_YGNodeSwapChildJNI(
JNIEnv* env,
jobject obj,
jlong nativePointer,
jlong childPointer,
jint index) {
YGNodeSwapChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
}
static void jni_YGNodeSetIsReferenceBaselineJNI( static void jni_YGNodeSetIsReferenceBaselineJNI(
JNIEnv* env, JNIEnv* env,
jobject obj, jobject obj,
@@ -372,8 +383,18 @@ static void jni_YGNodeCalculateLayoutJNI(
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)),
layoutContext); layoutContext);
YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext); YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext);
} catch (jthrowable throwable) { } catch (const YogaJniException& jniException) {
env->Throw(throwable); ScopedLocalRef<jthrowable> throwable = jniException.getThrowable();
if (throwable.get()) {
env->Throw(throwable.get());
}
} catch (const std::logic_error& ex) {
env->ExceptionClear();
jclass cl = env->FindClass("Ljava/lang/IllegalStateException;");
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
env, cl, "<init>", "(Ljava/lang/String;)V");
auto throwable = env->NewObject(cl, methodId, env->NewStringUTF(ex.what()));
env->Throw(static_cast<jthrowable>(throwable));
} }
} }
@@ -750,6 +771,7 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI}, {"jni_YGNodeFreeJNI", "(J)V", (void*) jni_YGNodeFreeJNI},
{"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI}, {"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI},
{"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI}, {"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI},
{"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI},
{"jni_YGNodeSetIsReferenceBaselineJNI", {"jni_YGNodeSetIsReferenceBaselineJNI",
"(JZ)V", "(JZ)V",
(void*) jni_YGNodeSetIsReferenceBaselineJNI}, (void*) jni_YGNodeSetIsReferenceBaselineJNI},

View File

@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include "jni.h"
namespace YGJNIVanilla { namespace YGJNIVanilla {
void registerNatives(JNIEnv* env); void registerNatives(JNIEnv* env);
}; };

View File

@@ -1,43 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "YGJTypes.h"
using facebook::jni::alias_ref;
using facebook::jni::local_ref;
jfloat JYogaNode::baseline(jfloat width, jfloat height) {
static auto javaMethod =
javaClassLocal()->getMethod<jfloat(jfloat, jfloat)>("baseline");
return javaMethod(self(), width, height);
}
jlong JYogaNode::measure(
jfloat width,
jint widthMode,
jfloat height,
jint heightMode) {
static auto javaMethod =
javaClassLocal()->getMethod<jlong(jfloat, jint, jfloat, jint)>("measure");
return javaMethod(self(), width, widthMode, height, heightMode);
}
facebook::jni::local_ref<JYogaLogLevel> JYogaLogLevel::fromInt(jint logLevel) {
static auto javaMethod =
javaClassStatic()->getStaticMethod<alias_ref<JYogaLogLevel>(jint)>(
"fromInt");
return javaMethod(javaClassStatic(), logLevel);
}
void JYogaLogger::log(
facebook::jni::alias_ref<JYogaLogLevel> logLevel,
jstring message) {
static auto javaMethod =
javaClassLocal()->getMethod<void(alias_ref<JYogaLogLevel>, jstring)>(
"log");
javaMethod(self(), logLevel, message);
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fbjni/fbjni.h>
#include <yoga/YGValue.h>
#include <yoga/Yoga.h>
#include <map>
using namespace facebook::jni;
using namespace std;
struct JYogaNode : public facebook::jni::JavaClass<JYogaNode> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaNodeJNIBase;";
jfloat baseline(jfloat width, jfloat height);
jlong measure(jfloat width, jint widthMode, jfloat height, jint heightMode);
};
struct JYogaLogLevel : public facebook::jni::JavaClass<JYogaLogLevel> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogLevel;";
static facebook::jni::local_ref<JYogaLogLevel> fromInt(jint);
};
struct JYogaLogger : public facebook::jni::JavaClass<JYogaLogger> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogger;";
void log(facebook::jni::alias_ref<JYogaLogLevel>, jstring);
};
class PtrJNodeMap {
using JNodeArray = JArrayClass<JYogaNode::javaobject>;
std::map<YGNodeRef, size_t> ptrsToIdxs_;
alias_ref<JNodeArray> javaNodes_;
public:
PtrJNodeMap() : ptrsToIdxs_{}, javaNodes_{} {}
PtrJNodeMap(
alias_ref<JArrayLong> nativePointers,
alias_ref<JNodeArray> javaNodes)
: javaNodes_{javaNodes} {
auto pin = nativePointers->pinCritical();
auto ptrs = pin.get();
for (size_t i = 0, n = pin.size(); i < n; ++i) {
ptrsToIdxs_[(YGNodeRef) ptrs[i]] = i;
}
}
local_ref<JYogaNode> ref(YGNodeRef node) {
auto idx = ptrsToIdxs_.find(node);
if (idx == ptrsToIdxs_.end()) {
return local_ref<JYogaNode>{};
} else {
return javaNodes_->getElement(idx->second);
}
}
};

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdexcept>
#include <string>
#include "YogaJniException.h"
#include "common.h"
namespace facebook {
namespace yoga {
namespace vanillajni {
YogaJniException::YogaJniException() {
jclass cl = getCurrentEnv()->FindClass("Ljava/lang/RuntimeException;");
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
getCurrentEnv(), cl, "<init>", "()V");
auto throwable = getCurrentEnv()->NewObject(cl, methodId);
throwable_ =
newGlobalRef(getCurrentEnv(), static_cast<jthrowable>(throwable));
}
YogaJniException::YogaJniException(jthrowable throwable) {
throwable_ = newGlobalRef(getCurrentEnv(), throwable);
}
YogaJniException::YogaJniException(YogaJniException&& rhs)
: throwable_(std::move(rhs.throwable_)) {}
YogaJniException::YogaJniException(const YogaJniException& rhs) {
throwable_ = newGlobalRef(getCurrentEnv(), rhs.throwable_.get());
}
YogaJniException::~YogaJniException() {
try {
throwable_.reset();
} catch (...) {
std::terminate();
}
}
ScopedLocalRef<jthrowable> YogaJniException::getThrowable() const noexcept {
return make_local_ref(
getCurrentEnv(),
static_cast<jthrowable>(getCurrentEnv()->NewLocalRef(throwable_.get())));
}
} // namespace vanillajni
} // namespace yoga
} // namespace facebook

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdexcept>
#include <string>
#include "common.h"
namespace facebook {
namespace yoga {
namespace vanillajni {
/**
* This class wraps a Java exception (jthrowable) into a C++ exception; A global
* reference to Java exception (jthrowable) is made so that the exception object
* does not gets cleared before jni call completion
*/
class YogaJniException : public std::exception {
public:
YogaJniException();
~YogaJniException() override;
explicit YogaJniException(jthrowable throwable);
YogaJniException(YogaJniException&& rhs);
YogaJniException(const YogaJniException& other);
ScopedLocalRef<jthrowable> getThrowable() const noexcept;
private:
ScopedGlobalRef<jthrowable> throwable_;
};
} // namespace vanillajni
} // namespace yoga
} // namespace facebook

View File

@@ -18,11 +18,11 @@ void registerNatives(
size_t numMethods) { size_t numMethods) {
jclass clazz = env->FindClass(className); jclass clazz = env->FindClass(className);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !clazz);
env->RegisterNatives(clazz, methods, numMethods); auto result = env->RegisterNatives(clazz, methods, numMethods);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, result != JNI_OK);
} }
jmethodID getStaticMethodId( jmethodID getStaticMethodId(
@@ -32,7 +32,7 @@ jmethodID getStaticMethodId(
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = jmethodID methodId =
env->GetStaticMethodID(clazz, methodName, methodDescriptor); env->GetStaticMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -42,7 +42,7 @@ jmethodID getMethodId(
const char* methodName, const char* methodName,
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor); jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -52,7 +52,7 @@ jfieldID getFieldId(
const char* fieldName, const char* fieldName,
const char* fieldSignature) { const char* fieldSignature) {
jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature); jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !fieldId);
return fieldId; return fieldId;
} }
@@ -77,13 +77,16 @@ DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(void, Void) {
assertNoPendingJniException(env); assertNoPendingJniException(env);
} }
ScopedLocalRef<jobject> ScopedLocalRef<jobject> callStaticObjectMethod(
callStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID methodId, ...) { JNIEnv* env,
jclass clazz,
jmethodID methodId,
...) {
va_list args; va_list args;
va_start(args, methodId); va_start(args, methodId);
jobject result = env->CallStaticObjectMethodV(clazz, methodId, args); jobject result = env->CallStaticObjectMethodV(clazz, methodId, args);
va_end(args); va_end(args);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !result);
return make_local_ref(env, result); return make_local_ref(env, result);
} }
@@ -96,6 +99,16 @@ ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj) {
return make_global_ref(result); return make_global_ref(result);
} }
ScopedGlobalRef<jthrowable> newGlobalRef(JNIEnv* env, jthrowable obj) {
jthrowable result = static_cast<jthrowable>(env->NewGlobalRef(obj));
if (!result) {
logErrorMessageAndDie("Could not obtain global reference from object");
}
return make_global_ref(result);
}
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -61,14 +61,19 @@ DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(void, Void);
DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jlong, Long); DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jlong, Long);
DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jfloat, Float); DEFINE_CALL_METHOD_FOR_PRIMITIVE_INTERFACE(jfloat, Float);
ScopedLocalRef<jobject> ScopedLocalRef<jobject> callStaticObjectMethod(
callStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID methodId, ...); JNIEnv* env,
jclass clazz,
jmethodID methodId,
...);
/** /**
* Given a local or a global reference, this method creates a new global * Given a local or a global reference, this method creates a new global
* reference out of it. If any error happens, aborts the process. * reference out of it. If any error happens, aborts the process.
*/ */
ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj); ScopedGlobalRef<jobject> newGlobalRef(JNIEnv* env, jobject obj);
ScopedGlobalRef<jthrowable> newGlobalRef(JNIEnv* env, jthrowable obj);
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -7,6 +7,7 @@
#include "corefunctions.h" #include "corefunctions.h"
#include "macros.h" #include "macros.h"
#include "YogaJniException.h"
namespace facebook { namespace facebook {
namespace yoga { namespace yoga {
@@ -72,7 +73,20 @@ void assertNoPendingJniException(JNIEnv* env) {
logErrorMessageAndDie("Unable to get pending JNI exception."); logErrorMessageAndDie("Unable to get pending JNI exception.");
} }
env->ExceptionClear(); env->ExceptionClear();
throw throwable; throw YogaJniException(throwable);
}
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition) {
if (!condition) {
return;
}
if (env->ExceptionCheck() == JNI_TRUE) {
assertNoPendingJniException(env);
return;
}
throw YogaJniException();
} }
} // namespace vanillajni } // namespace vanillajni

View File

@@ -47,6 +47,8 @@ void logErrorMessageAndDie(const char* message);
*/ */
void assertNoPendingJniException(JNIEnv* env); void assertNoPendingJniException(JNIEnv* env);
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition);
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -4,20 +4,14 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include "yogajni.h"
#include "YGJNIVanilla.h" #include "YGJNIVanilla.h"
#include <fbjni/fbjni.h>
#include "common.h" #include "common.h"
using namespace facebook::jni;
using namespace facebook::yoga; using namespace facebook::yoga;
jint JNI_OnLoad(JavaVM* vm, void*) { jint JNI_OnLoad(JavaVM* vm, void*) {
jint ret = YGJNI::registerNativeMethods(vm);
JNIEnv* env; JNIEnv* env;
vanillajni::ensureInitialized(&env, vm); jint ret = vanillajni::ensureInitialized(&env, vm);
YGJNIVanilla::registerNatives(env); YGJNIVanilla::registerNatives(env);
return ret; return ret;
} }

View File

@@ -1,12 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fbjni/fbjni.h>
namespace YGJNI {
jint registerNativeMethods(JavaVM* vm);
};

View File

@@ -28,25 +28,7 @@ public class TestParametrization {
return "JNI"; return "JNI";
} }
}; };
return Arrays.asList(nodeFactory);
NodeFactory nodeFactoryUsingVanillaJNI = new NodeFactory() {
@Override
public YogaNode create() {
return YogaNodeFactory.create(true);
}
@Override
public YogaNode create(YogaConfig config) {
config.setUseVanillaJNI(true);
return YogaNodeFactory.create(config);
}
@Override
public String toString() {
return "VanillaJNI";
}
};
return Arrays.asList(nodeFactory, nodeFactoryUsingVanillaJNI);
} }

6
java/yogajni.version Normal file
View File

@@ -0,0 +1,6 @@
{
global:
JNI_OnLoad;
local:
*;
};

View File

@@ -18,7 +18,5 @@ struct Size {
Size(double width, double height) : width(width), height(height) {} Size(double width, double height) : width(width), height(height) {}
void toJS(nbind::cbOutput expose) const { void toJS(nbind::cbOutput expose) const { expose(width, height); }
expose(width, height);
}
}; };

View File

@@ -21,7 +21,5 @@ struct Value {
Value(int unit, double value) : unit(unit), value(value) {} Value(int unit, double value) : unit(unit), value(value) {}
void toJS(nbind::cbOutput expose) const { void toJS(nbind::cbOutput expose) const { expose(unit, value); }
expose(unit, value);
}
}; };

View File

@@ -3,7 +3,7 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "JSR_305_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library") load("//tools/build_defs/oss:yoga_defs.bzl", "JSR_305_TARGET", "PROGUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library")
yoga_java_library( yoga_java_library(
name = "jni", name = "jni",
@@ -13,7 +13,7 @@ yoga_java_library(
"PUBLIC", "PUBLIC",
], ],
deps = [ deps = [
PROGRUARD_ANNOTATIONS_TARGET, PROGUARD_ANNOTATIONS_TARGET,
SOLOADER_TARGET, SOLOADER_TARGET,
JSR_305_TARGET, JSR_305_TARGET,
], ],

View File

@@ -3,10 +3,9 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_prebuilt_aar")
load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS")
fb_native.android_prebuilt_aar( yoga_prebuilt_aar(
name = "soloader", name = "soloader",
aar = "soloader-0.5.1.aar", aar = "soloader-0.5.1.aar",
visibility = YOGA_ROOTS, visibility = YOGA_ROOTS,

View File

@@ -14,14 +14,14 @@ set -e
BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
IS_SNAPSHOT="$(grep 'VERSION_NAME=[0-9\.]\+-SNAPSHOT' "$BASEDIR/gradle.properties")" IS_SNAPSHOT="$(grep 'VERSION_NAME=[0-9\.]\+-SNAPSHOT' "$BASEDIR/gradle.properties")"
if [ "$TRAVIS_REPO_SLUG" != "facebook/yoga" ]; then if [ "$GITHUB_REPOSITORY" != "facebook/yoga" ]; then
echo >&2 "Skipping repository. Expected project to be 'facebook/yoga', but was '$TRAVIS_REPO_SLUG'." echo >&2 "Skipping repository. Expected project to be 'facebook/yoga', but was '$GITHUB_REPOSITORY'."
exit exit
elif [ "$TRAVIS_BRANCH" != "master" ]; then elif [ "$GITHUB_REF" != "refs/heads/master" ]; then
echo >&2 "Skipping build. Expected branch name to be 'master', but was '$TRAVIS_BRANCH'." echo >&2 "Skipping build. Expected ref name to be 'refs/heads/master', but was '$GITHUB_REF'."
exit exit
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then elif [ "$GITHUB_EVENT_NAME" != "push" ]; then
echo >&2 "Skipping build. Only considering non-PR builds, but URL was '$TRAVIS_PULL_REQUEST'." echo >&2 "Skipping build. Only considering push builds, but event was '$GITHUB_EVENT_NAME'."
exit exit
elif [ "$IS_SNAPSHOT" == "" ]; then elif [ "$IS_SNAPSHOT" == "" ]; then
echo >&2 "Skipping build. Given build doesn't appear to be a SNAPSHOT release." echo >&2 "Skipping build. Given build doesn't appear to be a SNAPSHOT release."

206
tests/BitUtilsTest.cpp Normal file
View File

@@ -0,0 +1,206 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <cstdint>
#include <yoga/BitUtils.h>
namespace facebook {
namespace yoga {
TEST(BitUtils, one_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
}
TEST(BitUtils, one_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 1;
ASSERT_EQ(detail::getBooleanData(flags, 0), true);
static_assert(
detail::getBooleanData(flags, 0) == true,
"first boolean member must be initialized to true");
}
TEST(BitUtils, one_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 0, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), true);
}
TEST(BitUtils, second_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
static_assert(
detail::getBooleanData(flags, 1) == false,
"second boolean member must default to false");
}
TEST(BitUtils, second_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 2;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 1) == true,
"second boolean member must be initialized to true");
}
TEST(BitUtils, second_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 1, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
}
TEST(BitUtils, third_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getBooleanData(flags, 2), false);
static_assert(
detail::getBooleanData(flags, 2) == false,
"second boolean member must default to false");
}
TEST(BitUtils, third_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 4;
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
ASSERT_EQ(detail::getBooleanData(flags, 2), true);
static_assert(
detail::getBooleanData(flags, 0) == false,
"first boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 1) == false,
"second boolean member must default to false");
static_assert(
detail::getBooleanData(flags, 2) == true,
"second boolean member must be initialized to true");
}
TEST(BitUtils, third_boolean_can_be_set_to_true) {
uint8_t flags = 0;
detail::setBooleanData(flags, 2, true);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), false);
ASSERT_EQ(detail::getBooleanData(flags, 2), true);
}
TEST(BitUtils, setting_boolean_values_does_not_spill_over) {
uint8_t flags = 0;
detail::setBooleanData(flags, 1, (bool) 7);
ASSERT_EQ(detail::getBooleanData(flags, 0), false);
ASSERT_EQ(detail::getBooleanData(flags, 1), true);
ASSERT_EQ(detail::getBooleanData(flags, 2), false);
}
TEST(BitUtils, first_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, 0), YGAlignAuto);
static_assert(
detail::getEnumData<YGAlign>(flags, 0) == YGAlignAuto,
"first enum member must default to 0");
}
TEST(BitUtils, first_enum_can_be_set) {
uint8_t flags = 0;
detail::setEnumData<YGAlign>(flags, 0, YGAlignSpaceBetween);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, 0), YGAlignSpaceBetween);
}
TEST(BitUtils, second_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgeOffset), YGEdgeLeft);
static_assert(
detail::getEnumData<YGAlign>(flags, alignOffset) == YGAlignAuto,
"first enum member must default to 0");
static_assert(
detail::getEnumData<YGEdge>(flags, edgeOffset) == YGEdgeLeft,
"second enum member must default to 0");
}
TEST(BitUtils, second_enum_can_be_set) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3;
detail::setEnumData<YGEdge>(flags, edgeOffset, YGEdgeAll);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgeOffset), YGEdgeAll);
}
TEST(BitUtils, third_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4;
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), YGEdgeLeft);
static_assert(
detail::getEnumData<YGAlign>(flags, alignOffset) == YGAlignAuto,
"first enum member must default to 0");
static_assert(
detail::getBooleanData(flags, boolOffset) == false,
"middle boolean member must default to false");
static_assert(
detail::getEnumData<YGEdge>(flags, edgesOffset) == YGEdgeLeft,
"last enum member must default to 0");
}
TEST(BitUtils, third_enum_can_be_set) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4;
detail::setEnumData<YGEdge>(flags, edgesOffset, YGEdgeVertical);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), YGAlignAuto);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), YGEdgeVertical);
}
TEST(BitUtils, setting_values_does_not_spill_over) {
uint8_t flags = 0;
static constexpr size_t alignOffset = 0;
static constexpr size_t edgesOffset = 3;
static constexpr size_t boolOffset = 7;
detail::setEnumData<YGEdge>(flags, edgesOffset, (YGEdge) 0xffffff);
ASSERT_EQ(detail::getEnumData<YGAlign>(flags, alignOffset), 0);
ASSERT_EQ(detail::getBooleanData(flags, boolOffset), false);
ASSERT_EQ(detail::getEnumData<YGEdge>(flags, edgesOffset), 0xf);
}
} // namespace yoga
} // namespace facebook

View File

@@ -1,244 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <cstdint>
#include <yoga/Bitfield.h>
namespace facebook {
namespace yoga {
TEST(Bitfield, one_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool>{};
ASSERT_EQ(bf.at<0>(), false);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
}
TEST(Bitfield, one_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool>{true};
ASSERT_EQ(bf.at<0>(), true);
static_assert(
bf.at<0>() == true, "first boolean member must be initialized to true");
}
TEST(Bitfield, one_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool>{};
bf.at<0>() = true;
ASSERT_EQ(bf.at<0>(), true);
}
TEST(Bitfield, second_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool, bool>{};
ASSERT_EQ(bf.at<1>(), false);
static_assert(
bf.at<1>() == false, "second boolean member must default to false");
}
TEST(Bitfield, second_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool, bool>{false, true};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
static_assert(
bf.at<1>() == true, "second boolean member must be initialized to true");
}
TEST(Bitfield, second_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool, bool>{};
bf.at<1>() = true;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
}
TEST(Bitfield, third_boolean_defaults_to_false) {
constexpr auto bf = Bitfield<uint8_t, bool, bool, bool>{};
ASSERT_EQ(bf.at<2>(), false);
static_assert(
bf.at<2>() == false, "second boolean member must default to false");
}
TEST(Bitfield, third_boolean_can_be_initialized_to_true) {
constexpr auto bf = Bitfield<uint8_t, bool, bool, bool>{false, false, true};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), true);
static_assert(
bf.at<0>() == false, "first boolean member must default to false");
static_assert(
bf.at<1>() == false, "second boolean member must default to false");
static_assert(
bf.at<2>() == true, "second boolean member must be initialized to true");
}
TEST(Bitfield, third_boolean_can_be_set_to_true) {
auto bf = Bitfield<uint8_t, bool, bool, bool>{};
bf.at<2>() = true;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), true);
}
TEST(Bitfield, initializing_boolean_values_does_not_spill_over) {
constexpr auto bf =
Bitfield<uint8_t, bool, bool, bool>{false, (bool) 7, false};
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
ASSERT_EQ(bf.at<2>(), false);
static_assert(
bf.at<0>() == false, "first boolean member must be initialized to false");
static_assert(
bf.at<1>() == true, "second boolean member must be initialized to true");
static_assert(
bf.at<2>() == false, "third boolean member must be initialized to false");
}
TEST(Bitfield, setting_boolean_values_does_not_spill_over) {
auto bf = Bitfield<uint8_t, bool, bool, bool>{};
bf.at<1>() = (bool) 7;
ASSERT_EQ(bf.at<0>(), false);
ASSERT_EQ(bf.at<1>(), true);
ASSERT_EQ(bf.at<2>(), false);
}
TEST(Bitfield, first_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
}
TEST(Bitfield, first_enum_can_be_initialized) {
constexpr auto bf = Bitfield<uint8_t, YGAlign>{YGAlignFlexEnd};
ASSERT_EQ(bf.at<0>(), YGAlignFlexEnd);
static_assert(
bf.at<0>() == YGAlignFlexEnd,
"first enum member must be initialized to YGAlignFlexEnd");
}
TEST(Bitfield, first_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign>{};
bf.at<0>() = YGAlignSpaceBetween;
ASSERT_EQ(bf.at<0>(), YGAlignSpaceBetween);
}
TEST(Bitfield, second_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, YGEdge>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeLeft);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == YGEdgeLeft, "second enum member must default to 0");
}
TEST(Bitfield, second_enum_can_be_initialized) {
constexpr auto bf =
Bitfield<uint8_t, YGAlign, YGEdge>{YGAlignAuto, YGEdgeAll};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeAll);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == YGEdgeAll,
"second enum member must be initialized to YGEdgeAll");
}
TEST(Bitfield, second_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign, YGEdge>{};
bf.at<1>() = YGEdgeAll;
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), YGEdgeAll);
}
TEST(Bitfield, third_enum_defaults_to_0) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeLeft);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == false, "middle boolean member must default to false");
static_assert(bf.at<2>() == YGEdgeLeft, "last enum member must default to 0");
}
TEST(Bitfield, third_enum_can_be_initialized) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{
YGAlignAuto, false, YGEdgeVertical};
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeVertical);
static_assert(
bf.at<0>() == YGAlignAuto, "first enum member must default to 0");
static_assert(
bf.at<1>() == false, "middle boolean member must default to false");
static_assert(
bf.at<2>() == YGEdgeVertical,
"second enum member must be initialized to YGEdgeVertical");
}
TEST(Bitfield, third_enum_can_be_set) {
auto bf = Bitfield<uint8_t, YGAlign, bool, YGEdge>{};
bf.at<2>() = YGEdgeVertical;
ASSERT_EQ(bf.at<0>(), YGAlignAuto);
ASSERT_EQ(bf.at<1>(), false);
ASSERT_EQ(bf.at<2>(), YGEdgeVertical);
}
TEST(Bitfield, initializing_values_does_not_spill_over) {
constexpr auto bf = Bitfield<uint8_t, YGAlign, YGEdge, bool>{
(YGAlign) 0, (YGEdge) 0xffffff, false};
ASSERT_EQ(bf.at<0>(), (YGAlign) 0);
ASSERT_EQ(bf.at<1>(), 0xf);
ASSERT_EQ(bf.at<2>(), false);
static_assert(bf.at<0>() == 0, "first enum member must be initialized to 0");
static_assert(
bf.at<1>() == 0xf, "second member must be initialized to YGEdgeVertical");
static_assert(
bf.at<2>() == false, "boolean member must be initialized to false");
}
TEST(Bitfield, setting_values_does_not_spill_over) {
auto bf = Bitfield<uint8_t, YGAlign, YGEdge, bool>{};
bf.at<1>() = (YGEdge) 0xffffff;
ASSERT_EQ(bf.at<0>(), 0);
ASSERT_EQ(bf.at<1>(), 0xf);
ASSERT_EQ(bf.at<2>(), false);
}
} // namespace yoga
} // namespace facebook

View File

@@ -605,3 +605,121 @@ TEST(YogaTest, flex_grow_less_than_factor_one) {
YGConfigFree(config); YGConfigFree(config);
} }
TEST(YogaTest, flex_shrink_min_width) {
const YGConfigRef config = YGConfigNew();
YGConfigSetUseWebDefaults(config, true);
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetMinWidth(root_child0, 301);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetMinWidth(root_child1, 25);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child2, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeInsertChild(root, root_child2, 2);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(401, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(99, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, flex_shrink_flex_grow_min_width) {
const YGConfigRef config = YGConfigNew();
YGConfigSetUseWebDefaults(config, true);
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
YGNodeStyleSetFlexGrow(root_child0, 0);
YGNodeStyleSetFlexShrink(root_child0, 1);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetMinWidth(root_child0, 301);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetFlexGrow(root_child1, 1);
YGNodeStyleSetFlexShrink(root_child1, 1);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetMinWidth(root_child1, 25);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child2, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeStyleSetFlexShrink(root_child2, 1);
YGNodeStyleSetFlexGrow(root_child2, 1);
YGNodeInsertChild(root, root_child2, 2);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(301, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(401, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(99, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -4,7 +4,8 @@
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*/ */
// @Generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html // @Generated by gentest/gentest.rb from
// gentest/fixtures/YGMarginTest.html
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <yoga/Yoga.h> #include <yoga/Yoga.h>
@@ -1714,3 +1715,111 @@ TEST(YogaTest, margin_auto_left_stretching_child) {
YGConfigFree(config); YGConfigFree(config);
} }
TEST(YogaTest, margin_top_auto_overflow_parent) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 20);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetHeight(root_child0, 300);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetMarginAuto(root_child1, YGEdgeTop);
YGNodeStyleSetHeight(root_child1, 300);
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(20, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1));
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, margin_bottom_auto_overflow_parent) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 20);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetHeight(root_child0, 300);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetMarginAuto(root_child1, YGEdgeTop);
YGNodeStyleSetHeight(root_child1, 300);
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(20, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1));
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -580,7 +580,7 @@ TEST(YogaDeathTest, cannot_add_child_to_node_with_measure_func) {
root->setMeasureFunc(_measure); root->setMeasureFunc(_measure);
const YGNodeRef root_child0 = YGNodeNew(); const YGNodeRef root_child0 = YGNodeNew();
ASSERT_DEATH(YGNodeInsertChild(root, root_child0, 0), "Cannot add child.*"); ASSERT_THROW(YGNodeInsertChild(root, root_child0, 0), std::logic_error);
YGNodeFree(root_child0); YGNodeFree(root_child0);
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);
} }
@@ -589,7 +589,7 @@ TEST(YogaDeathTest, cannot_add_nonnull_measure_func_to_non_leaf_node) {
const YGNodeRef root = YGNodeNew(); const YGNodeRef root = YGNodeNew();
const YGNodeRef root_child0 = YGNodeNew(); const YGNodeRef root_child0 = YGNodeNew();
YGNodeInsertChild(root, root_child0, 0); YGNodeInsertChild(root, root_child0, 0);
ASSERT_DEATH(root->setMeasureFunc(_measure), "Cannot set measure function.*"); ASSERT_THROW(root->setMeasureFunc(_measure), std::logic_error);
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);
} }
@@ -654,6 +654,19 @@ static YGSize _measure_90_10(
}; };
} }
static YGSize _measure_100_100(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
return YGSize{
.width = 100,
.height = 100,
};
}
TEST(YogaTest, percent_with_text_node) { TEST(YogaTest, percent_with_text_node) {
const YGConfigRef config = YGConfigNew(); const YGConfigRef config = YGConfigNew();
@@ -686,9 +699,211 @@ TEST(YogaTest, percent_with_text_node) {
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1)); ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_margin_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetMargin(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetMargin(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child2, 100);
YGNodeStyleSetHeight(root_child2, 100);
YGNodeStyleSetMarginPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child3, 100);
YGNodeStyleSetHeight(root_child3, 100);
YGNodeStyleSetMarginPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, 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(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_padding_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
YGNodeStyleSetAlignContent(root, YGAlignFlexStart);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetPadding(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, 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(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, percent_padding_and_percent_margin_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
YGNodeStyleSetAlignContent(root, YGAlignFlexStart);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child0, 100);
YGNodeStyleSetHeight(root_child0, 100);
YGNodeStyleSetPadding(root_child0, YGEdgeTop, 0);
root_child0->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root_child1, 100);
YGNodeStyleSetHeight(root_child1, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100);
root_child1->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child2, YGEdgeTop, 10);
YGNodeStyleSetMarginPercent(root_child2, YGEdgeTop, 10);
root_child2->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child2, 2);
const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
YGNodeStyleSetPaddingPercent(root_child3, YGEdgeTop, 20);
YGNodeStyleSetMarginPercent(root_child3, YGEdgeTop, 20);
root_child3->setMeasureFunc(_measure_100_100);
YGNodeInsertChild(root, root_child3, 3);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(500, 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(100, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2));
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child3));
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);

View File

@@ -1295,3 +1295,82 @@ TEST(YogaTest, min_max_percent_no_width_height) {
YGConfigFree(config); YGConfigFree(config);
} }
static YGSize _measureCk_test_label_shrink_based_on_height(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
if (heightMode == YGMeasureModeAtMost) {
return YGSize{
.width = 290,
.height = 103,
};
} else {
return YGSize{
.width = 290,
.height = height,
};
}
}
TEST(YogaTest, min_max_percent_margin_percent_no_width_height) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 320);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetHeight(root_child0_child0, 450);
YGNodeInsertChild(root_child0, root_child0_child0, 0);
const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow);
YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeTop, 5);
YGNodeStyleSetMaxHeightPercent(root_child0_child0_child0, 10);
YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
const YGNodeRef root_child0_child0_child0_child0 =
YGNodeNewWithConfig(config);
YGNodeSetMeasureFunc(
root_child0_child0_child0_child0,
_measureCk_test_label_shrink_based_on_height);
YGNodeInsertChild(
root_child0_child0_child0, root_child0_child0_child0_child0, 0);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0_child0));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
ASSERT_FLOAT_EQ(16, YGNodeLayoutGetTop(root_child0_child0_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0_child0_child0));
ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(290, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -1193,3 +1193,81 @@ TEST(YogaTest, percent_absolute_position) {
YGConfigFree(config); YGConfigFree(config);
} }
static YGSize _measureCk_test_label_shrink_based_on_height(
YGNodeRef node,
float width,
YGMeasureMode widthMode,
float height,
YGMeasureMode heightMode) {
if (heightMode == YGMeasureModeAtMost) {
return YGSize{
.width = 290,
.height = 103,
};
} else {
return YGSize{
.width = 290,
.height = height,
};
}
}
TEST(YogaTest, margin_percent_with_measure_func) {
const YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 320);
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetHeight(root_child0_child0, 450);
YGNodeInsertChild(root_child0, root_child0_child0, 0);
const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow);
YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeTop, 5);
YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
const YGNodeRef root_child0_child0_child0_child0 =
YGNodeNewWithConfig(config);
YGNodeSetMeasureFunc(
root_child0_child0_child0_child0,
_measureCk_test_label_shrink_based_on_height);
YGNodeInsertChild(
root_child0_child0_child0, root_child0_child0_child0_child0, 0);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0_child0));
ASSERT_FLOAT_EQ(450, YGNodeLayoutGetHeight(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
ASSERT_FLOAT_EQ(16, YGNodeLayoutGetTop(root_child0_child0_child0));
ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root_child0_child0_child0));
ASSERT_FLOAT_EQ(103, YGNodeLayoutGetHeight(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(290, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(103, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -11,6 +11,21 @@ yoga_cxx_library(
deps = [yoga_dep(":yoga")], deps = [yoga_dep(":yoga")],
) )
yoga_cxx_library(
name = "testutil-jni",
srcs = ["src/main/cpp/testutil/testutil.cpp"],
header_namespace = "",
exported_headers = subdir_glob([("src/main/cpp/include", "yoga/testutil/testutil.h")]),
compiler_flags = LIBRARY_COMPILER_FLAGS,
platforms = ANDROID,
soname = "libyoga_testutil.$(ext)",
visibility = ["PUBLIC"],
deps = [
yoga_dep("java:jni"),
yoga_dep(":yoga"),
],
)
yoga_java_library( yoga_java_library(
name = "java", name = "java",
srcs = ["src/main/java/com/facebook/yoga/TestUtil.java"], srcs = ["src/main/java/com/facebook/yoga/TestUtil.java"],
@@ -32,7 +47,7 @@ yoga_cxx_library(
soname = "libyoga_testutil_jni.$(ext)", soname = "libyoga_testutil_jni.$(ext)",
visibility = ["PUBLIC"], visibility = ["PUBLIC"],
deps = [ deps = [
":testutil", ":testutil-jni",
FBJNI_TARGET, FBJNI_TARGET,
], ],
) )

View File

@@ -14,7 +14,7 @@ JSR_305_TARGET = "//lib/jsr-305:jsr-305"
JUNIT_TARGET = "//lib/junit:junit" JUNIT_TARGET = "//lib/junit:junit"
PROGRUARD_ANNOTATIONS_TARGET = "//java/proguard-annotations/src/main/java/com/facebook/proguard/annotations:annotations" PROGUARD_ANNOTATIONS_TARGET = "//java/proguard-annotations/src/main/java/com/facebook/proguard/annotations:annotations"
SOLOADER_TARGET = "//lib/soloader:soloader" SOLOADER_TARGET = "//lib/soloader:soloader"
@@ -202,6 +202,9 @@ def yoga_prebuilt_cxx_library(*args, **kwargs):
def yoga_prebuilt_jar(*args, **kwargs): def yoga_prebuilt_jar(*args, **kwargs):
native.prebuilt_jar(*args, **kwargs) native.prebuilt_jar(*args, **kwargs)
def yoga_prebuilt_aar(*args, **kwargs):
native.android_prebuilt_aar(*args, **kwargs)
def is_apple_platform(): def is_apple_platform():
return True return True

View File

@@ -32,6 +32,6 @@
"develop": "gatsby develop" "develop": "gatsby develop"
}, },
"devDependencies": { "devDependencies": {
"prettier": "1.17.0" "prettier": "1.19.1"
} }
} }

View File

@@ -47,8 +47,8 @@ function dipOrPercent(value) {
return value === 'auto' return value === 'auto'
? 'Auto' ? 'Auto'
: typeof value === 'string' && /%$/.test(value) : typeof value === 'string' && /%$/.test(value)
? 'Percent' ? 'Percent'
: 'Dip'; : 'Dip';
} }
function getValue(value) { function getValue(value) {

View File

@@ -51,7 +51,10 @@
} }
.Editor .ant-tabs-tabpane { .Editor .ant-tabs-tabpane {
overflow-y: scroll; overflow-y: auto;
min-height: 320px;
height: 100%;
max-height: 25vh;
padding: 15px; padding: 15px;
} }

View File

@@ -196,7 +196,7 @@ export default class Editor extends Component<Props> {
onChange={this.props.onChangeLayout} onChange={this.props.onChangeLayout}
/> />
</TabPane> </TabPane>
<TabPane tab="Layout" key="3"> <TabPane tab="Layout" key="3" className="ant-tabs-tabpane">
<h2> <h2>
Width &times; Height Width &times; Height
<InfoText doclink="/docs/width-height"> <InfoText doclink="/docs/width-height">

View File

@@ -52,9 +52,7 @@ export default class URLShortener extends Component<{}, State> {
} }
fetch( fetch(
`https://cors-anywhere.herokuapp.com/tinyurl.com/api-create.php?url=${ `https://cors-anywhere.herokuapp.com/tinyurl.com/api-create.php?url=${window.location.href}`,
window.location.href
}`,
) )
.then(res => res.text()) .then(res => res.text())
.then(shortURL => this.setState({shortURL, loading: false})) .then(shortURL => this.setState({shortURL, loading: false}))

View File

@@ -49,17 +49,16 @@ export default ({data}) => (
({node}) => ({node}) =>
node.fileAbsolutePath.indexOf(`/${category}/`) > -1, node.fileAbsolutePath.indexOf(`/${category}/`) > -1,
) )
.map( .map(({node}) =>
({node}) => node.frontmatter.redirect ? (
node.frontmatter.redirect ? ( <a key={node.id} href={node.frontmatter.path}>
<a key={node.id} href={node.frontmatter.path}> {node.frontmatter.title}
{node.frontmatter.title} </a>
</a> ) : (
) : ( <Link key={node.id} to={node.frontmatter.path}>
<Link key={node.id} to={node.frontmatter.path}> {node.frontmatter.title}
{node.frontmatter.title} </Link>
</Link> ),
),
)} )}
</Col> </Col>
), ),

View File

@@ -6978,10 +6978,10 @@ preserve@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettier@1.17.0: prettier@1.19.1:
version "1.17.0" version "1.19.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.17.0.tgz#53b303676eed22cc14a9f0cec09b477b3026c008" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
integrity sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw== integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
pretty-bytes@^4.0.2: pretty-bytes@^4.0.2:
version "4.0.2" version "4.0.2"

66
yoga/BitUtils.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <cstdio>
#include <cstdint>
#include "YGEnums.h"
namespace facebook {
namespace yoga {
namespace detail {
constexpr size_t log2ceilFn(size_t n) {
return n < 1 ? 0 : (1 + log2ceilFn(n / 2));
}
constexpr int mask(size_t bitWidth, size_t index) {
return ((1 << bitWidth) - 1) << index;
}
// The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL
template <typename Enum>
constexpr size_t bitWidthFn() {
static_assert(
enums::count<Enum>() > 0, "Enums must have at least one entries");
return log2ceilFn(enums::count<Enum>() - 1);
}
template <typename Enum>
constexpr Enum getEnumData(int flags, size_t index) {
return static_cast<Enum>((flags & mask(bitWidthFn<Enum>(), index)) >> index);
}
template <typename Enum>
void setEnumData(uint32_t& flags, size_t index, int newValue) {
flags = (flags & ~mask(bitWidthFn<Enum>(), index)) |
((newValue << index) & (mask(bitWidthFn<Enum>(), index)));
}
template <typename Enum>
void setEnumData(uint8_t& flags, size_t index, int newValue) {
flags = (flags & ~mask(bitWidthFn<Enum>(), index)) |
((newValue << index) & (mask(bitWidthFn<Enum>(), index)));
}
constexpr bool getBooleanData(int flags, size_t index) {
return (flags >> index) & 1;
}
inline void setBooleanData(uint8_t& flags, size_t index, bool value) {
if (value) {
flags |= 1 << index;
} else {
flags &= ~(1 << index);
}
}
} // namespace detail
} // namespace yoga
} // namespace facebook

View File

@@ -1,145 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <cstddef>
#include <limits>
#include <type_traits>
#include <yoga/YGEnums.h>
namespace facebook {
namespace yoga {
namespace detail {
constexpr size_t log2ceil(size_t n) {
return n < 1 ? 0 : (1 + log2ceil(n / 2));
}
// The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL
template <typename Enum>
constexpr size_t bitWidth() {
static_assert(
enums::count<Enum>() > 0, "Enums must have at least one entries");
return log2ceil(enums::count<Enum>() - 1);
}
// Number of bits needed for a boolean
template <>
constexpr size_t bitWidth<bool>() {
return 1;
}
template <typename U, typename... Ts>
struct BitTraits {};
template <typename U>
struct BitTraits<U> {
// Base cases
static constexpr size_t width(size_t) { return 0; }
static constexpr size_t shift(size_t) { return 0; }
};
template <typename U, typename T, typename... Ts>
struct BitTraits<U, T, Ts...> {
using Rest = BitTraits<U, Ts...>;
static constexpr size_t width(size_t idx) {
return idx == 0 ? bitWidth<T>() : Rest::width(idx - 1);
}
static constexpr size_t shift(size_t idx) {
return idx == 0 ? Rest::width(0) + Rest::shift(0) : Rest::shift(idx - 1);
}
static constexpr U mask(size_t idx) {
return ((U{1} << width(idx)) - 1) << shift(idx);
}
};
template <size_t Idx, typename T, typename... Ts>
struct IndexedType {
using Type = typename IndexedType<Idx - 1, Ts...>::Type;
};
template <typename T, typename... Ts>
struct IndexedType<0, T, Ts...> {
using Type = T;
};
} // namespace detail
template <typename Storage, typename... Fields>
class Bitfield {
static_assert(
std::is_integral<Storage>::value,
"Bitfield needs an integral storage type");
static_assert(
std::is_unsigned<Storage>::value,
"Bitfield needs an unsigned storage type");
static_assert(sizeof...(Fields) > 0, "Bitfield needs at least one member");
using BitTraits = detail::BitTraits<Storage, Fields...>;
#if !defined(_MSC_VER) || _MSC_VER > 1914
static_assert(
BitTraits::shift(0) + BitTraits::width(0) <=
std::numeric_limits<Storage>::digits,
"Specified storage type is too narrow to hold all types");
#endif
template <size_t Idx>
using TypeAt = typename detail::IndexedType<Idx, Fields...>::Type;
template <size_t Idx, typename Value, typename... Values>
static constexpr Storage initStorage(Value value, Values... values) {
return ((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx)) |
initStorage<Idx + 1, Values...>(values...);
}
template <size_t Idx>
static constexpr Storage initStorage() {
return Storage{0};
}
Storage storage_ = 0;
public:
template <size_t Idx>
class Ref {
Bitfield& bitfield_;
public:
Ref(Bitfield& bitfield) : bitfield_(bitfield) {}
Ref& operator=(TypeAt<Idx> value) {
bitfield_.storage_ = (bitfield_.storage_ & ~BitTraits::mask(Idx)) |
((value << BitTraits::shift(Idx)) & BitTraits::mask(Idx));
return *this;
}
operator TypeAt<Idx>() const {
return const_cast<const Bitfield&>(bitfield_).at<Idx>();
}
};
constexpr Bitfield() = default;
constexpr Bitfield(Fields... values) : storage_{initStorage<0>(values...)} {}
template <size_t Idx>
constexpr TypeAt<Idx> at() const {
return static_cast<TypeAt<Idx>>(
(storage_ & BitTraits::mask(Idx)) >> BitTraits::shift(Idx));
}
template <size_t Idx>
Ref<Idx> at() {
return {*this};
}
};
} // namespace yoga
} // namespace facebook

View File

@@ -65,3 +65,7 @@ YGFloatOptional YGFloatOptionalMax(YGFloatOptional op1, YGFloatOptional op2) {
} }
return op1.isUndefined() ? op2 : op1; return op1.isUndefined() ? op2 : op1;
} }
void throwLogicalErrorWithMessage(const char* message) {
throw std::logic_error(message);
}

View File

@@ -141,3 +141,5 @@ inline YGFloatOptional YGResolveValueMargin(
const float ownerSize) { const float ownerSize) {
return value.isAuto() ? YGFloatOptional{0} : YGResolveValue(value, ownerSize); return value.isAuto() ? YGFloatOptional{0} : YGResolveValue(value, ownerSize);
} }
void throwLogicalErrorWithMessage(const char* message);

View File

@@ -6,10 +6,12 @@
*/ */
#pragma once #pragma once
#include "Bitfield.h" #include "BitUtils.h"
#include "YGFloatOptional.h" #include "YGFloatOptional.h"
#include "Yoga-internal.h" #include "Yoga-internal.h"
using namespace facebook::yoga;
struct YGLayout { struct YGLayout {
std::array<float, 4> position = {}; std::array<float, 4> position = {};
std::array<float, 2> dimensions = {{YGUndefined, YGUndefined}}; std::array<float, 2> dimensions = {{YGUndefined, YGUndefined}};
@@ -18,12 +20,14 @@ struct YGLayout {
std::array<float, 4> padding = {}; std::array<float, 4> padding = {};
private: private:
static constexpr size_t directionIdx = 0; static constexpr size_t directionOffset = 0;
static constexpr size_t didUseLegacyFlagIdx = 1; static constexpr size_t didUseLegacyFlagOffset =
static constexpr size_t doesLegacyStretchFlagAffectsLayoutIdx = 2; directionOffset + facebook::yoga::detail::bitWidthFn<YGDirection>();
static constexpr size_t hadOverflowIdx = 3; static constexpr size_t doesLegacyStretchFlagAffectsLayoutOffset =
facebook::yoga::Bitfield<uint8_t, YGDirection, bool, bool, bool> flags_ = didUseLegacyFlagOffset + 1;
{YGDirectionInherit, false, false, false}; static constexpr size_t hadOverflowOffset =
doesLegacyStretchFlagAffectsLayoutOffset + 1;
uint8_t flags = 0;
public: public:
uint32_t computedFlexBasisGeneration = 0; uint32_t computedFlexBasisGeneration = 0;
@@ -32,7 +36,7 @@ public:
// Instead of recomputing the entire layout every single time, we cache some // Instead of recomputing the entire layout every single time, we cache some
// information to break early when nothing changed // information to break early when nothing changed
uint32_t generationCount = 0; uint32_t generationCount = 0;
YGDirection lastOwnerDirection = (YGDirection) -1; YGDirection lastOwnerDirection = YGDirectionInherit;
uint32_t nextCachedMeasurementsIndex = 0; uint32_t nextCachedMeasurementsIndex = 0;
std::array<YGCachedMeasurement, YG_MAX_CACHED_RESULT_COUNT> std::array<YGCachedMeasurement, YG_MAX_CACHED_RESULT_COUNT>
@@ -41,27 +45,41 @@ public:
YGCachedMeasurement cachedLayout = YGCachedMeasurement(); YGCachedMeasurement cachedLayout = YGCachedMeasurement();
YGDirection direction() const { return flags_.at<directionIdx>(); } YGDirection direction() const {
decltype(flags_)::Ref<directionIdx> direction() { return facebook::yoga::detail::getEnumData<YGDirection>(
return flags_.at<directionIdx>(); flags, directionOffset);
} }
bool didUseLegacyFlag() const { return flags_.at<didUseLegacyFlagIdx>(); } void setDirection(YGDirection direction) {
decltype(flags_)::Ref<didUseLegacyFlagIdx> didUseLegacyFlag() { facebook::yoga::detail::setEnumData<YGDirection>(
return flags_.at<didUseLegacyFlagIdx>(); flags, directionOffset, direction);
}
bool didUseLegacyFlag() const {
return facebook::yoga::detail::getBooleanData(
flags, didUseLegacyFlagOffset);
}
void setDidUseLegacyFlag(bool val) {
facebook::yoga::detail::setBooleanData(flags, didUseLegacyFlagOffset, val);
} }
bool doesLegacyStretchFlagAffectsLayout() const { bool doesLegacyStretchFlagAffectsLayout() const {
return flags_.at<doesLegacyStretchFlagAffectsLayoutIdx>(); return facebook::yoga::detail::getBooleanData(
} flags, doesLegacyStretchFlagAffectsLayoutOffset);
decltype(flags_)::Ref<doesLegacyStretchFlagAffectsLayoutIdx>
doesLegacyStretchFlagAffectsLayout() {
return flags_.at<doesLegacyStretchFlagAffectsLayoutIdx>();
} }
bool hadOverflow() const { return flags_.at<hadOverflowIdx>(); } void setDoesLegacyStretchFlagAffectsLayout(bool val) {
decltype(flags_)::Ref<hadOverflowIdx> hadOverflow() { facebook::yoga::detail::setBooleanData(
return flags_.at<hadOverflowIdx>(); flags, doesLegacyStretchFlagAffectsLayoutOffset, val);
}
bool hadOverflow() const {
return facebook::yoga::detail::getBooleanData(flags, hadOverflowOffset);
}
void setHadOverflow(bool hadOverflow) {
facebook::yoga::detail::setBooleanData(
flags, hadOverflowOffset, hadOverflow);
} }
bool operator==(YGLayout layout) const; bool operator==(YGLayout layout) const;

View File

@@ -16,7 +16,7 @@ using facebook::yoga::detail::CompactValue;
YGNode::YGNode(YGNode&& node) { YGNode::YGNode(YGNode&& node) {
context_ = node.context_; context_ = node.context_;
flags_ = node.flags_; flags = node.flags;
measure_ = node.measure_; measure_ = node.measure_;
baseline_ = node.baseline_; baseline_ = node.baseline_;
print_ = node.print_; print_ = node.print_;
@@ -29,7 +29,7 @@ YGNode::YGNode(YGNode&& node) {
config_ = node.config_; config_ = node.config_;
resolvedDimensions_ = node.resolvedDimensions_; resolvedDimensions_ = node.resolvedDimensions_;
for (auto c : children_) { for (auto c : children_) {
c->setOwner(c); c->setOwner(this);
} }
} }
@@ -42,7 +42,7 @@ YGNode::YGNode(const YGNode& node, YGConfigRef config) : YGNode{node} {
void YGNode::print(void* printContext) { void YGNode::print(void* printContext) {
if (print_.noContext != nullptr) { if (print_.noContext != nullptr) {
if (flags_.at<printUsesContext_>()) { if (facebook::yoga::detail::getBooleanData(flags, printUsesContext_)) {
print_.withContext(this, printContext); print_.withContext(this, printContext);
} else { } else {
print_.noContext(this); print_.noContext(this);
@@ -148,14 +148,14 @@ YGSize YGNode::measure(
YGMeasureMode heightMode, YGMeasureMode heightMode,
void* layoutContext) { void* layoutContext) {
return flags_.at<measureUsesContext_>() return facebook::yoga::detail::getBooleanData(flags, measureUsesContext_)
? measure_.withContext( ? measure_.withContext(
this, width, widthMode, height, heightMode, layoutContext) this, width, widthMode, height, heightMode, layoutContext)
: measure_.noContext(this, width, widthMode, height, heightMode); : measure_.noContext(this, width, widthMode, height, heightMode);
} }
float YGNode::baseline(float width, float height, void* layoutContext) { float YGNode::baseline(float width, float height, void* layoutContext) {
return flags_.at<baselineUsesContext_>() return facebook::yoga::detail::getBooleanData(flags, baselineUsesContext_)
? baseline_.withContext(this, width, height, layoutContext) ? baseline_.withContext(this, width, height, layoutContext)
: baseline_.noContext(this, width, height); : baseline_.noContext(this, width, height);
} }
@@ -166,7 +166,7 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) {
if (measureFunc.noContext == nullptr) { if (measureFunc.noContext == nullptr) {
// TODO: t18095186 Move nodeType to opt-in function and mark appropriate // TODO: t18095186 Move nodeType to opt-in function and mark appropriate
// places in Litho // places in Litho
flags_.at<nodeType_>() = YGNodeTypeDefault; setNodeType(YGNodeTypeDefault);
} else { } else {
YGAssertWithNode( YGAssertWithNode(
this, this,
@@ -182,14 +182,14 @@ void YGNode::setMeasureFunc(decltype(YGNode::measure_) measureFunc) {
} }
void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) {
flags_.at<measureUsesContext_>() = false; facebook::yoga::detail::setBooleanData(flags, measureUsesContext_, false);
decltype(YGNode::measure_) m; decltype(YGNode::measure_) m;
m.noContext = measureFunc; m.noContext = measureFunc;
setMeasureFunc(m); setMeasureFunc(m);
} }
YOGA_EXPORT void YGNode::setMeasureFunc(MeasureWithContextFn measureFunc) { YOGA_EXPORT void YGNode::setMeasureFunc(MeasureWithContextFn measureFunc) {
flags_.at<measureUsesContext_>() = true; facebook::yoga::detail::setBooleanData(flags, measureUsesContext_, true);
decltype(YGNode::measure_) m; decltype(YGNode::measure_) m;
m.withContext = measureFunc; m.withContext = measureFunc;
setMeasureFunc(m); setMeasureFunc(m);
@@ -208,10 +208,10 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) {
} }
void YGNode::setDirty(bool isDirty) { void YGNode::setDirty(bool isDirty) {
if (isDirty == flags_.at<isDirty_>()) { if (isDirty == facebook::yoga::detail::getBooleanData(flags, isDirty_)) {
return; return;
} }
flags_.at<isDirty_>() = isDirty; facebook::yoga::detail::setBooleanData(flags, isDirty_, isDirty);
if (isDirty && dirtied_) { if (isDirty && dirtied_) {
dirtied_(this); dirtied_(this);
} }
@@ -232,7 +232,7 @@ void YGNode::removeChild(uint32_t index) {
} }
void YGNode::setLayoutDirection(YGDirection direction) { void YGNode::setLayoutDirection(YGDirection direction) {
layout_.direction() = direction; layout_.setDirection(direction);
} }
void YGNode::setLayoutMargin(float margin, int index) { void YGNode::setLayoutMargin(float margin, int index) {
@@ -270,7 +270,7 @@ void YGNode::setLayoutMeasuredDimension(float measuredDimension, int index) {
} }
void YGNode::setLayoutHadOverflow(bool hadOverflow) { void YGNode::setLayoutHadOverflow(bool hadOverflow) {
layout_.hadOverflow() = hadOverflow; layout_.setHadOverflow(hadOverflow);
} }
void YGNode::setLayoutDimension(float dimension, int index) { void YGNode::setLayoutDimension(float dimension, int index) {
@@ -351,7 +351,9 @@ YGValue YGNode::resolveFlexBasisPtr() const {
return flexBasis; return flexBasis;
} }
if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) {
return flags_.at<useWebDefaults_>() ? YGValueAuto : YGValueZero; return facebook::yoga::detail::getBooleanData(flags, useWebDefaults_)
? YGValueAuto
: YGValueZero;
} }
return YGValueAuto; return YGValueAuto;
} }
@@ -390,7 +392,7 @@ void YGNode::cloneChildrenIfNeeded(void* cloneContext) {
} }
void YGNode::markDirtyAndPropogate() { void YGNode::markDirtyAndPropogate() {
if (!flags_.at<isDirty_>()) { if (!facebook::yoga::detail::getBooleanData(flags, isDirty_)) {
setDirty(true); setDirty(true);
setLayoutComputedFlexBasis(YGFloatOptional()); setLayoutComputedFlexBasis(YGFloatOptional());
if (owner_) { if (owner_) {
@@ -400,7 +402,7 @@ void YGNode::markDirtyAndPropogate() {
} }
void YGNode::markDirtyAndPropogateDownwards() { void YGNode::markDirtyAndPropogateDownwards() {
flags_.at<isDirty_>() = true; facebook::yoga::detail::setBooleanData(flags, isDirty_, true);
for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) { for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) {
childNode->markDirtyAndPropogateDownwards(); childNode->markDirtyAndPropogateDownwards();
}); });
@@ -427,12 +429,13 @@ float YGNode::resolveFlexShrink() const {
if (!style_.flexShrink().isUndefined()) { if (!style_.flexShrink().isUndefined()) {
return style_.flexShrink().unwrap(); return style_.flexShrink().unwrap();
} }
if (!flags_.at<useWebDefaults_>() && !style_.flex().isUndefined() && if (!facebook::yoga::detail::getBooleanData(flags, useWebDefaults_) &&
style_.flex().unwrap() < 0.0f) { !style_.flex().isUndefined() && style_.flex().unwrap() < 0.0f) {
return -style_.flex().unwrap(); return -style_.flex().unwrap();
} }
return flags_.at<useWebDefaults_>() ? kWebDefaultFlexShrink return facebook::yoga::detail::getBooleanData(flags, useWebDefaults_)
: kDefaultFlexShrink; ? kWebDefaultFlexShrink
: kDefaultFlexShrink;
} }
bool YGNode::isNodeFlexible() { bool YGNode::isNodeFlexible() {
@@ -536,11 +539,11 @@ bool YGNode::didUseLegacyFlag() {
void YGNode::setLayoutDoesLegacyFlagAffectsLayout( void YGNode::setLayoutDoesLegacyFlagAffectsLayout(
bool doesLegacyFlagAffectsLayout) { bool doesLegacyFlagAffectsLayout) {
layout_.doesLegacyStretchFlagAffectsLayout() = doesLegacyFlagAffectsLayout; layout_.setDoesLegacyStretchFlagAffectsLayout(doesLegacyFlagAffectsLayout);
} }
void YGNode::setLayoutDidUseLegacyFlag(bool didUseLegacyFlag) { void YGNode::setLayoutDidUseLegacyFlag(bool didUseLegacyFlag) {
layout_.didUseLegacyFlag() = didUseLegacyFlag; layout_.setDidUseLegacyFlag(didUseLegacyFlag);
} }
bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const { bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const {
@@ -577,7 +580,8 @@ void YGNode::reset() {
clearChildren(); clearChildren();
auto webDefaults = flags_.at<useWebDefaults_>(); auto webDefaults =
facebook::yoga::detail::getBooleanData(flags, useWebDefaults_);
*this = YGNode{getConfig()}; *this = YGNode{getConfig()};
if (webDefaults) { if (webDefaults) {
useWebDefaults(); useWebDefaults();

View File

@@ -6,9 +6,12 @@
*/ */
#pragma once #pragma once
#ifdef __cplusplus
#include <cstdint> #include <cstdint>
#include <stdio.h> #include <stdio.h>
#include "Bitfield.h" #include "BitUtils.h"
#include "CompactValue.h" #include "CompactValue.h"
#include "YGConfig.h" #include "YGConfig.h"
#include "YGLayout.h" #include "YGLayout.h"
@@ -35,10 +38,7 @@ private:
static constexpr size_t useWebDefaults_ = 7; static constexpr size_t useWebDefaults_ = 7;
void* context_ = nullptr; void* context_ = nullptr;
using Flags = facebook::yoga:: uint8_t flags = 1;
Bitfield<uint8_t, bool, bool, bool, YGNodeType, bool, bool, bool, bool>;
Flags flags_ =
{true, false, false, YGNodeTypeDefault, false, false, false, false};
uint8_t reserved_ = 0; uint8_t reserved_ = 0;
union { union {
YGMeasureFunc noContext; YGMeasureFunc noContext;
@@ -70,13 +70,13 @@ private:
void setBaselineFunc(decltype(baseline_)); void setBaselineFunc(decltype(baseline_));
void useWebDefaults() { void useWebDefaults() {
flags_.at<useWebDefaults_>() = true; facebook::yoga::detail::setBooleanData(flags, useWebDefaults_, true);
style_.flexDirection() = YGFlexDirectionRow; style_.flexDirection() = YGFlexDirectionRow;
style_.alignContent() = YGAlignStretch; style_.alignContent() = YGAlignStretch;
} }
// DANGER DANGER DANGER! // DANGER DANGER DANGER!
// If the the node assigned to has children, we'd either have to deallocate // If the node assigned to has children, we'd either have to deallocate
// them (potentially incorrect) or ignore them (danger of leaks). Only ever // them (potentially incorrect) or ignore them (danger of leaks). Only ever
// use this after checking that there are no children. // use this after checking that there are no children.
// DO NOT CHANGE THE VISIBILITY OF THIS METHOD! // DO NOT CHANGE THE VISIBILITY OF THIS METHOD!
@@ -114,9 +114,13 @@ public:
void print(void*); void print(void*);
bool getHasNewLayout() const { return flags_.at<hasNewLayout_>(); } bool getHasNewLayout() const {
return facebook::yoga::detail::getBooleanData(flags, hasNewLayout_);
}
YGNodeType getNodeType() const { return flags_.at<nodeType_>(); } YGNodeType getNodeType() const {
return facebook::yoga::detail::getEnumData<YGNodeType>(flags, nodeType_);
}
bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; } bool hasMeasureFunc() const noexcept { return measure_.noContext != nullptr; }
@@ -142,7 +146,9 @@ public:
uint32_t getLineIndex() const { return lineIndex_; } uint32_t getLineIndex() const { return lineIndex_; }
bool isReferenceBaseline() { return flags_.at<isReferenceBaseline_>(); } bool isReferenceBaseline() {
return facebook::yoga::detail::getBooleanData(flags, isReferenceBaseline_);
}
// returns the YGNodeRef that owns this YGNode. An owner is used to identify // returns the YGNodeRef that owns this YGNode. An owner is used to identify
// the YogaTree that a YGNode belongs to. This method will return the parent // the YogaTree that a YGNode belongs to. This method will return the parent
@@ -175,7 +181,9 @@ public:
YGConfigRef getConfig() const { return config_; } YGConfigRef getConfig() const { return config_; }
bool isDirty() const { return flags_.at<isDirty_>(); } bool isDirty() const {
return facebook::yoga::detail::getBooleanData(flags, isDirty_);
}
std::array<YGValue, 2> getResolvedDimensions() const { std::array<YGValue, 2> getResolvedDimensions() const {
return resolvedDimensions_; return resolvedDimensions_;
@@ -223,19 +231,22 @@ public:
void setPrintFunc(YGPrintFunc printFunc) { void setPrintFunc(YGPrintFunc printFunc) {
print_.noContext = printFunc; print_.noContext = printFunc;
flags_.at<printUsesContext_>() = false; facebook::yoga::detail::setBooleanData(flags, printUsesContext_, false);
} }
void setPrintFunc(PrintWithContextFn printFunc) { void setPrintFunc(PrintWithContextFn printFunc) {
print_.withContext = printFunc; print_.withContext = printFunc;
flags_.at<printUsesContext_>() = true; facebook::yoga::detail::setBooleanData(flags, printUsesContext_, true);
} }
void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); } void setPrintFunc(std::nullptr_t) { setPrintFunc(YGPrintFunc{nullptr}); }
void setHasNewLayout(bool hasNewLayout) { void setHasNewLayout(bool hasNewLayout) {
flags_.at<hasNewLayout_>() = hasNewLayout; facebook::yoga::detail::setBooleanData(flags, hasNewLayout_, hasNewLayout);
} }
void setNodeType(YGNodeType nodeType) { flags_.at<nodeType_>() = nodeType; } void setNodeType(YGNodeType nodeType) {
return facebook::yoga::detail::setEnumData<YGNodeType>(
flags, nodeType_, nodeType);
}
void setMeasureFunc(YGMeasureFunc measureFunc); void setMeasureFunc(YGMeasureFunc measureFunc);
void setMeasureFunc(MeasureWithContextFn); void setMeasureFunc(MeasureWithContextFn);
@@ -244,11 +255,11 @@ public:
} }
void setBaselineFunc(YGBaselineFunc baseLineFunc) { void setBaselineFunc(YGBaselineFunc baseLineFunc) {
flags_.at<baselineUsesContext_>() = false; facebook::yoga::detail::setBooleanData(flags, baselineUsesContext_, false);
baseline_.noContext = baseLineFunc; baseline_.noContext = baseLineFunc;
} }
void setBaselineFunc(BaselineWithContextFn baseLineFunc) { void setBaselineFunc(BaselineWithContextFn baseLineFunc) {
flags_.at<baselineUsesContext_>() = true; facebook::yoga::detail::setBooleanData(flags, baselineUsesContext_, true);
baseline_.withContext = baseLineFunc; baseline_.withContext = baseLineFunc;
} }
void setBaselineFunc(std::nullptr_t) { void setBaselineFunc(std::nullptr_t) {
@@ -264,7 +275,8 @@ public:
void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; } void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; }
void setIsReferenceBaseline(bool isReferenceBaseline) { void setIsReferenceBaseline(bool isReferenceBaseline) {
flags_.at<isReferenceBaseline_>() = isReferenceBaseline; facebook::yoga::detail::setBooleanData(
flags, isReferenceBaseline_, isReferenceBaseline);
} }
void setOwner(YGNodeRef owner) { owner_ = owner; } void setOwner(YGNodeRef owner) { owner_ = owner; }
@@ -321,3 +333,5 @@ public:
bool isLayoutTreeEqualToNode(const YGNode& node) const; bool isLayoutTreeEqualToNode(const YGNode& node) const;
void reset(); void reset();
}; };
#endif

View File

@@ -6,16 +6,19 @@
*/ */
#pragma once #pragma once
#ifdef __cplusplus
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <type_traits> #include <type_traits>
#include "Bitfield.h"
#include "CompactValue.h" #include "CompactValue.h"
#include "YGEnums.h" #include "YGEnums.h"
#include "YGFloatOptional.h" #include "YGFloatOptional.h"
#include "Yoga-internal.h" #include "Yoga-internal.h"
#include "Yoga.h" #include "Yoga.h"
#include "BitUtils.h"
class YOGA_EXPORT YGStyle { class YOGA_EXPORT YGStyle {
template <typename Enum> template <typename Enum>
@@ -27,6 +30,19 @@ public:
using Dimensions = Values<YGDimension>; using Dimensions = Values<YGDimension>;
using Edges = Values<YGEdge>; using Edges = Values<YGEdge>;
template <typename T>
struct BitfieldRef {
YGStyle& style;
size_t offset;
operator T() const {
return facebook::yoga::detail::getEnumData<T>(style.flags, offset);
}
BitfieldRef<T>& operator=(T x) {
facebook::yoga::detail::setEnumData<T>(style.flags, offset, x);
return *this;
}
};
template <typename T, T YGStyle::*Prop> template <typename T, T YGStyle::*Prop>
struct Ref { struct Ref {
YGStyle& style; YGStyle& style;
@@ -60,43 +76,35 @@ public:
CompactValue operator[](Idx idx) const { return (style.*Prop)[idx]; } CompactValue operator[](Idx idx) const { return (style.*Prop)[idx]; }
}; };
YGStyle() = default; YGStyle() {
alignContent() = YGAlignFlexStart;
alignItems() = YGAlignStretch;
}
~YGStyle() = default; ~YGStyle() = default;
private: private:
static constexpr size_t directionIdx = 0; static constexpr size_t directionOffset = 0;
static constexpr size_t flexDirectionIdx = 1; static constexpr size_t flexdirectionOffset =
static constexpr size_t justifyContentIdx = 2; directionOffset + facebook::yoga::detail::bitWidthFn<YGDirection>();
static constexpr size_t alignContentIdx = 3; static constexpr size_t justifyContentOffset = flexdirectionOffset +
static constexpr size_t alignItemsIdx = 4; facebook::yoga::detail::bitWidthFn<YGFlexDirection>();
static constexpr size_t alignSelfIdx = 5; static constexpr size_t alignContentOffset =
static constexpr size_t positionTypeIdx = 6; justifyContentOffset + facebook::yoga::detail::bitWidthFn<YGJustify>();
static constexpr size_t flexWrapIdx = 7; static constexpr size_t alignItemsOffset =
static constexpr size_t overflowIdx = 8; alignContentOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
static constexpr size_t displayIdx = 9; static constexpr size_t alignSelfOffset =
using Flags = facebook::yoga::Bitfield< alignItemsOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
uint32_t, static constexpr size_t positionTypeOffset =
YGDirection, alignSelfOffset + facebook::yoga::detail::bitWidthFn<YGAlign>();
YGFlexDirection, static constexpr size_t flexWrapOffset =
YGJustify, positionTypeOffset + facebook::yoga::detail::bitWidthFn<YGPositionType>();
YGAlign, static constexpr size_t overflowOffset =
YGAlign, flexWrapOffset + facebook::yoga::detail::bitWidthFn<YGWrap>();
YGAlign, static constexpr size_t displayOffset =
YGPositionType, overflowOffset + facebook::yoga::detail::bitWidthFn<YGOverflow>();
YGWrap,
YGOverflow, uint32_t flags = 0;
YGDisplay>;
Flags flags_ = {YGDirectionInherit,
YGFlexDirectionColumn,
YGJustifyFlexStart,
YGAlignFlexStart,
YGAlignStretch,
YGAlignAuto,
YGPositionTypeRelative,
YGWrapNoWrap,
YGOverflowVisible,
YGDisplayFlex};
YGFloatOptional flex_ = {}; YGFloatOptional flex_ = {};
YGFloatOptional flexGrow_ = {}; YGFloatOptional flexGrow_ = {};
YGFloatOptional flexShrink_ = {}; YGFloatOptional flexShrink_ = {};
@@ -115,45 +123,68 @@ public:
// for library users needing a type // for library users needing a type
using ValueRepr = std::remove_reference<decltype(margin_[0])>::type; using ValueRepr = std::remove_reference<decltype(margin_[0])>::type;
YGDirection direction() const { return flags_.at<directionIdx>(); } YGDirection direction() const {
Flags::Ref<directionIdx> direction() { return flags_.at<directionIdx>(); } return facebook::yoga::detail::getEnumData<YGDirection>(
flags, directionOffset);
}
BitfieldRef<YGDirection> direction() { return {*this, directionOffset}; }
YGFlexDirection flexDirection() const { YGFlexDirection flexDirection() const {
return flags_.at<flexDirectionIdx>(); return facebook::yoga::detail::getEnumData<YGFlexDirection>(
flags, flexdirectionOffset);
} }
Flags::Ref<flexDirectionIdx> flexDirection() { BitfieldRef<YGFlexDirection> flexDirection() {
return flags_.at<flexDirectionIdx>(); return {*this, flexdirectionOffset};
} }
YGJustify justifyContent() const { return flags_.at<justifyContentIdx>(); } YGJustify justifyContent() const {
Flags::Ref<justifyContentIdx> justifyContent() { return facebook::yoga::detail::getEnumData<YGJustify>(
return flags_.at<justifyContentIdx>(); flags, justifyContentOffset);
}
BitfieldRef<YGJustify> justifyContent() {
return {*this, justifyContentOffset};
} }
YGAlign alignContent() const { return flags_.at<alignContentIdx>(); } YGAlign alignContent() const {
Flags::Ref<alignContentIdx> alignContent() { return facebook::yoga::detail::getEnumData<YGAlign>(
return flags_.at<alignContentIdx>(); flags, alignContentOffset);
}
BitfieldRef<YGAlign> alignContent() { return {*this, alignContentOffset}; }
YGAlign alignItems() const {
return facebook::yoga::detail::getEnumData<YGAlign>(
flags, alignItemsOffset);
}
BitfieldRef<YGAlign> alignItems() { return {*this, alignItemsOffset}; }
YGAlign alignSelf() const {
return facebook::yoga::detail::getEnumData<YGAlign>(flags, alignSelfOffset);
}
BitfieldRef<YGAlign> alignSelf() { return {*this, alignSelfOffset}; }
YGPositionType positionType() const {
return facebook::yoga::detail::getEnumData<YGPositionType>(
flags, positionTypeOffset);
}
BitfieldRef<YGPositionType> positionType() {
return {*this, positionTypeOffset};
} }
YGAlign alignItems() const { return flags_.at<alignItemsIdx>(); } YGWrap flexWrap() const {
Flags::Ref<alignItemsIdx> alignItems() { return flags_.at<alignItemsIdx>(); } return facebook::yoga::detail::getEnumData<YGWrap>(flags, flexWrapOffset);
YGAlign alignSelf() const { return flags_.at<alignSelfIdx>(); }
Flags::Ref<alignSelfIdx> alignSelf() { return flags_.at<alignSelfIdx>(); }
YGPositionType positionType() const { return flags_.at<positionTypeIdx>(); }
Flags::Ref<positionTypeIdx> positionType() {
return flags_.at<positionTypeIdx>();
} }
BitfieldRef<YGWrap> flexWrap() { return {*this, flexWrapOffset}; }
YGWrap flexWrap() const { return flags_.at<flexWrapIdx>(); } YGOverflow overflow() const {
Flags::Ref<flexWrapIdx> flexWrap() { return flags_.at<flexWrapIdx>(); } return facebook::yoga::detail::getEnumData<YGOverflow>(
flags, overflowOffset);
}
BitfieldRef<YGOverflow> overflow() { return {*this, overflowOffset}; }
YGOverflow overflow() const { return flags_.at<overflowIdx>(); } YGDisplay display() const {
Flags::Ref<overflowIdx> overflow() { return flags_.at<overflowIdx>(); } return facebook::yoga::detail::getEnumData<YGDisplay>(flags, displayOffset);
}
YGDisplay display() const { return flags_.at<displayIdx>(); } BitfieldRef<YGDisplay> display() { return {*this, displayOffset}; }
Flags::Ref<displayIdx> display() { return flags_.at<displayIdx>(); }
YGFloatOptional flex() const { return flex_; } YGFloatOptional flex() const { return flex_; }
Ref<YGFloatOptional, &YGStyle::flex_> flex() { return {*this}; } Ref<YGFloatOptional, &YGStyle::flex_> flex() { return {*this}; }
@@ -201,3 +232,5 @@ YOGA_EXPORT bool operator==(const YGStyle& lhs, const YGStyle& rhs);
YOGA_EXPORT inline bool operator!=(const YGStyle& lhs, const YGStyle& rhs) { YOGA_EXPORT inline bool operator!=(const YGStyle& lhs, const YGStyle& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif

View File

@@ -11,6 +11,13 @@
#include "YGEnums.h" #include "YGEnums.h"
#include "YGMacros.h" #include "YGMacros.h"
#if defined(_MSC_VER) && defined(__clang__)
#define COMPILING_WITH_CLANG_ON_WINDOWS
#endif
#if defined(COMPILING_WITH_CLANG_ON_WINDOWS)
#include <limits>
constexpr float YGUndefined = std::numeric_limits<float>::quiet_NaN();
#else
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
// Not defined in MSVC++ // Not defined in MSVC++
@@ -20,6 +27,7 @@ static const uint32_t __nan = 0x7fc00000;
#endif #endif
#define YGUndefined NAN #define YGUndefined NAN
#endif
typedef struct YGValue { typedef struct YGValue {
float value; float value;
@@ -30,7 +38,10 @@ YOGA_EXPORT extern const YGValue YGValueAuto;
YOGA_EXPORT extern const YGValue YGValueUndefined; YOGA_EXPORT extern const YGValue YGValueUndefined;
YOGA_EXPORT extern const YGValue YGValueZero; YOGA_EXPORT extern const YGValue YGValueZero;
#if !defined(COMPILING_WITH_CLANG_ON_WINDOWS)
YG_EXTERN_C_END YG_EXTERN_C_END
#endif
#undef COMPILING_WITH_CLANG_ON_WINDOWS
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -54,10 +54,10 @@ struct YGCachedMeasurement {
float computedHeight; float computedHeight;
YGCachedMeasurement() YGCachedMeasurement()
: availableWidth(0), : availableWidth(-1),
availableHeight(0), availableHeight(-1),
widthMeasureMode((YGMeasureMode) -1), widthMeasureMode(YGMeasureModeUndefined),
heightMeasureMode((YGMeasureMode) -1), heightMeasureMode(YGMeasureModeUndefined),
computedWidth(-1), computedWidth(-1),
computedHeight(-1) {} computedHeight(-1) {}

View File

@@ -249,9 +249,6 @@ YOGA_EXPORT YGNodeRef YGNodeClone(YGNodeRef oldNode) {
static YGConfigRef YGConfigClone(const YGConfig& oldConfig) { static YGConfigRef YGConfigClone(const YGConfig& oldConfig) {
const YGConfigRef config = new YGConfig(oldConfig); const YGConfigRef config = new YGConfig(oldConfig);
YGAssert(config != nullptr, "Could not allocate memory for config"); YGAssert(config != nullptr, "Could not allocate memory for config");
if (config == nullptr) {
abort();
}
gConfigInstanceCount++; gConfigInstanceCount++;
return config; return config;
} }
@@ -386,6 +383,14 @@ YOGA_EXPORT void YGNodeInsertChild(
owner->markDirtyAndPropogate(); owner->markDirtyAndPropogate();
} }
YOGA_EXPORT void YGNodeSwapChild(
const YGNodeRef owner,
const YGNodeRef child,
const uint32_t index) {
owner->replaceChild(child, index);
child->setOwner(owner);
}
YOGA_EXPORT void YGNodeRemoveChild( YOGA_EXPORT void YGNodeRemoveChild(
const YGNodeRef owner, const YGNodeRef owner,
const YGNodeRef excludedChild) { const YGNodeRef excludedChild) {
@@ -1655,8 +1660,8 @@ static void YGNodeAbsoluteLayoutChild(
static void YGNodeWithMeasureFuncSetMeasuredDimensions( static void YGNodeWithMeasureFuncSetMeasuredDimensions(
const YGNodeRef node, const YGNodeRef node,
const float availableWidth, float availableWidth,
const float availableHeight, float availableHeight,
const YGMeasureMode widthMeasureMode, const YGMeasureMode widthMeasureMode,
const YGMeasureMode heightMeasureMode, const YGMeasureMode heightMeasureMode,
const float ownerWidth, const float ownerWidth,
@@ -1669,14 +1674,21 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(
node->hasMeasureFunc(), node->hasMeasureFunc(),
"Expected node to have custom measure function"); "Expected node to have custom measure function");
if (widthMeasureMode == YGMeasureModeUndefined) {
availableWidth = YGUndefined;
}
if (heightMeasureMode == YGMeasureModeUndefined) {
availableHeight = YGUndefined;
}
const float paddingAndBorderAxisRow = const float paddingAndBorderAxisRow =
YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth);
const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( const float paddingAndBorderAxisColumn =
node, YGFlexDirectionColumn, availableWidth); YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, ownerWidth);
const float marginAxisRow = const float marginAxisRow =
node->getMarginForAxis(YGFlexDirectionRow, availableWidth).unwrap(); node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap();
const float marginAxisColumn = const float marginAxisColumn =
node->getMarginForAxis(YGFlexDirectionColumn, availableWidth).unwrap(); node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap();
// 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)
@@ -1868,15 +1880,17 @@ static float YGNodeCalculateAvailableInnerDim(
const YGNodeConstRef node, const YGNodeConstRef node,
YGFlexDirection axis, YGFlexDirection axis,
float availableDim, float availableDim,
float ownerDim) { float ownerDim,
float ownerDimForMarginPadding) {
YGFlexDirection direction = YGFlexDirection direction =
YGFlexDirectionIsRow(axis) ? YGFlexDirectionRow : YGFlexDirectionColumn; YGFlexDirectionIsRow(axis) ? YGFlexDirectionRow : YGFlexDirectionColumn;
YGDimension dimension = YGDimension dimension =
YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight; YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight;
const float margin = node->getMarginForAxis(direction, ownerDim).unwrap(); const float margin =
node->getMarginForAxis(direction, ownerDimForMarginPadding).unwrap();
const float paddingAndBorder = const float paddingAndBorder =
YGNodePaddingAndBorderForAxis(node, direction, ownerDim); YGNodePaddingAndBorderForAxis(node, direction, ownerDimForMarginPadding);
float availableInnerDim = availableDim - margin - paddingAndBorder; float availableInnerDim = availableDim - margin - paddingAndBorder;
// Max dimension overrides predefined dimension value; Min dimension in turn // Max dimension overrides predefined dimension value; Min dimension in turn
@@ -2328,7 +2342,8 @@ static void YGDistributeFreeSpaceFirstPass(
// first and second passes. // first and second passes.
deltaFreeSpace += boundMainSize - childFlexBasis; deltaFreeSpace += boundMainSize - childFlexBasis;
collectedFlexItemsValues.totalFlexShrinkScaledFactors -= collectedFlexItemsValues.totalFlexShrinkScaledFactors -=
flexShrinkScaledFactor; (-currentRelativeChild->resolveFlexShrink() *
currentRelativeChild->getLayout().computedFlexBasis.unwrap());
} }
} }
} else if ( } else if (
@@ -2575,7 +2590,8 @@ static void YGJustifyMainAxis(
// We need to do that only for relative elements. Absolute elements do not // We need to do that only for relative elements. Absolute elements do not
// take part in that phase. // take part in that phase.
if (childStyle.positionType() == YGPositionTypeRelative) { if (childStyle.positionType() == YGPositionTypeRelative) {
if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) { if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto
&& collectedFlexItemsValues.remainingFreeSpace > 0.0f) {
collectedFlexItemsValues.mainDim += collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine; numberOfAutoMarginsOnCurrentLine;
@@ -2588,7 +2604,8 @@ static void YGJustifyMainAxis(
pos[mainAxis]); pos[mainAxis]);
} }
if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) { if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto
&& collectedFlexItemsValues.remainingFreeSpace > 0.0f) {
collectedFlexItemsValues.mainDim += collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine; numberOfAutoMarginsOnCurrentLine;
@@ -2894,9 +2911,9 @@ static void YGNodelayoutImpl(
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
float availableInnerWidth = YGNodeCalculateAvailableInnerDim( float availableInnerWidth = YGNodeCalculateAvailableInnerDim(
node, YGFlexDirectionRow, availableWidth, ownerWidth); node, YGFlexDirectionRow, availableWidth, ownerWidth, ownerWidth);
float availableInnerHeight = YGNodeCalculateAvailableInnerDim( float availableInnerHeight = YGNodeCalculateAvailableInnerDim(
node, YGFlexDirectionColumn, availableHeight, ownerHeight); node, YGFlexDirectionColumn, availableHeight, ownerHeight, ownerWidth);
float availableInnerMainDim = float availableInnerMainDim =
isMainAxisRow ? availableInnerWidth : availableInnerHeight; isMainAxisRow ? availableInnerWidth : availableInnerHeight;
@@ -3646,8 +3663,8 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(
} }
YOGA_EXPORT float YGRoundValueToPixelGrid( YOGA_EXPORT float YGRoundValueToPixelGrid(
const float value, const double value,
const float pointScaleFactor, const double pointScaleFactor,
const bool forceCeil, const bool forceCeil,
const bool forceFloor) { const bool forceFloor) {
double scaledValue = ((double) value) * pointScaleFactor; double scaledValue = ((double) value) * pointScaleFactor;
@@ -3803,8 +3820,10 @@ bool YGLayoutNodeInternal(
if (needToVisitNode) { if (needToVisitNode) {
// Invalidate the cached results. // Invalidate the cached results.
layout->nextCachedMeasurementsIndex = 0; layout->nextCachedMeasurementsIndex = 0;
layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1; layout->cachedLayout.availableWidth = -1;
layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1; layout->cachedLayout.availableHeight = -1;
layout->cachedLayout.widthMeasureMode = YGMeasureModeUndefined;
layout->cachedLayout.heightMeasureMode = YGMeasureModeUndefined;
layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedWidth = -1;
layout->cachedLayout.computedHeight = -1; layout->cachedLayout.computedHeight = -1;
} }
@@ -4061,24 +4080,24 @@ YOGA_EXPORT void YGConfigSetPointScaleFactor(
static void YGRoundToPixelGrid( static void YGRoundToPixelGrid(
const YGNodeRef node, const YGNodeRef node,
const float pointScaleFactor, const double pointScaleFactor,
const float absoluteLeft, const double absoluteLeft,
const float absoluteTop) { const double absoluteTop) {
if (pointScaleFactor == 0.0f) { if (pointScaleFactor == 0.0f) {
return; return;
} }
const float nodeLeft = node->getLayout().position[YGEdgeLeft]; const double nodeLeft = node->getLayout().position[YGEdgeLeft];
const float nodeTop = node->getLayout().position[YGEdgeTop]; const double nodeTop = node->getLayout().position[YGEdgeTop];
const float nodeWidth = node->getLayout().dimensions[YGDimensionWidth]; const double nodeWidth = node->getLayout().dimensions[YGDimensionWidth];
const float nodeHeight = node->getLayout().dimensions[YGDimensionHeight]; const double nodeHeight = node->getLayout().dimensions[YGDimensionHeight];
const float absoluteNodeLeft = absoluteLeft + nodeLeft; const double absoluteNodeLeft = absoluteLeft + nodeLeft;
const float absoluteNodeTop = absoluteTop + nodeTop; const double absoluteNodeTop = absoluteTop + nodeTop;
const float absoluteNodeRight = absoluteNodeLeft + nodeWidth; const double absoluteNodeRight = absoluteNodeLeft + nodeWidth;
const float absoluteNodeBottom = absoluteNodeTop + nodeHeight; const double absoluteNodeBottom = absoluteNodeTop + nodeHeight;
// If a node has a custom measure function we never want to round down its // If a node has a custom measure function we never want to round down its
// size as this could lead to unwanted text truncation. // size as this could lead to unwanted text truncation.
@@ -4321,6 +4340,7 @@ YOGA_EXPORT void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(
void YGAssert(const bool condition, const char* message) { void YGAssert(const bool condition, const char* message) {
if (!condition) { if (!condition) {
Log::log(YGNodeRef{nullptr}, YGLogLevelFatal, nullptr, "%s\n", message); Log::log(YGNodeRef{nullptr}, YGLogLevelFatal, nullptr, "%s\n", message);
throwLogicalErrorWithMessage(message);
} }
} }
@@ -4330,6 +4350,7 @@ void YGAssertWithNode(
const char* message) { const char* message) {
if (!condition) { if (!condition) {
Log::log(node, YGLogLevelFatal, nullptr, "%s\n", message); Log::log(node, YGLogLevelFatal, nullptr, "%s\n", message);
throwLogicalErrorWithMessage(message);
} }
} }
@@ -4339,6 +4360,7 @@ void YGAssertWithConfig(
const char* message) { const char* message) {
if (!condition) { if (!condition) {
Log::log(config, YGLogLevelFatal, nullptr, "%s\n", message); Log::log(config, YGLogLevelFatal, nullptr, "%s\n", message);
throwLogicalErrorWithMessage(message);
} }
} }

View File

@@ -69,6 +69,11 @@ WIN_EXPORT void YGNodeInsertChild(
YGNodeRef child, YGNodeRef child,
uint32_t index); uint32_t index);
WIN_EXPORT void YGNodeSwapChild(
YGNodeRef node,
YGNodeRef child,
uint32_t index);
WIN_EXPORT void YGNodeRemoveChild(YGNodeRef node, YGNodeRef child); WIN_EXPORT void YGNodeRemoveChild(YGNodeRef node, YGNodeRef child);
WIN_EXPORT void YGNodeRemoveAllChildren(YGNodeRef node); WIN_EXPORT void YGNodeRemoveAllChildren(YGNodeRef node);
WIN_EXPORT YGNodeRef YGNodeGetChild(YGNodeRef node, uint32_t index); WIN_EXPORT YGNodeRef YGNodeGetChild(YGNodeRef node, uint32_t index);
@@ -347,8 +352,8 @@ WIN_EXPORT void YGConfigSetContext(YGConfigRef config, void* context);
WIN_EXPORT void* YGConfigGetContext(YGConfigRef config); WIN_EXPORT void* YGConfigGetContext(YGConfigRef config);
WIN_EXPORT float YGRoundValueToPixelGrid( WIN_EXPORT float YGRoundValueToPixelGrid(
float value, double value,
float pointScaleFactor, double pointScaleFactor,
bool forceCeil, bool forceCeil,
bool forceFloor); bool forceFloor);

Some files were not shown because too many files have changed in this diff Show More