Compare commits

...

41 Commits

Author SHA1 Message Date
Mateo Guzmán
0ea3cc6d2e Migrate YogaNode to Kotlin 2025-08-08 00:37:23 +02:00
Mateo Guzmán
8bf7a34d02 Initial Kotlin setup and migrate YogaConstants (#1829)
Summary:
X-link: https://github.com/facebook/react-native/pull/53133

# Changelog:
[Internal] -

As part of the ongoing effort to migrate the React Native codebase to Kotlin, this PR introduces the initial setup required for Kotlin support in Yoga.

- Added initial basic Kotlin configuration to the project.
- Migrated `YogaConstants` as an initial file to try out the first migration steps.

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

Test Plan:
- Tested the migrated class directly against facebook/react-native, see the PR [here](https://github.com/facebook/react-native/pull/52998).
- Run: `./gradlew :yoga:assembleDebug` & `./gradlew :yoga:compileDebugSources`

I am not able to run the Java tests in this repo (even before the initial Kotlin setup) – not sure if I am missing something there but any pointers are welcome – it seems like there is some missing configuration. Currently trying with `./gradlew :yoga:test`

Reviewed By: cortinico

Differential Revision: D79545992

Pulled By: rshest

fbshipit-source-id: 8257ff53e6b6f2436980be98b6c94e1ac526b207
2025-08-07 08:17:56 -07:00
Dmitry Polukhin
82671c0132 Disable modernize-avoid-c-arrays in xplat/yoga/tests
Reviewed By: JuanBesa, rshest

Differential Revision: D79247609

fbshipit-source-id: 529ba950ab200c46493152b81dece6bd76f6fdbd
2025-07-30 03:39:00 -07:00
Alexey Medvedev
9f2a9476e5 Make yoga/Yoga.h an umbrell header (#1828)
Summary:
X-link: https://github.com/facebook/react-native/pull/52817

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

X-link: https://github.com/facebook/litho/pull/1070

This diff makes the Yoga/Yoga.h header an umbrella header, which means that it includes all of Yoga's public headers. The code changes in each file include adding the IWYU pragma export to each header file, which is a way to tell the compiler to export the header file's symbols to other files that include it. This is necessary for the header file to be used as an umbrella header.

Changelog:
[General][Added] - Code quality fixes

Reviewed By: corporateshark

Differential Revision: D78692457

fbshipit-source-id: 7fcd53d2a6f268fa4377dbd5bd6ba6eebc94b5f8
2025-07-24 16:51:13 -07:00
Jakub Piasecki
c7c85621fc Fix display: contents nodes not being cloned with the wrong owner (#1826)
Summary:
X-link: https://github.com/facebook/react-native/pull/52530

This PR fixes two issues with `display: contents` implementation:
1. When a node with `display: contents` set is a leaf, it won't be cloned after the initial tree is built. The added test case covers this scenario.
2. It was possible for the subtree of `display: contents` nodes not to be cloned during layout. I don't have a minimal reproduction for this one, unfortunately. It was discovered in the Expensify app: https://github.com/Expensify/App/issues/65268, along with a consistent reproduction. In that specific case, it seems to be heavily tied to `react-native-onyx`, which is a state management library.

Changelog: [GENERAL][FIXED] - Fixed nodes with `display: contents` set being cloned with the wrong owner

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

Reviewed By: adityasharat, NickGerleman

Differential Revision: D78084270

Pulled By: j-piasecki

fbshipit-source-id: eb81f6d7dcd1665974d07261ba693e2abea239bb
2025-07-11 02:16:35 -07:00
Nolan O'Brien
73980a3cf8 Fix exhaustive switches
Summary:
X-link: https://github.com/facebook/react-native/pull/52379

Changelog: [General][Fixed] - Add `default:` case to avoid warnings/errors for targets that compile with `-Wswitch-enum` and `-Wswitch-default` enabled

Reviewed By: aary, yungsters, astreet

Differential Revision: D77051152

fbshipit-source-id: 100b10f97cb3a5d73f1e3dcaf1b284baf6a43982
2025-07-02 14:21:18 -07:00
Nick Gerleman
4b5ca50117 Reland Fix possible invalid measurements when width or height is zero pixels (#1823)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1823

X-link: https://github.com/facebook/react-native/pull/52348

Fixes https://github.com/facebook/yoga/issues/1819

Yoga has a fast path when measuring a node, if it thinks it knows its dimensions ahead of time.

This path has some eroneous logic, to set both axis to owner size, if *either* will evaluate to zero, while having an `YGMeasureModeAtMost`/`FitContent` constraint. This means that if a node is given a zero width, and Yoga later measures with with `FitContent`, its height will become the maximum allowable height, even if it shouldn't be that large.

We can fix this, by only allowing if both axis are this fixed case, instead of just one.

This bug has existed for about a decade (going back to at least D3312496).

Changelog:
[General][Fixed] - Fix possible invalid measurements with width or height is zero pixels

Reviewed By: yungsters

Differential Revision: D76851589

fbshipit-source-id: 6f5a0e6beccc51f591726c9e83e9b90f3350ed0f
2025-06-30 20:46:39 -07:00
FBLite Revert Bot
30291398f3 Revert D76793705: Fix possible invalid measurements when width or height is zero pixels
Differential Revision:
D76793705

Original commit changeset: ea4c00e68891

Original Phabricator Diff: D76793705

fbshipit-source-id: 95d6b66ab08e073da9fb07fd4094a7e30e2f453b
2025-06-17 14:33:32 -07:00
Nick Gerleman
27d632c697 Fix possible invalid measurements when width or height is zero pixels (#1820)
Summary:
X-link: https://github.com/facebook/react-native/pull/52073

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

Fixes https://github.com/facebook/yoga/issues/1819

Yoga has a fast path when measuring a node, if it thinks it knows its dimensions ahead of time.

This path has some eroneous logic, to set both axis to owner size, if *either* will evaluate to zero, while having an `YGMeasureModeAtMost`/`FitContent` constraint. This means that if a node is given a zero width, and Yoga later measures with with `FitContent`, its height will become the maximum allowable height, even if it shouldn't be that large.

We can fix this, by only allowing if both axis are this fixed case, instead of just one.

This bug has existed for about a decade (going back to at least D3312496).

Changelog:
[General][Fixed] - Fix possible invalid measurements with width or height is zero pixels

Reviewed By: yungsters

Differential Revision: D76793705

fbshipit-source-id: ea4c00e688912a58c08801e4a14ddf1b293a5d86
2025-06-17 12:15:55 -07:00
Nicola Corti
117fa494f7 Migrate from OSSRH to Central Portal (#1816)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1816

This migrates Yoga to publish to Central Portal rather than OSSRC

Reviewed By: NickGerleman

Differential Revision: D76436235

fbshipit-source-id: ddaaa95472054aa2b09399b5cc8d821dae51234f
2025-06-11 16:12:06 -07:00
Nicola Corti
073c136117 Remove unnecessary gradle-enterprise.gradle.kts from Yoga (#1817)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1817

This file is not really necessary. As we don't have a Gradle Enterprise instance anymore, let's just remove it and inline it.

Reviewed By: mdvacca

Differential Revision: D76436236

fbshipit-source-id: 27fcc48574905415b147f67dd4a8f57dffbeda3e
2025-06-11 11:46:34 -07:00
Nick Gerleman
1232761571 YGPersistentNodeCloningTest (#1813)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1813

This adds a unit test to Yoga, which emulates the model of "persistent Yoga nodes" and cloning used by React Fabric, including the private (but relied on) Yoga APIs.

It models the over-invalidation exposed in D75287261, which reproduces (due to Yoga incorrectly measuring flex-basis under fit-content, and that constraint changing when sibling changes) but this test for now sets a definite height on A, to show that we only clone what is neccesary, when measure constraints do not have to change.

Having a minimal version of Fabric's model in Yoga unit tests should make some of these interesting interactions a bit easier to debug.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D75572762

fbshipit-source-id: cda8b3fdd6e538a55dd100494518688c864bd233
2025-06-02 19:32:45 -07:00
Nick Gerleman
c935fd5e10 Resubmit: Expose Unsnapped Dimensions (#1811)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1811

X-link: https://github.com/facebook/react-native/pull/51298

## Resubmit

This was backed out due to being up the stack from another change that was backed out, but should be safe by itself.

## Original

We want to know if an artifact created during measurement can fully be reused after final layout, but the final layout is allowed to be slightly larger due to pixel grid rounding (while still allowing reuse). It's hard to tell after the fact, whether it is larger because of this rounding (though the measure is used), or if it may be a pixel larger for valid reasons.

We can expose the unsnapped dimensions of a node to give us this information, and to correlate measurement artifacts.

This is most of the time the same as the layout's measured dimension, though I don't think it's safe to use this, since anything else measuring the node after could clobber this (I think `YGNodeLayoutGetOverflow` may also be prone to this as a bug).

Changelog: [Internal]

Reviewed By: joevilches

Differential Revision: D74673119

fbshipit-source-id: 06d2eb21e28b76458ec88f4dfcaec809707d0390
2025-05-13 18:21:04 -07:00
Yannick Loriot
624325302c Revert D74292949: Expose Unsnapped Dimensions
Differential Revision:
D74292949

Original commit changeset: 05011c66a9a9

Original Phabricator Diff: D74292949

fbshipit-source-id: c6ca51c7b882950d54b6a43e206973774db40429
2025-05-09 01:45:16 -07:00
Nick Gerleman
37a94a86de Expose Unsnapped Dimensions (#1809)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1809

X-link: https://github.com/facebook/react-native/pull/51181

We want to know if an artifact created during measurement can fully be reused after final layout, but the final layout is allowed to be slightly larger due to pixel grid rounding (while still allowing reuse). It's hard to tell after the fact, whether it is larger because of this rounding (though the measure is used), or if it may be a pixel larger for valid reasons.

We can expose the unsnapped dimensions of a node to give us this information, and to correlate measurement artifacts.

This is most of the time the same as the layout's measured dimension, though I don't think it's safe to use this, since anything else measuring the node after could clobber this (I think `YGNodeLayoutGetOverflow` may also be prone to this as a bug).

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D74292949

fbshipit-source-id: 05011c66a9a9480544313eb1dfe2c46bf7742bac
2025-05-08 17:45:16 -07:00
Santhosh Kumar
4abc1a7d5f Fix documentation of 'alignContent' property configured with spaces (#1808)
Summary:
The documentation shall be corrected to specify in which axis the spaces are distributed when flex container is configured 'alignContent' property.

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

Reviewed By: joevilches

Differential Revision: D74347272

Pulled By: philIip

fbshipit-source-id: 1b05840028bca774c9d4a68562bcf537d5a72500
2025-05-07 14:40:02 -07:00
Yurii Nakonechnyi
51e6095005 LayoutData - added explicit default fields values initialization (#1802)
Summary:
X-link: https://github.com/facebook/react-native/pull/50227

Explicit defaults add 'strictness' and take the guesswork out of what's going on in places like this:

6455a848a7/yoga/algorithm/CalculateLayout.cpp (L2345)

Changelog: [Internal]

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

Reviewed By: javache

Differential Revision: D71687310

Pulled By: NickGerleman

fbshipit-source-id: f11d18aa68ce7ccd17fb1d5af0e729e8c0711cf9
2025-03-24 12:23:46 -07:00
Yurii Nakonechnyi
79cef614ce fatalWithMessage() - added warning suppression: unused 'message' argument (#1803)
Summary:
X-link: https://github.com/facebook/react-native/pull/50148

## Changelog:

[Internal] - suppression: unused 'message' argument

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

Reviewed By: NickGerleman

Differential Revision: D71492528

Pulled By: lunaleaps

fbshipit-source-id: 6fc7a665066351d15e09f0b6c82ed1fe3f688a94
2025-03-19 19:06:50 -07:00
Rob Hogan
6455a848a7 Update GHA actions/upload-artifact to v4, unbreak CI (#1799)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1799

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

`actions/upload-artifact@v3` is deprecated and will no longer execute, causing CI to fail - eg:

https://github.com/facebook/yoga/actions/runs/13789185831/job/38564343959

See https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/ for context

Reviewed By: NickGerleman

Differential Revision: D70986391

fbshipit-source-id: 66cec50bb485e89c0948c752ba7dc2a4f42617d6
2025-03-11 13:40:51 -07:00
Nicola Corti
1b7d2c8d48 Enable RTTI to fix exception pointer issue on React Native (#1791)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1791

Disabling RTTI for Yoga is causing std::exception to don't work properly in OSS.
Fixes: https://github.com/facebook/react-native/issues/48027

Not sure why we originally disabled RTTI for Yoga, but we have it enable for the whole
React Native build so it probably makes sense to have it enabled for Yoga as well.

Changelog:
[Internal] [Changed] - Enable RTTI to fix exception pointer issue on React Native

bypass-github-export-checks

Reviewed By: javache, NickGerleman

Differential Revision: D70386744

fbshipit-source-id: 36e3a1ddb38346d31979d5c1b77d6e9796d6a855
2025-03-04 04:51:38 -08:00
Nicola Corti
3aa594c1f9 Gradle to 8.13 (#1790)
Summary:
X-link: https://github.com/facebook/react-native/pull/49689

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

X-link: https://github.com/facebook/react-native/pull/49703

I'm bumping Gradle to the latest minor.
https://docs.gradle.org/8.13/release-notes.html

I'm also changing the distribution from `all` to `bin` as
this reduces the download time of the distribution.

Changelog:
[Android] [Changed] - Gradle to 8.13

Reviewed By: NickGerleman

Differential Revision: D70239710

fbshipit-source-id: 89808242a93344f540bfe82f4178cf6db72597d1
2025-02-27 03:13:26 -08:00
Mihaela Ogrezeanu
c2ae39167e Update yoga aar targets (#1786)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1786

Follow up on comments from D68152410

- Removes minsdk version from manifest
- Update to MIT licence
- Rename targets that don't export existing libs

I've looked into using yoga_java_library and adding a param to pass what libs to exclude, but ultimately provided_deps does what we need and it simpler to maintain; we still need to add the different targets because the aar needs to depend on :jni-server and not :jni.

Reviewed By: NickGerleman

Differential Revision: D69455682

fbshipit-source-id: aa08bc030495d13da9545ec368ab63a7a946dad0
2025-02-12 02:28:59 -08:00
Mihaela Ogrezeanu
49ee855f99 Add aar BUCK targets to export Litho libraries as aars (#1782)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1782

This adds fb_native.android_aar targets for resources that are needed by Litho at runtime and cannot be exported as jars.
- resource modules referenced by Litho
- Yoga library. Some dependencies required by Yoga neded to be added as "provided_deps" so they don't get exported with the aar

Reviewed By: astreet

Differential Revision: D68152410

fbshipit-source-id: 7dc2ffa0b60a4ca160a011d16d2dc5ab91f608a6
2025-01-24 07:57:56 -08:00
Nick Gerleman
b12e0a2a15 Fix CI after GHA Update to Ubuntu 24.04 (#1781)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1781

This new image removed preinstalled libc++, and the ability to install old version of Clang Format we were installing.

This manually installs libc++ when setting up Clang jobs, and fully removes the clang-format validation job, since it wasn't correctly running before, and it's probably more a pain to ask people to run this than to just run Arcanist when importing a change.

Changelog: [Internal]

Reviewed By: joevilches

Differential Revision: D68455129

fbshipit-source-id: b5767be832b2b5d46db7e60e18b66823819ba15a
2025-01-21 13:34:22 -08:00
Ruslan Shestopalyuk
9591210a7a Add more unit tests for rounding values to pixel grid (#1776)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1776

# Changelog:
[Internal] -

I was looking into some profiling results and noticed that Yoga has some quirky custom logic when it comes to rounding to the pixel grid, especially for the values that are halfway through.

There are already unit tests in place, but those cases weren't covered, so I am adding these extra corner cases here, to make sure they are covered in case that the actual rounding function may get modified (which it might make sense to, as it's currently can be more expensive than it could have been in some scenarios).

Reviewed By: christophpurrer

Differential Revision: D67712673

fbshipit-source-id: da1b7339a8939ced8d91f15441bc7d1f8af768c8
2024-12-30 12:38:48 -08:00
Ruslan Shestopalyuk
91997d6cd3 Avoid calling fmod twice in roundLayoutResultsToPixelGrid (#1775)
Summary:
X-link: https://github.com/facebook/litho/pull/1036

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

X-link: https://github.com/facebook/react-native/pull/48404

## Changelog:
[Internal] -

This popped up when profiling some heavy UI performance, calling `fmod` operation in Yoga's `roundLayoutResultsToPixelGrid` in `PixelGrid.cpp` can be expensive, furthermore it turns out that some of the calls were redundant.

This replaces the duplicate calls to fmod with an equivalent single round operation, which for e.g. clang compiler on Windows brings the code in question from ~50 instructions (including 4 call instructions to the fmod function) down to ~30 instructions (without any external calls), and the layout operation being **~1% more efficient** for the particular benchmark I was looking into.

Reviewed By: christophpurrer

Differential Revision: D67689065

fbshipit-source-id: 2a074a1cb81bd7f7a3c414050b9ddda2ba90180f
2024-12-30 12:38:48 -08:00
Joe Vilches
909e4bea6e Fix test util to measure text properly based on flex direction (#1768)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1768

Depending on the flex direction text will either be capped to the measured size or to the longest word, so I added that functionality

Reviewed By: mlord93

Differential Revision: D67106199

fbshipit-source-id: 0b4691768809004043a847f3fc5f7b94e92f1575
2024-12-12 11:11:49 -08:00
Nicola Corti
13f4adbbcd Add 16K support for standalone Yoga (#1766)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1766

While we added support for 16K pages for yoga through React Native,
the standalone version we upload to Maven Central wasn't handled.
This fixes it.

Reviewed By: NickGerleman

Differential Revision: D66975933

fbshipit-source-id: 36a8404e2f2a60a44b9a39e478b23d1829bc542e
2024-12-10 09:34:38 -08:00
heoblitz
ae2d06d0f5 Update YGNodeStyleGetGap to return YGValue (#1753)
Summary:
X-link: https://github.com/facebook/react-native/pull/47973

Gap can be styled using both `points` and `percentages`, but YGNodeStyleGetGap currently returns a float value.

To maintain alignment with the `padding` and `margin` functionalities and allow it to be handled in bridging code, this function has been updated to return YGValue.

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

Reviewed By: joevilches

Differential Revision: D66513236

Pulled By: NickGerleman

fbshipit-source-id: b7110855c037f20780f031f22a945bde4446687d
2024-12-09 13:38:05 -08:00
Joe Vilches
5478812db3 Use crossAxisOwnerSize instead of ownerHeight in cross axis bound call (#1763)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1763

X-link: https://github.com/facebook/react-native/pull/48080

Small bug that I noticed while doing intrinsic sizing. We have the ownerHeight as the axis size despite bounding the length of the cross axis. This should therefore be the crossAxisOwnerSize, which might be the width in some cases

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66736539

fbshipit-source-id: 528fc438b3327cd6f7890ea0ba408e4ce7b0f02c
2024-12-06 15:34:06 -08:00
Joe Vilches
050ac8a413 Properly camelcase mainAxisownerSize in FlexLine (#1762)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1762

X-link: https://github.com/facebook/react-native/pull/48077

OCD strikes again. Grepped this time to make sure we didn't miss any cases for this specific param name

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66715777

fbshipit-source-id: 3e881a15b3b2836a4a55b11d7ec621541b92a05d
2024-12-03 19:16:56 -08:00
Nick Gerleman
733ba24064 Add Yoga 3.2 Release notes (#1761)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1761

Whips up some release notes for what is new since Yoga 3.1.

https://github.com/facebook/yoga/compare/v3.1.0...v3.2.0

The relevant packages have already been published.

Reviewed By: joevilches

Differential Revision: D66679637

fbshipit-source-id: dd94e2a52f2bdc80541c331d1fb39de82669cc7a
2024-12-02 17:39:41 -08:00
Joe Vilches
e177477144 Add text based intrinsic sizing tests (#1759)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1759

We just have block based tests right now. Intrinsic sizing is commonly used with text so lets add a few there.

Reviewed By: NickGerleman

Differential Revision: D66662940

fbshipit-source-id: f8b91419c89d22d79a91d3bd8c7da70429c827fb
2024-12-02 17:29:49 -08:00
Joe Vilches
76ffdbc25d Back out "Back out "[yoga][gentest][intrinsic sizing] Gentest and initial tests for intrinsic sizing"" (#1758)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1758

Original commit changeset: 52d6cc754cb9

Original Phabricator Diff: D66332308

Reviewed By: NickGerleman

Differential Revision: D66662663

fbshipit-source-id: fb3a0d10ec0f0149aeee510148f26ada8eff7e47
2024-12-02 17:29:49 -08:00
Joe Vilches
f99e657acd Back out "Back out "[yoga][intrinsic sizing] Update public API for intrinsic sizing setters""
Summary:
Original commit changeset: 793f77dad021

Original Phabricator Diff: D66332309

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66662661

fbshipit-source-id: 22ed3ac9492f0a563c041ce4cb5fba4b65b53211
2024-12-02 17:29:49 -08:00
Joe Vilches
a9246bc7db Back out "Back out "[yoga][intrinsic sizing] Modify private apis to set, store, and get intrinsic sizing keywords"" (#1756)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1756

X-link: https://github.com/facebook/react-native/pull/48049

Changelog: [Internal]

Original commit changeset: 1d596964e0c8

Original Phabricator Diff: D66332307

Reviewed By: NickGerleman

Differential Revision: D66662662

fbshipit-source-id: 4f9ac2b1557b848f519dcd728d7097b52f1190b3
2024-12-02 17:29:49 -08:00
Joe Vilches
be72b8e8aa Align order of params between calculateLayoutInternal and calculateLayoutImpl (#1755)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1755

X-link: https://github.com/facebook/react-native/pull/47975

I've been working with callsites here and its annoying if you switch these that you need to move these params around too. Let's just make them the same order

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66519836

fbshipit-source-id: 2e98e671270a053c6e62372e2003f1ca67774ec9
2024-11-26 22:48:24 -08:00
Joe Vilches
b876f596d9 Camel case LengthValue in Node.cpp (#1754)
Summary:
X-link: https://github.com/facebook/react-native/pull/47971

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

This was annoying me

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66510734

fbshipit-source-id: d1b952f2e82e7018b16dc0c572d9b98aec18c0e5
2024-11-26 15:23:08 -08:00
Joe Vilches
be00354b71 Back out "Modify private apis to set, store, and get intrinsic sizing keywords" (#1750)
Summary:
X-link: https://github.com/facebook/react-native/pull/47895

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

These APIs were only added so that we could do TDD as we work on intrinsic sizing functionality. As of right now they do nothing. We are aiming on publishing a new version of Yoga soon so for the time being we are going to back these out so as not to confuse anyone with this new functionality. Ideally we get to a point where we have some temporary experimental header to stage these in but this is a bit time sensitive so just backing out for now

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66332307

fbshipit-source-id: 1d596964e0c893091c541988506e8b80fa6d1957
2024-11-25 00:40:03 -08:00
Joe Vilches
0c995496c8 Back out "Update public API for intrinsic sizing setters" (#1752)
Summary:
X-link: https://github.com/facebook/react-native/pull/47896

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

These APIs were only added so that we could do TDD as we work on intrinsic sizing functionality. As of right now they do nothing. We are aiming on publishing a new version of Yoga soon so for the time being we are going to back these out so as not to confuse anyone with this new functionality. Ideally we get to a point where we have some temporary experimental header to stage these in but this is a bit time sensitive so just backing out for now

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66332309

fbshipit-source-id: 793f77dad021fa5e57b52c36ae954307636bcbf0
2024-11-25 00:40:03 -08:00
Joe Vilches
c12e732fab Back out "Gentest and initial tests for intrinsic sizing" (#1751)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1751

Original commit changeset: 1e3e7214fab0

Original Phabricator Diff: D64145117

Reviewed By: NickGerleman

Differential Revision: D66332308

fbshipit-source-id: 52d6cc754cb931e851e444bac2c946907a098235
2024-11-25 00:40:03 -08:00
66 changed files with 3487 additions and 1214 deletions

View File

@@ -1,23 +0,0 @@
name: Clang Format
inputs:
directory:
description: Directory to Lint
required: true
version:
description: LLVM version to use # Should be kept roughly in sync with arcanist
required: false
default: 12
runs:
using: "composite"
steps:
- name: Install
shell: bash
run: sudo apt-get install -y clang-format-${{ inputs.version }}
- name: clang-format
working-directory: ${{ inputs.directory }}
shell: bash
env:
BASHOPTS: extglob:nullglob
run: clang-format-${{ inputs.version }} --dry-run --Werror **/*.{h,hh,hpp,c,cpp,cc,m,mm}

View File

@@ -16,6 +16,7 @@ runs:
if: ${{ inputs.toolchain == 'Clang' }}
shell: bash
run: |
sudo apt-get install -y libc++-dev libc++abi-dev
echo "CC=/usr/bin/clang" >> $GITHUB_ENV
echo "CXX=/usr/bin/clang++" >> $GITHUB_ENV
echo "CXXFLAGS=-stdlib=libc++" >> $GITHUB_ENV

View File

@@ -24,7 +24,7 @@ jobs:
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: 'snapshot-artifacts'
path: '~/.m2/repository/'

View File

@@ -23,7 +23,7 @@ jobs:
ORG_GRADLE_PROJECT_USE_SNAPSHOT: true
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: 'snapshot-artifacts'
path: '~/.m2/repository/'

View File

@@ -97,13 +97,3 @@ jobs:
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
cmake --build build
working-directory: capture
clang-format:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: clang-format
uses: ./.github/actions/clang-format

View File

@@ -110,7 +110,7 @@ jobs:
run: yarn pack --filename yoga-layout.tar.gz
working-directory: javascript
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: npm-package
path: javascript/yoga-layout.tar.gz

3
.gitignore vendored
View File

@@ -73,3 +73,6 @@ local.properties
# Docusarus build
.docusaurus
# Android Studio
.idea

View File

@@ -9,6 +9,7 @@ plugins {
id("com.android.library") version "8.7.1" apply false
id("com.android.application") version "8.7.1" apply false
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
id 'org.jetbrains.kotlin.android' version '2.1.20' apply false
}
allprojects {
@@ -34,6 +35,8 @@ nexusPublishing {
sonatype {
username.set(sonatypeUsername)
password.set(sonatypePassword)
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
}
}
}

View File

@@ -225,17 +225,17 @@ static void serializeTreeImpl(
appendEdges<&YGNodeStyleGetPosition>(
j, "position", node, defaultNode.get());
appendFloatIfNotDefault(
appendYGValueIfNotDefault(
j["style"],
"gap",
YGNodeStyleGetGap(node, YGGutterAll),
YGNodeStyleGetGap(defaultNode.get(), YGGutterAll));
appendFloatIfNotDefault(
appendYGValueIfNotDefault(
j["style"],
"column-gap",
YGNodeStyleGetGap(node, YGGutterColumn),
YGNodeStyleGetGap(defaultNode.get(), YGGutterColumn));
appendFloatIfNotDefault(
appendYGValueIfNotDefault(
j["style"],
"row-gap",
YGNodeStyleGetGap(node, YGGutterRow),

View File

@@ -19,8 +19,8 @@ add_compile_options(
# Enable warnings and warnings as errors
/W4
/WX
# Disable RTTI
$<$<COMPILE_LANGUAGE:CXX>:/GR->
# Enable RTTI
$<$<COMPILE_LANGUAGE:CXX>:/GR>
# Use /O2 (Maximize Speed)
$<$<CONFIG:RELEASE>:/O2>)
@@ -34,8 +34,8 @@ add_compile_options(
# Enable warnings and warnings as errors
-Wall
-Werror
# Disable RTTI
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
# Enable RTTI
$<$<COMPILE_LANGUAGE:CXX>:-frtti>
# Use -O2 (prioritize speed)
$<$<CONFIG:RELEASE>:-O2>
# Enable separate sections per function/data item

View File

@@ -240,3 +240,14 @@
<div style="position:relative; width:50px; height:50px;">
</div>
</div>
<div id="align_items_non_stretch_s526008"
style="flex-direction: column; width: 400px; height: 400px;">
<div style="flex-direction: row;">
<div style="flex-direction: column; align-items: flex-start;">
<div>
<div style="width: 0; height: 10px;"></div>
</div>
</div>
</div>
</div>

View File

@@ -157,6 +157,31 @@
</div>
</div>
<div id="contains_inner_text_max_width_max_height_column" style="width:2000px; align-items: flex-start;">
<div style="max-width: 50px;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eleifasd et tortor ac auctor. Integer at
volutpat
libero, sed elementum dui interdum id. Aliquam consectetur massa vel neque aliquet, quis consequat risus
fringilla. Fusce rhoncus ipsum tempor eros aliquam, vel tempus metus ullamcorper. Nam at nulla sed tellus
vestibulum fringilla vel sit amet ligula. Proin velit lectus, euismod sit amet quam vel ultricies dolor,
vitae
finibus lorem ipsum. Pellentesque molestie at mi sit amet dictum. Donec vehicula lacinia felis sit amet
consectetur. Praesent sodales enim sapien, sed varius ipsum pellentesque vel. Aenean eu mi eu justo
tincidunt
finibus vel sit amet ipsum. Sed bibasdum purus vel ipsum sagittis, quis fermentum dolor lobortis. Etiam
vulputate eleifasd lectus vel varius.
Phasellus imperdiet lectus sit amet ipsum egestas, ut bibasdum ipsum malesuada. Vestibulum ante ipsum primis
in
faucibus orci luctus et ultrices posuere cubilia Curae; Sed mollis eros sit amet elit porttitor, vel
venenatis
turpis venenatis. Nulla tempus tortor at eros efficitur, sit amet dapibus ipsum malesuada. Ut at mauris sed
nunc
malesuada convallis. Duis id sem vel magna varius eleifasd vel at est. Donec eget orci a ipsum tempor
lobortis.
Sed at consectetur ipsum.
</div>
</div>
<div id="contains_inner_text_max_width" style="width:2000px;height:2000px;align-items: flex-start;">
<div style="flex-direction:row;max-width:100px">
@@ -229,7 +254,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_width" style="width: 90px; position: relative;">
<div data-disabled="true" id="fit_content_width" style="width: 90px;">
<div style="flex-direction: row; width: fit-content; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -240,7 +265,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_width" style="width: 500px; position: relative;">
<div id="stretch_width" style="width: 500px;">
<div style="flex-direction: row; width: -webkit-fill-available; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -260,7 +285,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_height" style="height: 90px; position: relative;">
<div data-disabled="true" id="fit_content_height" style="height: 90px; ">
<div style="height: fit-content; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -271,7 +296,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_height" style="height: 500px; position: relative;">
<div data-disabled="true" id="stretch_height" style="height: 500px;">
<div style="height: -webkit-fill-available; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -291,7 +316,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_flex_basis_column" style="height: 90px; position: relative;">
<div data-disabled="true" id="fit_content_flex_basis_column" style="height: 90px;">
<div style="flex-basis: fit-content; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -302,7 +327,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_flex_basis_column" style="height: 500px; position: relative;">
<div id="stretch_flex_basis_column" style="height: 500px;">
<div style="flex-basis: -webkit-fill-available; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -313,7 +338,7 @@
</div>
</div>
<div id="max_content_flex_basis_row" style="flex-direction: row; flex-basis: max-content; flex-wrap: wrap;">
<div data-disabled="true" id="max_content_flex_basis_row" style="flex-direction: row; flex-basis: max-content; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
<div style="width: 100px; height: 500px;">
@@ -322,7 +347,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_flex_basis_row" style="width: 90px; position: relative;">
<div data-disabled="true" id="fit_content_flex_basis_row" style="width: 90px;">
<div style="flex-direction: row; flex-basis: fit-content; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -333,7 +358,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_flex_basis_row" style="width: 500px; position: relative;">
<div data-disabled="true" id="stretch_flex_basis_row" style="width: 500px;">
<div style="flex-direction: row; flex-basis: -webkit-fill-available; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -344,7 +369,8 @@
</div>
</div>
<div data-disabled="true" id="max_content_max_width" style="flex-direction: row; max-width:max-content; width: 200px; flex-wrap: wrap;">
<div data-disabled="true" id="max_content_max_width"
style="flex-direction: row; max-width:max-content; width: 200px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
<div style="width: 100px; height: 50px;">
@@ -353,7 +379,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_max_width" style="width: 90px; position: relative;">
<div data-disabled="true" id="fit_content_max_width" style="width: 90px;">
<div style="flex-direction: row; max-width: fit-content; width: 110px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -364,7 +390,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_max_width" style="width: 500px; position: relative;">
<div data-disabled="true" id="stretch_max_width" style="width: 500px;">
<div style="flex-direction: row; max-width: -webkit-fill-available; width: 600px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -375,7 +401,8 @@
</div>
</div>
<div data-disabled="true" id="max_content_min_width" style="flex-direction: row; min-width:max-content; width: 100px; flex-wrap: wrap;">
<div data-disabled="true" id="max_content_min_width"
style="flex-direction: row; min-width:max-content; width: 100px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
<div style="width: 100px; height: 50px;">
@@ -384,7 +411,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_min_width" style="width: 90px; position: relative;">
<div data-disabled="true" id="fit_content_min_width" style="width: 90px;">
<div style="flex-direction: row; min-width: fit-content; width: 90px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -395,7 +422,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_min_width" style="width: 500px; position: relative;">
<div data-disabled="true" id="stretch_min_width" style="width: 500px;">
<div style="flex-direction: row; min-width: -webkit-fill-available; width: 400px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -415,7 +442,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_max_height" style="height: 90px; position: relative;">
<div data-disabled="true" id="fit_content_max_height" style="height: 90px;">
<div style="max-height: fit-content; height: 110px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -426,7 +453,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_max_height" style="height: 500px; position: relative;">
<div data-disabled="true" id="stretch_max_height" style="height: 500px;">
<div style="max-height: -webkit-fill-available; flex-wrap: wrap; height: 600px;">
<div style="width: 50px; height: 50px;">
</div>
@@ -446,7 +473,7 @@
</div>
</div>
<div data-disabled="true" id="fit_content_min_height" style="height: 90px; position: relative;">
<div data-disabled="true" id="fit_content_min_height" style="height: 90px;">
<div style="min-height: fit-content; height: 90px; flex-wrap: wrap;">
<div style="width: 50px; height: 50px;">
</div>
@@ -457,7 +484,7 @@
</div>
</div>
<div data-disabled="true" id="stretch_min_height" style="height: 500px; position: relative;">
<div data-disabled="true" id="stretch_min_height" style="height: 500px;">
<div style="min-height: -webkit-fill-available; flex-wrap: wrap; height: 400px;">
<div style="width: 50px; height: 50px;">
</div>
@@ -467,3 +494,75 @@
</div>
</div>
</div>
<div data-disabled="true" id="text_max_content_width" style="width: 200px">
<div style="width: max-content;">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_stretch_width" style="width: 200px">
<div style="width: -webkit-fill-available;">
<div style="flex-direction:row;">
Lorem ipsum dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_fit_content_width" style="width: 200px">
<div style="width: fit-content;">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_max_content_min_width" style="width: 200px">
<div style="min-width: max-content; width: 200px;">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_stretch_min_width" style="width: 200px">
<div style="min-width: -webkit-fill-available; width: 100px;">
<div style="flex-direction:row;">
Lorem ipsum dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" data-disabled="true" id="text_fit_content_min_width" style="width: 200px">
<div style="min-width: fit-content; width: 300px">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_max_content_max_width" style="width: 200px">
<div style="max-width: max-content; width: 2000px;">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_stretch_max_width" style="width: 200px">
<div style="max-width: -webkit-fill-available; width: 300px;">
<div style="flex-direction:row;">
Lorem ipsum dolor sit amet
</div>
</div>
</div>
<div data-disabled="true" id="text_fit_content_max_width" style="width: 200px">
<div style="max-width: fit-content; width: 1000px">
<div style="flex-direction:row;">
Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet
</div>
</div>
</div>

View File

@@ -502,7 +502,7 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, {
},
YGNodeSetMeasureFunc: {
value: function (nodeName, innerText) {
value: function (nodeName, innerText, _) {
this.push(`YGNodeSetContext(${nodeName}, (void*)"${innerText}");`);
this.push(
`YGNodeSetMeasureFunc(${nodeName}, &facebook::yoga::test::IntrinsicSizeMeasure);`,

View File

@@ -467,7 +467,7 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, {
},
YGNodeSetMeasureFunc: {
value: function (nodeName, innerText) {
value: function (nodeName, innerText, _) {
this.push(`${nodeName}.setData("${innerText}");`);
this.push(
`${nodeName}.setMeasureFunction(new TestUtils.intrinsicMeasureFunction());`,

View File

@@ -429,9 +429,11 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
},
YGNodeSetMeasureFunc: {
value: function (nodeName, innerText) {
value: function (nodeName, innerText, flexDirection) {
this.push(
`${nodeName}.setMeasureFunc(instrinsicSizeMeasureFunc.bind("${innerText}"));`,
`${nodeName}.setMeasureFunc(instrinsicSizeMeasureFunc.bind({text: "${innerText}", flexDirection: ${toValueJavascript(
flexDirection,
)}}));`,
);
},
},

View File

@@ -533,7 +533,11 @@ function setupTestTree(
}
if (node.innerText && node.children.length === 0) {
e.YGNodeSetMeasureFunc(nodeName, node.innerText);
e.YGNodeSetMeasureFunc(
nodeName,
node.innerText,
flexDirectionValue(e, node.style['flex-direction']),
);
}
for (let i = 0; i < node.children.length; i++) {

View File

@@ -1,17 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// You can use this script to configure the gradleEnterprise{} block in your build.
// You need to rename this file to ./gradle/gradle-enterprise.gradle.kts in order for
// this to be processed.
extensions.getByName("gradleEnterprise").withGroovyBuilder {
setProperty("server", "https://your-gradle-enterprise-instance.example.com")
getProperty("buildScan").withGroovyBuilder {
"publishAlways"()
"tag"(if(System.getenv("CI") != null) "CI" else "Local")
}
}

Binary file not shown.

View File

@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

26
gradlew vendored
View File

@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -83,7 +85,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +133,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
@@ -141,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -149,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -198,11 +204,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

22
gradlew.bat vendored
View File

@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail

View File

@@ -1,4 +1,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Meta Platforms, Inc. and affiliates.
This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.yoga"
android:versionCode="1"
android:versionName="1.0"
>
<application/>

View File

@@ -9,6 +9,7 @@ plugins {
id("com.android.library")
id("maven-publish")
id("signing")
id("org.jetbrains.kotlin.android")
}
group = "com.facebook.yoga"
@@ -30,6 +31,7 @@ android {
consumerProguardFiles("proguard-rules.pro")
ndk { abiFilters.addAll(setOf("x86", "x86_64", "armeabi-v7a", "arm64-v8a")) }
externalNativeBuild { cmake { arguments("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON") } }
}
externalNativeBuild { cmake { path("CMakeLists.txt") } }
@@ -47,6 +49,8 @@ android {
}
}
kotlinOptions { jvmTarget = "1.8" }
publishing {
multipleVariants {
withSourcesJar()
@@ -59,6 +63,7 @@ android {
dependencies {
implementation("com.google.code.findbugs:jsr305:3.0.2")
implementation("com.facebook.soloader:soloader:0.10.5")
implementation("androidx.core:core-ktx:1.16.0")
testImplementation("junit:junit:4.12")
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga;
public class YogaConstants {
public static final float UNDEFINED = Float.NaN;
public static boolean isUndefined(float value) {
return Float.compare(value, UNDEFINED) == 0;
}
public static boolean isUndefined(YogaValue value) {
return value.unit == YogaUnit.UNDEFINED;
}
public static float getUndefined() {
return UNDEFINED;
}
}

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga
public object YogaConstants {
@JvmField public val UNDEFINED: Float = Float.NaN
@JvmStatic public fun isUndefined(value: Float): Boolean = value.compareTo(UNDEFINED) == 0
@JvmStatic public fun isUndefined(value: YogaValue): Boolean = value.unit == YogaUnit.UNDEFINED
@JvmStatic public fun getUndefined(): Float = UNDEFINED
}

View File

@@ -130,7 +130,7 @@ public class YogaNative {
static native void jni_YGNodeStyleSetMaxHeightStretchJNI(long nativePointer);
static native float jni_YGNodeStyleGetAspectRatioJNI(long nativePointer);
static native void jni_YGNodeStyleSetAspectRatioJNI(long nativePointer, float aspectRatio);
static native float jni_YGNodeStyleGetGapJNI(long nativePointer, int gutter);
static native long jni_YGNodeStyleGetGapJNI(long nativePointer, int gutter);
static native void jni_YGNodeStyleSetGapJNI(long nativePointer, int gutter, float gapLength);
static native void jni_YGNodeStyleSetGapPercentJNI(long nativePointer, int gutter, float gapLength);
static native void jni_YGNodeSetHasMeasureFuncJNI(long nativePointer, boolean hasMeasureFunc);

View File

@@ -1,279 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga;
import javax.annotation.Nullable;
public abstract class YogaNode implements YogaProps {
/** The interface the {@link #getData()} object can optionally implement. */
public interface Inputs {
/** Requests the data object to disable mutations of its inputs. */
void freeze(final YogaNode node, final @Nullable YogaNode parent);
}
public abstract void reset();
public abstract int getChildCount();
public abstract YogaNode getChildAt(int i);
public abstract void addChildAt(YogaNode child, int i);
public abstract void setIsReferenceBaseline(boolean isReferenceBaseline);
public abstract boolean isReferenceBaseline();
public abstract YogaNode removeChildAt(int i);
/**
* @returns the {@link YogaNode} that owns this {@link YogaNode}. The owner is used to identify
* the YogaTree that a {@link YogaNode} belongs to. This method will return the parent of the
* {@link YogaNode} when the {@link YogaNode} only belongs to one YogaTree or null when the
* {@link YogaNode} is shared between two or more YogaTrees.
*/
@Nullable
public abstract YogaNode getOwner();
/** @deprecated Use #getOwner() instead. This will be removed in the next version. */
@Deprecated
@Nullable
public abstract YogaNode getParent();
public abstract int indexOf(YogaNode child);
public abstract void calculateLayout(float width, float height);
public abstract boolean hasNewLayout();
public abstract void dirty();
public abstract boolean isDirty();
public abstract void copyStyle(YogaNode srcNode);
public abstract void markLayoutSeen();
public abstract YogaDirection getStyleDirection();
public abstract void setDirection(YogaDirection direction);
public abstract YogaFlexDirection getFlexDirection();
public abstract void setFlexDirection(YogaFlexDirection flexDirection);
public abstract YogaJustify getJustifyContent();
public abstract void setJustifyContent(YogaJustify justifyContent);
public abstract YogaAlign getAlignItems();
public abstract void setAlignItems(YogaAlign alignItems);
public abstract YogaAlign getAlignSelf();
public abstract void setAlignSelf(YogaAlign alignSelf);
public abstract YogaAlign getAlignContent();
public abstract void setAlignContent(YogaAlign alignContent);
public abstract YogaPositionType getPositionType();
public abstract void setPositionType(YogaPositionType positionType);
public abstract YogaBoxSizing getBoxSizing();
public abstract void setBoxSizing(YogaBoxSizing boxSizing);
public abstract YogaWrap getWrap();
public abstract void setWrap(YogaWrap flexWrap);
public abstract YogaOverflow getOverflow();
public abstract void setOverflow(YogaOverflow overflow);
public abstract YogaDisplay getDisplay();
public abstract void setDisplay(YogaDisplay display);
public abstract float getFlex();
public abstract void setFlex(float flex);
public abstract float getFlexGrow();
public abstract void setFlexGrow(float flexGrow);
public abstract float getFlexShrink();
public abstract void setFlexShrink(float flexShrink);
public abstract YogaValue getFlexBasis();
public abstract void setFlexBasis(float flexBasis);
public abstract void setFlexBasisPercent(float percent);
public abstract void setFlexBasisAuto();
public abstract void setFlexBasisMaxContent();
public abstract void setFlexBasisFitContent();
public abstract void setFlexBasisStretch();
public abstract YogaValue getMargin(YogaEdge edge);
public abstract void setMargin(YogaEdge edge, float margin);
public abstract void setMarginPercent(YogaEdge edge, float percent);
public abstract void setMarginAuto(YogaEdge edge);
public abstract YogaValue getPadding(YogaEdge edge);
public abstract void setPadding(YogaEdge edge, float padding);
public abstract void setPaddingPercent(YogaEdge edge, float percent);
public abstract float getBorder(YogaEdge edge);
public abstract void setBorder(YogaEdge edge, float border);
public abstract YogaValue getPosition(YogaEdge edge);
public abstract void setPosition(YogaEdge edge, float position);
public abstract void setPositionPercent(YogaEdge edge, float percent);
public abstract void setPositionAuto(YogaEdge edge);
public abstract YogaValue getWidth();
public abstract void setWidth(float width);
public abstract void setWidthPercent(float percent);
public abstract void setWidthAuto();
public abstract void setWidthMaxContent();
public abstract void setWidthFitContent();
public abstract void setWidthStretch();
public abstract YogaValue getHeight();
public abstract void setHeight(float height);
public abstract void setHeightPercent(float percent);
public abstract void setHeightAuto();
public abstract void setHeightMaxContent();
public abstract void setHeightFitContent();
public abstract void setHeightStretch();
public abstract YogaValue getMinWidth();
public abstract void setMinWidth(float minWidth);
public abstract void setMinWidthPercent(float percent);
public abstract void setMinWidthMaxContent();
public abstract void setMinWidthFitContent();
public abstract void setMinWidthStretch();
public abstract YogaValue getMinHeight();
public abstract void setMinHeight(float minHeight);
public abstract void setMinHeightPercent(float percent);
public abstract void setMinHeightMaxContent();
public abstract void setMinHeightFitContent();
public abstract void setMinHeightStretch();
public abstract YogaValue getMaxWidth();
public abstract void setMaxWidth(float maxWidth);
public abstract void setMaxWidthPercent(float percent);
public abstract void setMaxWidthMaxContent();
public abstract void setMaxWidthFitContent();
public abstract void setMaxWidthStretch();
public abstract YogaValue getMaxHeight();
public abstract void setMaxHeight(float maxheight);
public abstract void setMaxHeightPercent(float percent);
public abstract void setMaxHeightMaxContent();
public abstract void setMaxHeightFitContent();
public abstract void setMaxHeightStretch();
public abstract float getAspectRatio();
public abstract void setAspectRatio(float aspectRatio);
public abstract float getGap(YogaGutter gutter);
public abstract void setGap(YogaGutter gutter, float gapLength);
public abstract void setGapPercent(YogaGutter gutter, float gapLength);
public abstract float getLayoutX();
public abstract float getLayoutY();
public abstract float getLayoutWidth();
public abstract float getLayoutHeight();
public abstract float getLayoutMargin(YogaEdge edge);
public abstract float getLayoutPadding(YogaEdge edge);
public abstract float getLayoutBorder(YogaEdge edge);
public abstract YogaDirection getLayoutDirection();
public abstract void setMeasureFunction(YogaMeasureFunction measureFunction);
public abstract void setBaselineFunction(YogaBaselineFunction baselineFunction);
public abstract boolean isMeasureDefined();
public abstract boolean isBaselineDefined();
public abstract void setData(Object data);
@Nullable
public abstract Object getData();
public abstract YogaNode cloneWithoutChildren();
public abstract YogaNode cloneWithChildren();
public abstract void setAlwaysFormsContainingBlock(boolean alwaysFormsContainingBlock);
}

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga
public abstract class YogaNode : YogaProps {
/** The interface the [getData] object can optionally implement. */
public fun interface Inputs {
/** Requests the data object to disable mutations of its inputs. */
public fun freeze(node: YogaNode, parent: YogaNode?)
}
public abstract fun reset()
public abstract fun getChildCount(): Int
public abstract fun getChildAt(i: Int): YogaNode
public abstract fun addChildAt(child: YogaNode, i: Int)
abstract override fun setIsReferenceBaseline(isReferenceBaseline: Boolean)
public abstract fun isReferenceBaseline(): Boolean
public abstract fun removeChildAt(i: Int): YogaNode
/**
* @returns the [YogaNode] that owns this [YogaNode]. The owner is used to identify the YogaTree
* that a [YogaNode] belongs to. This method will return the parent of the [YogaNode] when the
* [YogaNode] only belongs to one YogaTree or null when the [YogaNode] is shared between two or
* more YogaTrees.
*/
public abstract fun getOwner(): YogaNode?
@Deprecated(
"Use getOwner() instead. This will be removed in the next version. ",
replaceWith = ReplaceWith("getOwner()"))
public abstract fun getParent(): YogaNode?
public abstract fun indexOf(child: YogaNode): Int
public abstract fun calculateLayout(width: Float, height: Float)
public abstract fun hasNewLayout(): Boolean
public abstract fun dirty()
public abstract fun isDirty(): Boolean
public abstract fun copyStyle(srcNode: YogaNode)
public abstract fun markLayoutSeen()
abstract override fun getStyleDirection(): YogaDirection
abstract override fun setDirection(direction: YogaDirection)
abstract override fun getFlexDirection(): YogaFlexDirection
abstract override fun setFlexDirection(flexDirection: YogaFlexDirection)
abstract override fun getJustifyContent(): YogaJustify
abstract override fun setJustifyContent(justifyContent: YogaJustify)
abstract override fun getAlignItems(): YogaAlign
abstract override fun setAlignItems(alignItems: YogaAlign)
abstract override fun getAlignSelf(): YogaAlign
abstract override fun setAlignSelf(alignSelf: YogaAlign)
abstract override fun getAlignContent(): YogaAlign
abstract override fun setAlignContent(alignContent: YogaAlign)
abstract override fun getPositionType(): YogaPositionType
abstract override fun setPositionType(positionType: YogaPositionType)
abstract override fun getBoxSizing(): YogaBoxSizing
abstract override fun setBoxSizing(boxSizing: YogaBoxSizing)
public abstract fun getWrap(): YogaWrap
abstract override fun setWrap(flexWrap: YogaWrap)
public abstract fun getOverflow(): YogaOverflow
public abstract fun setOverflow(overflow: YogaOverflow)
public abstract fun getDisplay(): YogaDisplay
public abstract fun setDisplay(display: YogaDisplay)
public abstract fun getFlex(): Float
abstract override fun setFlex(flex: Float)
abstract override fun getFlexGrow(): Float
abstract override fun setFlexGrow(flexGrow: Float)
abstract override fun getFlexShrink(): Float
abstract override fun setFlexShrink(flexShrink: Float)
abstract override fun getFlexBasis(): YogaValue
abstract override fun setFlexBasis(flexBasis: Float)
abstract override fun setFlexBasisPercent(percent: Float)
abstract override fun setFlexBasisAuto()
abstract override fun setFlexBasisMaxContent()
abstract override fun setFlexBasisFitContent()
abstract override fun setFlexBasisStretch()
abstract override fun getMargin(edge: YogaEdge): YogaValue
abstract override fun setMargin(edge: YogaEdge, margin: Float)
abstract override fun setMarginPercent(edge: YogaEdge, percent: Float)
abstract override fun setMarginAuto(edge: YogaEdge)
abstract override fun getPadding(edge: YogaEdge): YogaValue
abstract override fun setPadding(edge: YogaEdge, padding: Float)
abstract override fun setPaddingPercent(edge: YogaEdge, percent: Float)
abstract override fun getBorder(edge: YogaEdge): Float
abstract override fun setBorder(edge: YogaEdge, border: Float)
abstract override fun getPosition(edge: YogaEdge): YogaValue
abstract override fun setPosition(edge: YogaEdge, position: Float)
abstract override fun setPositionPercent(edge: YogaEdge, percent: Float)
public abstract fun setPositionAuto(edge: YogaEdge)
abstract override fun getWidth(): YogaValue
abstract override fun setWidth(width: Float)
abstract override fun setWidthPercent(percent: Float)
abstract override fun setWidthAuto()
abstract override fun setWidthMaxContent()
abstract override fun setWidthFitContent()
abstract override fun setWidthStretch()
abstract override fun getHeight(): YogaValue
abstract override fun setHeight(height: Float)
abstract override fun setHeightPercent(percent: Float)
abstract override fun setHeightAuto()
abstract override fun setHeightMaxContent()
abstract override fun setHeightFitContent()
abstract override fun setHeightStretch()
abstract override fun getMinWidth(): YogaValue
abstract override fun setMinWidth(minWidth: Float)
abstract override fun setMinWidthPercent(percent: Float)
abstract override fun setMinWidthMaxContent()
abstract override fun setMinWidthFitContent()
abstract override fun setMinWidthStretch()
abstract override fun getMinHeight(): YogaValue
abstract override fun setMinHeight(minHeight: Float)
abstract override fun setMinHeightPercent(percent: Float)
abstract override fun setMinHeightMaxContent()
abstract override fun setMinHeightFitContent()
abstract override fun setMinHeightStretch()
abstract override fun getMaxWidth(): YogaValue
abstract override fun setMaxWidth(maxWidth: Float)
abstract override fun setMaxWidthPercent(percent: Float)
abstract override fun setMaxWidthMaxContent()
abstract override fun setMaxWidthFitContent()
abstract override fun setMaxWidthStretch()
abstract override fun getMaxHeight(): YogaValue
abstract override fun setMaxHeight(maxheight: Float)
abstract override fun setMaxHeightPercent(percent: Float)
abstract override fun setMaxHeightMaxContent()
abstract override fun setMaxHeightFitContent()
abstract override fun setMaxHeightStretch()
abstract override fun getAspectRatio(): Float
abstract override fun setAspectRatio(aspectRatio: Float)
public abstract fun getGap(gutter: YogaGutter): YogaValue
public abstract fun setGap(gutter: YogaGutter, gapLength: Float)
public abstract fun setGapPercent(gutter: YogaGutter, gapLength: Float)
public abstract fun getLayoutX(): Float
public abstract fun getLayoutY(): Float
public abstract fun getLayoutWidth(): Float
public abstract fun getLayoutHeight(): Float
public abstract fun getLayoutMargin(edge: YogaEdge): Float
public abstract fun getLayoutPadding(edge: YogaEdge): Float
public abstract fun getLayoutBorder(edge: YogaEdge): Float
public abstract fun getLayoutDirection(): YogaDirection
abstract override fun setMeasureFunction(measureFunction: YogaMeasureFunction)
abstract override fun setBaselineFunction(baselineFunction: YogaBaselineFunction)
public abstract fun isMeasureDefined(): Boolean
public abstract fun isBaselineDefined(): Boolean
public abstract fun setData(data: Any)
public abstract fun getData(): Any?
public abstract fun cloneWithoutChildren(): YogaNode
public abstract fun cloneWithChildren(): YogaNode
public abstract fun setAlwaysFormsContainingBlock(alwaysFormsContainingBlock: Boolean)
}

View File

@@ -811,8 +811,8 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
}
@Override
public float getGap(YogaGutter gutter) {
return YogaNative.jni_YGNodeStyleGetGapJNI(mNativePointer, gutter.intValue());
public YogaValue getGap(YogaGutter gutter) {
return valueFromLong(YogaNative.jni_YGNodeStyleGetGapJNI(mNativePointer, gutter.intValue()));
}
@Override

View File

@@ -725,13 +725,13 @@ jni_YGNodeCloneJNI(JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) {
return reinterpret_cast<jlong>(clonedYogaNode);
}
static jfloat jni_YGNodeStyleGetGapJNI(
static jlong jni_YGNodeStyleGetGapJNI(
JNIEnv* /*env*/,
jobject /*obj*/,
jlong nativePointer,
jint gutter) {
return (jfloat)YGNodeStyleGetGap(
_jlong2YGNodeRef(nativePointer), static_cast<YGGutter>(gutter));
return YogaValue::asJavaLong(YGNodeStyleGetGap(
_jlong2YGNodeRef(nativePointer), static_cast<YGGutter>(gutter)));
}
static void jni_YGNodeStyleSetGapJNI(
@@ -1057,7 +1057,7 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeSetHasMeasureFuncJNI",
"(JZ)V",
(void*)jni_YGNodeSetHasMeasureFuncJNI},
{"jni_YGNodeStyleGetGapJNI", "(JI)F", (void*)jni_YGNodeStyleGetGapJNI},
{"jni_YGNodeStyleGetGapJNI", "(JI)J", (void*)jni_YGNodeStyleGetGapJNI},
{"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*)jni_YGNodeStyleSetGapJNI},
{"jni_YGNodeStyleSetGapPercentJNI",
"(JIF)V",

View File

@@ -11,6 +11,7 @@ import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaFlexDirection;
public class TestUtils {
@@ -43,9 +44,13 @@ public class TestUtils {
} else if (heightMode == YogaMeasureMode.AT_MOST) {
measuredHeight =
Math.min(
caclulateHeight(text, Math.max(measuredWidth, getWidestWordWidth(text))), height);
caclulateHeight(text, node.getFlexDirection() == YogaFlexDirection.COLUMN
? measuredWidth
: Math.max(measuredWidth, getWidestWordWidth(text))), height);
} else {
measuredHeight = caclulateHeight(text, Math.max(measuredWidth, getWidestWordWidth(text)));
measuredHeight = caclulateHeight(text, node.getFlexDirection() == YogaFlexDirection.COLUMN
? measuredWidth
: Math.max(measuredWidth, getWidestWordWidth(text)));
}
return YogaMeasureOutput.make(measuredWidth, measuredHeight);

View File

@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e8d11c0e97041bb2f1487f0d87363fdc>>
* @generated SignedSource<<84597dd8b2c4f3aac1f21abe68f25308>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
*/
@@ -2293,6 +2293,86 @@ public class YGAlignItemsTest {
assertEquals(50f, root_child1.getLayoutHeight(), 0.0f);
}
@Test
public void test_align_items_non_stretch_s526008() {
YogaConfig config = YogaConfigFactory.create();
final YogaNode root = createNode(config);
root.setPositionType(YogaPositionType.ABSOLUTE);
root.setWidth(400f);
root.setHeight(400f);
final YogaNode root_child0 = createNode(config);
root_child0.setFlexDirection(YogaFlexDirection.ROW);
root.addChildAt(root_child0, 0);
final YogaNode root_child0_child0 = createNode(config);
root_child0_child0.setAlignItems(YogaAlign.FLEX_START);
root_child0.addChildAt(root_child0_child0, 0);
final YogaNode root_child0_child0_child0 = createNode(config);
root_child0_child0.addChildAt(root_child0_child0_child0, 0);
final YogaNode root_child0_child0_child0_child0 = createNode(config);
root_child0_child0_child0_child0.setHeight(10f);
root_child0_child0_child0.addChildAt(root_child0_child0_child0_child0, 0);
root.setDirection(YogaDirection.LTR);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertEquals(0f, root.getLayoutX(), 0.0f);
assertEquals(0f, root.getLayoutY(), 0.0f);
assertEquals(400f, root.getLayoutWidth(), 0.0f);
assertEquals(400f, root.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
assertEquals(400f, root_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0_child0.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0_child0_child0.getLayoutHeight(), 0.0f);
root.setDirection(YogaDirection.RTL);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertEquals(0f, root.getLayoutX(), 0.0f);
assertEquals(0f, root.getLayoutY(), 0.0f);
assertEquals(400f, root.getLayoutWidth(), 0.0f);
assertEquals(400f, root.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0.getLayoutY(), 0.0f);
assertEquals(400f, root_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0.getLayoutHeight(), 0.0f);
assertEquals(400f, root_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0_child0.getLayoutHeight(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutX(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutY(), 0.0f);
assertEquals(0f, root_child0_child0_child0_child0.getLayoutWidth(), 0.0f);
assertEquals(10f, root_child0_child0_child0_child0.getLayoutHeight(), 0.0f);
}
private YogaNode createNode(YogaConfig config) {
return mNodeFactory.create(config);
}

View File

@@ -439,8 +439,9 @@ Value Node::getPadding(int edge) const {
YGNodeStyleGetPadding(m_node, static_cast<YGEdge>(edge)));
}
float Node::getGap(int gutter) {
return YGNodeStyleGetGap(m_node, static_cast<YGGutter>(gutter));
Value Node::getGap(int gutter) const {
return Value::fromYGValue(
YGNodeStyleGetGap(m_node, static_cast<YGGutter>(gutter)));
}
bool Node::isReferenceBaseline() {

View File

@@ -186,7 +186,7 @@ class Node {
Value getPadding(int edge) const;
float getGap(int gutter);
Value getGap(int gutter) const;
int getBoxSizing(void) const;

View File

@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<075a0b67003e5c4a1f51bd99da71c700>>
* @generated SignedSource<<fd80af208d8635435f86ffa8f3810b39>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
*/
@@ -2442,3 +2442,88 @@ test('align_stretch_with_row_reverse', () => {
config.free();
}
});
test('align_items_non_stretch_s526008', () => {
const config = Yoga.Config.create();
let root;
try {
root = Yoga.Node.create(config);
root.setPositionType(PositionType.Absolute);
root.setWidth(400);
root.setHeight(400);
const root_child0 = Yoga.Node.create(config);
root_child0.setFlexDirection(FlexDirection.Row);
root.insertChild(root_child0, 0);
const root_child0_child0 = Yoga.Node.create(config);
root_child0_child0.setAlignItems(Align.FlexStart);
root_child0.insertChild(root_child0_child0, 0);
const root_child0_child0_child0 = Yoga.Node.create(config);
root_child0_child0.insertChild(root_child0_child0_child0, 0);
const root_child0_child0_child0_child0 = Yoga.Node.create(config);
root_child0_child0_child0_child0.setHeight(10);
root_child0_child0_child0.insertChild(root_child0_child0_child0_child0, 0);
root.calculateLayout(undefined, undefined, Direction.LTR);
expect(root.getComputedLeft()).toBe(0);
expect(root.getComputedTop()).toBe(0);
expect(root.getComputedWidth()).toBe(400);
expect(root.getComputedHeight()).toBe(400);
expect(root_child0.getComputedLeft()).toBe(0);
expect(root_child0.getComputedTop()).toBe(0);
expect(root_child0.getComputedWidth()).toBe(400);
expect(root_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0.getComputedLeft()).toBe(0);
expect(root_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0_child0.getComputedLeft()).toBe(0);
expect(root_child0_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0_child0_child0.getComputedLeft()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedHeight()).toBe(10);
root.calculateLayout(undefined, undefined, Direction.RTL);
expect(root.getComputedLeft()).toBe(0);
expect(root.getComputedTop()).toBe(0);
expect(root.getComputedWidth()).toBe(400);
expect(root.getComputedHeight()).toBe(400);
expect(root_child0.getComputedLeft()).toBe(0);
expect(root_child0.getComputedTop()).toBe(0);
expect(root_child0.getComputedWidth()).toBe(400);
expect(root_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0.getComputedLeft()).toBe(400);
expect(root_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0_child0.getComputedLeft()).toBe(0);
expect(root_child0_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0_child0.getComputedHeight()).toBe(10);
expect(root_child0_child0_child0_child0.getComputedLeft()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedTop()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedWidth()).toBe(0);
expect(root_child0_child0_child0_child0.getComputedHeight()).toBe(10);
} finally {
if (typeof root !== 'undefined') {
root.freeRecursive();
}
config.free();
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -5,17 +5,23 @@
* LICENSE file in the root directory of this source tree.
*/
import {MeasureMode} from 'yoga-layout';
import {FlexDirection, MeasureMode} from 'yoga-layout';
type MeasureContext = {
text: string;
flexDirection: FlexDirection;
};
export function instrinsicSizeMeasureFunc(
this: string,
this: MeasureContext,
width: number,
widthMode: MeasureMode,
height: number,
heightMode: MeasureMode,
): {width: number; height: number} {
const textLength = this.length;
const words = this.split(' ');
const textLength = this.text.length;
const words = this.text.split(' ');
const flexDirection = this.flexDirection;
const widthPerChar = 10;
const heightPerChar = 10;
@@ -53,7 +59,10 @@ export function instrinsicSizeMeasureFunc(
return heightPerChar;
}
const maxLineWidth = Math.max(longestWordWidth(), measuredWidth);
const maxLineWidth =
flexDirection == FlexDirection.Column
? measuredWidth
: Math.max(longestWordWidth(), measuredWidth);
//if fixed width < width of widest word, take width of widest word

View File

@@ -19,10 +19,11 @@ include(":yoga")
project(":yoga").projectDir = file("java")
rootProject.name = "yoga-github"
// If you specify a file inside gradle/gradle-enterprise.gradle.kts
// you can configure your custom Gradle Enterprise instance
if (file("./gradle/gradle-enterprise.gradle.kts").exists()) {
apply(from = "./gradle/gradle-enterprise.gradle.kts")
gradleEnterprise {
buildScan {
termsOfServiceUrl = "https://gradle.com/terms-of-service"
termsOfServiceAgree = "yes"
}
}
rootProject.name = "yoga-github"

7
tests/.clang-tidy Normal file
View File

@@ -0,0 +1,7 @@
---
InheritParentConfig: true
Checks: '
-facebook-hte-CArray,
-modernize-avoid-c-arrays,
'
...

View File

@@ -0,0 +1,214 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <yoga/Yoga.h>
#include <yoga/config/Config.h>
#include <yoga/node/Node.h>
#include <functional>
#include <memory>
#include <vector>
namespace facebook::yoga {
struct YGPersistentNodeCloningTest : public ::testing::Test {
struct NodeWrapper {
explicit NodeWrapper(
YGConfigRef config,
std::vector<std::shared_ptr<NodeWrapper>> children = {})
: node{YGNodeNewWithConfig(config)}, children{std::move(children)} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
for (const auto& child : this->children) {
auto privateChild = resolveRef(child->node);
// Claim first ownership of not yet owned nodes, to avoid immediately
// cloning them
if (YGNodeGetOwner(child->node) == nullptr) {
privateChild->setOwner(privateNode);
}
privateNode->insertChild(privateChild, privateNode->getChildCount());
}
}
// Clone, with current children, for mutation
NodeWrapper(const NodeWrapper& other)
: node{YGNodeClone(other.node)}, children{other.children} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
privateNode->setOwner(nullptr);
}
// Clone, with new children
NodeWrapper(
const NodeWrapper& other,
std::vector<std::shared_ptr<NodeWrapper>> children)
: node{YGNodeClone(other.node)}, children{std::move(children)} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
privateNode->setOwner(nullptr);
privateNode->setChildren({});
privateNode->setDirty(true);
for (const auto& child : this->children) {
auto privateChild = resolveRef(child->node);
// Claim first ownership of not yet owned nodes, to avoid immediately
// cloning them
if (YGNodeGetOwner(child->node) == nullptr) {
privateChild->setOwner(privateNode);
}
privateNode->insertChild(privateChild, privateNode->getChildCount());
}
}
NodeWrapper(NodeWrapper&&) = delete;
~NodeWrapper() {
YGNodeFree(node);
}
NodeWrapper& operator=(const NodeWrapper& other) = delete;
NodeWrapper& operator=(NodeWrapper&& other) = delete;
YGNodeRef node;
std::vector<std::shared_ptr<NodeWrapper>> children;
};
struct ConfigWrapper {
ConfigWrapper() {
YGConfigSetCloneNodeFunc(
config,
[](YGNodeConstRef oldNode, YGNodeConstRef owner, size_t childIndex) {
onClone(oldNode, owner, childIndex);
auto wrapper = static_cast<NodeWrapper*>(YGNodeGetContext(owner));
auto old = static_cast<NodeWrapper*>(YGNodeGetContext(oldNode));
wrapper->children[childIndex] = std::make_shared<NodeWrapper>(*old);
return wrapper->children[childIndex]->node;
});
}
ConfigWrapper(const ConfigWrapper&) = delete;
ConfigWrapper(ConfigWrapper&&) = delete;
~ConfigWrapper() {
YGConfigFree(config);
}
ConfigWrapper& operator=(const ConfigWrapper&) = delete;
ConfigWrapper& operator=(ConfigWrapper&&) = delete;
YGConfigRef config{YGConfigNew()};
};
ConfigWrapper configWrapper;
YGConfigRef config{configWrapper.config};
void SetUp() override {
onClone = [](...) {};
}
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static inline std::function<void(YGNodeConstRef, YGNodeConstRef, size_t)>
onClone;
};
TEST_F(
YGPersistentNodeCloningTest,
changing_sibling_height_does_not_clone_neighbors) {
// <ScrollView>
// <View id="Sibling" style={{ height: 1 }} />
// <View id="A" style={{ height: 1 }}>
// <View id="B">
// <View id="C">
// <View id="D"/>
// </View>
// </View>
// </View>
// </ScrollView>
auto sibling = std::make_shared<NodeWrapper>(config);
YGNodeStyleSetHeight(sibling->node, 1);
auto d = std::make_shared<NodeWrapper>(config);
auto c = std::make_shared<NodeWrapper>(config, std::vector{d});
auto b = std::make_shared<NodeWrapper>(config, std::vector{c});
auto a = std::make_shared<NodeWrapper>(config, std::vector{b});
YGNodeStyleSetHeight(a->node, 1);
auto scrollContentView =
std::make_shared<NodeWrapper>(config, std::vector{sibling, a});
YGNodeStyleSetPositionType(scrollContentView->node, YGPositionTypeAbsolute);
auto scrollView =
std::make_shared<NodeWrapper>(config, std::vector{scrollContentView});
YGNodeStyleSetWidth(scrollView->node, 100);
YGNodeStyleSetHeight(scrollView->node, 100);
// We don't expect any cloning during the first layout
onClone = [](...) { FAIL(); };
YGNodeCalculateLayout(
scrollView->node, YGUndefined, YGUndefined, YGDirectionLTR);
auto siblingPrime = std::make_shared<NodeWrapper>(config);
YGNodeStyleSetHeight(siblingPrime->node, 2);
auto scrollContentViewPrime = std::make_shared<NodeWrapper>(
*scrollContentView, std::vector{siblingPrime, a});
auto scrollViewPrime = std::make_shared<NodeWrapper>(
*scrollView, std::vector{scrollContentViewPrime});
std::vector<NodeWrapper*> nodesCloned;
// We should only need to clone "A"
onClone = [&](YGNodeConstRef oldNode,
YGNodeConstRef /*owner*/,
size_t /*childIndex*/) {
nodesCloned.push_back(static_cast<NodeWrapper*>(YGNodeGetContext(oldNode)));
};
YGNodeCalculateLayout(
scrollViewPrime->node, YGUndefined, YGUndefined, YGDirectionLTR);
EXPECT_EQ(nodesCloned.size(), 1);
EXPECT_EQ(nodesCloned[0], a.get());
}
TEST_F(YGPersistentNodeCloningTest, clone_leaf_display_contents_node) {
// <View id="A">
// <View id="B" style={{ display: 'contents' }} />
// </View>
auto b = std::make_shared<NodeWrapper>(config);
auto a = std::make_shared<NodeWrapper>(config, std::vector{b});
YGNodeStyleSetDisplay(b->node, YGDisplayContents);
// We don't expect any cloning during the first layout
onClone = [](...) { FAIL(); };
YGNodeCalculateLayout(a->node, YGUndefined, YGUndefined, YGDirectionLTR);
auto aPrime = std::make_shared<NodeWrapper>(config, std::vector{b});
std::vector<NodeWrapper*> nodesCloned;
// We should clone "C"
onClone = [&](YGNodeConstRef oldNode,
YGNodeConstRef /*owner*/,
size_t /*childIndex*/) {
nodesCloned.push_back(static_cast<NodeWrapper*>(YGNodeGetContext(oldNode)));
};
YGNodeCalculateLayout(aPrime->node, 100, 100, YGDirectionLTR);
EXPECT_EQ(nodesCloned.size(), 1);
EXPECT_EQ(nodesCloned[0], b.get());
}
} // namespace facebook::yoga

View File

@@ -8,6 +8,8 @@
#include <gtest/gtest.h>
#include <yoga/Yoga.h>
#include <cmath>
TEST(YogaTest, rounding_value) {
// Test that whole numbers are rounded to whole despite ceil/floor flags
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, false));
@@ -39,6 +41,44 @@ TEST(YogaTest, rounding_value) {
ASSERT_FLOAT_EQ(-6.0, YGRoundValueToPixelGrid(-5.99, 2.0, false, false));
ASSERT_FLOAT_EQ(-5.5, YGRoundValueToPixelGrid(-5.99, 2.0, true, false));
ASSERT_FLOAT_EQ(-6.0, YGRoundValueToPixelGrid(-5.99, 2.0, false, true));
// Rounding up/down halfway values is as expected for both positive and
// negative numbers
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.5, 1.0, false, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.4, 1.0, false, false));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.6, 1.0, false, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.499999, 1.0, false, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.500001, 1.0, false, false));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.5001, 1.0, false, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.5, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.4, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.6, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.499999, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.500001, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.5001, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.00001, 1.0, true, false));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3, 1.0, true, false));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.5, 1.0, false, true));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.4, 1.0, false, true));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.6, 1.0, false, true));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.499999, 1.0, false, true));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.500001, 1.0, false, true));
ASSERT_FLOAT_EQ(-4, YGRoundValueToPixelGrid(-3.5001, 1.0, false, true));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3.00001, 1.0, false, true));
ASSERT_FLOAT_EQ(-3, YGRoundValueToPixelGrid(-3, 1.0, false, true));
// NAN is treated as expected:
ASSERT_TRUE(std::isnan(YGRoundValueToPixelGrid(
std::numeric_limits<double>::quiet_NaN(), 1.5, false, false)));
ASSERT_TRUE(std::isnan(YGRoundValueToPixelGrid(
1.5, std::numeric_limits<double>::quiet_NaN(), false, false)));
ASSERT_TRUE(std::isnan(YGRoundValueToPixelGrid(
std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(),
false,
false)));
}
static YGSize measureText(
@@ -121,3 +161,23 @@ TEST(YogaTest, per_node_point_scale_factor) {
YGConfigFree(config2);
YGConfigFree(config3);
}
TEST(YogaTest, raw_layout_dimensions) {
YGConfigRef config = YGConfigNew();
YGConfigSetPointScaleFactor(config, 0.5f);
YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 11.5f);
YGNodeStyleSetHeight(root, 9.5f);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_EQ(YGNodeLayoutGetWidth(root), 12.0f);
ASSERT_EQ(YGNodeLayoutGetHeight(root), 10.0f);
ASSERT_EQ(YGNodeLayoutGetRawWidth(root), 11.5f);
ASSERT_EQ(YGNodeLayoutGetRawHeight(root), 9.5f);
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* clang-format off
* @generated SignedSource<<71295a398c89ea424490884a05e2c77c>>
* @generated SignedSource<<1db57b05babb408c08efcec7dbdf16fb>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGAlignItemsTest.html
*/
@@ -2310,3 +2310,84 @@ TEST(YogaTest, align_stretch_with_row_reverse) {
YGConfigFree(config);
}
TEST(YogaTest, align_items_non_stretch_s526008) {
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
YGNodeStyleSetWidth(root, 400);
YGNodeStyleSetHeight(root, 400);
YGNodeRef root_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
YGNodeInsertChild(root, root_child0, 0);
YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetAlignItems(root_child0_child0, YGAlignFlexStart);
YGNodeInsertChild(root_child0, root_child0_child0, 0);
YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
YGNodeRef root_child0_child0_child0_child0 = YGNodeNewWithConfig(config);
YGNodeStyleSetHeight(root_child0_child0_child0_child0, 10);
YGNodeInsertChild(root_child0_child0_child0, root_child0_child0_child0_child0, 0);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetLeft(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

File diff suppressed because it is too large Load Diff

View File

@@ -90,14 +90,20 @@ YGSize IntrinsicSizeMeasure(
measuredHeight = std::min(
calculateHeight(
innerText,
std::max(longestWordWidth(innerText, widthPerChar), measuredWidth),
YGNodeStyleGetFlexDirection(node) == YGFlexDirectionColumn
? measuredWidth
: std::max(
longestWordWidth(innerText, widthPerChar), measuredWidth),
widthPerChar,
heightPerChar),
height);
} else {
measuredHeight = calculateHeight(
innerText,
std::max(longestWordWidth(innerText, widthPerChar), measuredWidth),
YGNodeStyleGetFlexDirection(node) == YGFlexDirectionColumn
? measuredWidth
: std::max(
longestWordWidth(innerText, widthPerChar), measuredWidth),
widthPerChar,
heightPerChar);
}

View File

@@ -0,0 +1,83 @@
---
slug: announcing-yoga-3.2
title: Announcing Yoga 3.2
authors:
- NickGerleman
---
import Playground from '@site/src/components/Playground';
Yoga 3.2 is a new minor version of Yoga, used by React Native 0.77.
## Highlights
1. Support for `box-sizing`
2. Support for `display: contents`
3. Bug fixes and improvements
## `box-sizing`
Yoga [now supports](https://github.com/facebook/yoga/commit/671ae61a39d02091d1e73fe773d6a09f2f93cda4) [`box-sizing`](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) on styles, allowing sizing values to influence the content box instead of the border box.
:::warning
To preserve compatibility, Yoga nodes default to `box-sizing: border-box`, even if `UseWebDefaults` is set. We recommend manually setting node defaults instead of using the `UseWebDefaults` API.
:::
<Playground code={`<Layout config={{useWebDefaults: true}}>
<Node
style={{
width: 100,
height: 100,
padding: 50,
boxSizing: "border-box",
}}>
</Node>
</Layout>`} />
<Playground code={`<Layout config={{useWebDefaults: true}}>
<Node
style={{
width: 100,
height: 100,
padding: 50,
boxSizing: "content-box",
}}>
</Node>
</Layout>`} />
## `display: contents`
Yoga nodes [may now be set to `display: contents`](https://github.com/facebook/yoga/commit/68bb2343d2b470962065789d09016bba8e785340) to remove them from the layout flow, while preserving and hoisting the node's children. This may be used by the higher level UI framework to allow more easily composing wrapper components (such as those which may need to handle events, without influencing child layout). Thanks [@j-piasecki](https://github.com/j-piasecki) for the contribution!
<Playground code={`<Layout config={{useWebDefaults: false}}>
<Node
style={{
width: 100,
height: 100,
gap: 10,
}}
>
<Node style={{display: "contents"}}>
<Node style={{flexGrow: 1}} />
<Node style={{flexGrow: 1}} />
<Node style={{flexGrow: 1}} />
</Node>
</Node>
</Layout>`} />
## Removal of legacy absolute positioning
Yoga 3.0 introduced a new algorithm used for absolute positioning. This algorithm is more correct than the one previously used, but led to observed compatibility issues with existing code, so we left the option to disable it via the `AbsolutePositioningIncorrect` erratum (enabled by default in frameworks like React Native). Yoga 3.2 removes the legacy absolute positioning path, but ports over the main compatibility quirk under a new erratum `AbsolutePositionWithoutInsetsExcludesPadding` (where the previous incorrect behavior would omit padding when a position was not specified on the absolute node). Errata users should see more correct absolute positioning behavior, while preserving compatibility with existing code.
## Fixed non-global YogaConfig in Java bindings
Yoga would previously allow garbage collection of a `YogaConfig` if it was not retained outside of the Yoga tree. This could result in confusing errors caused by use-after free. Yoga nodes [now correctly retain the configs they are using](https://github.com/facebook/yoga/commit/22b018c957e930de950338ad87f4ef8d59e8a169). Thanks [@michaeltroger](https://github.com/michaeltroger) for this fix!
## Fixed behavior when combining `align-items` with `align-content`
A regression [was fixed](https://github.com/facebook/yoga/commit/77c99870127e9c2d46a07264fa372025334d8fd0) in how Yoga handles some combinations of `align-content` and `align-items`. Thanks [@phuccvx12](https://github.com/phuccvx12) for this fix!

View File

@@ -17,15 +17,15 @@ has effect when items are wrapped to multiple lines using [flex wrap](/docs/styl
**Center**: Align wrapped lines in the center of the container's cross axis.
**Space between**: Evenly space wrapped lines across the container's main axis, distributing
**Space between**: Evenly space wrapped lines across the container's cross axis, distributing
remaining space between the lines.
**Space around**: Evenly space wrapped lines across the container's main axis, distributing
**Space around**: Evenly space wrapped lines across the container's cross axis, distributing
remaining space around the lines. Compared to space between using
space around will result in space being distributed to the beginning of
the first lines and end of the last line.
**Space evenly**: Evenly space wrapped lines across the container's main axis, distributing
**Space evenly**: Evenly space wrapped lines across the container's cross axis, distributing
remaining space around the lines. Compared to space around, space evenly will not
double the gaps between children. The size of gaps between children and between
the parent's edges and the first/last child will all be equal.

View File

@@ -63,7 +63,7 @@ export type FlexStyle = {
bottom?: number | `${number}%`;
boxSizing?: 'border-box' | 'content-box';
direction?: 'ltr' | 'rtl';
display?: 'none' | 'flex';
display?: 'none' | 'flex' | 'contents';
end?: number | `${number}%`;
flex?: number;
flexBasis?: number | 'auto' | `${number}%`;
@@ -360,12 +360,14 @@ function direction(str?: 'ltr' | 'rtl'): Direction {
throw new Error(`"${str}" is not a valid value for direction`);
}
function display(str?: 'none' | 'flex'): Display {
function display(str?: 'none' | 'flex' | 'contents'): Display {
switch (str) {
case 'none':
return Display.None;
case 'flex':
return Display.Flex;
case 'contents':
return Display.Contents;
}
throw new Error(`"${str}" is not a valid value for display`);
}

View File

@@ -16,6 +16,7 @@ export type LayoutMetrics = {
width: number;
height: number;
overflow?: 'visible' | 'hidden' | 'scroll';
display?: 'flex' | 'none' | 'contents';
children?: LayoutMetrics[];
};
@@ -49,7 +50,11 @@ export default function LayoutBox({metrics, depth, className}: Props) {
position: depth === 0 ? 'relative' : 'absolute',
}}>
{children?.map((child, i) => (
<LayoutBox key={i} metrics={child} depth={depth + 1} />
<LayoutBox
key={i}
metrics={child}
depth={style.display === 'contents' ? depth : depth + 1}
/>
))}
</div>
);

View File

@@ -8,7 +8,12 @@
*/
import {useMemo} from 'react';
import Yoga, {Direction, Overflow, Node as YogaNode} from 'yoga-layout';
import Yoga, {
Direction,
Display,
Overflow,
Node as YogaNode,
} from 'yoga-layout';
import {FlexStyle, applyStyle} from './FlexStyle';
import LayoutBox from './LayoutBox';
@@ -109,6 +114,16 @@ function metricsFromYogaNode(node: YogaNode): LayoutMetrics {
return 'visible';
}
})(),
display: (() => {
switch (node.getDisplay()) {
case Display.Flex:
return 'flex';
case Display.None:
return 'none';
case Display.Contents:
return 'contents';
}
})(),
children,
};
}

475
yarn.lock

File diff suppressed because it is too large Load Diff

View File

@@ -90,3 +90,11 @@ float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) {
return getResolvedLayoutProperty<&LayoutResults::padding>(
node, scopedEnum(edge));
}
float YGNodeLayoutGetRawHeight(YGNodeConstRef node) {
return resolveRef(node)->getLayout().rawDimension(Dimension::Height);
}
float YGNodeLayoutGetRawWidth(YGNodeConstRef node) {
return resolveRef(node)->getLayout().rawDimension(Dimension::Width);
}

View File

@@ -32,4 +32,14 @@ YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge);
YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge);
YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge);
/**
* Return the measured height of the node, before layout rounding
*/
YG_EXPORT float YGNodeLayoutGetRawHeight(YGNodeConstRef node);
/**
* Return the measured width of the node, before layout rounding
*/
YG_EXPORT float YGNodeLayoutGetRawWidth(YGNodeConstRef node);
YG_EXTERN_C_END

View File

@@ -293,13 +293,8 @@ void YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float percent) {
node, scopedEnum(gutter), StyleLength::percent(percent));
}
float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) {
auto gapLength = resolveRef(node)->style().gap(scopedEnum(gutter));
if (gapLength.isUndefined() || gapLength.isAuto()) {
return YGUndefined;
}
return static_cast<YGValue>(gapLength).value;
YGValue YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) {
return (YGValue)resolveRef(node)->style().gap(scopedEnum(gutter));
}
void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) {

View File

@@ -96,7 +96,7 @@ YG_EXPORT void
YGNodeStyleSetGap(YGNodeRef node, YGGutter gutter, float gapLength);
YG_EXPORT void
YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float gapLength);
YG_EXPORT float YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter);
YG_EXPORT YGValue YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter);
YG_EXPORT void YGNodeStyleSetBoxSizing(YGNodeRef node, YGBoxSizing boxSizing);
YG_EXPORT YGBoxSizing YGNodeStyleGetBoxSizing(YGNodeConstRef node);

View File

@@ -72,9 +72,9 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
case YGUnitPoint:
case YGUnitPercent:
return lhs.value == rhs.value;
default:
return false;
}
return false;
}
inline bool operator!=(const YGValue& lhs, const YGValue& rhs) {

View File

@@ -11,11 +11,11 @@
* `#include <yoga/Yoga.h>` includes all of Yoga's public headers.
*/
#include <yoga/YGConfig.h>
#include <yoga/YGEnums.h>
#include <yoga/YGMacros.h>
#include <yoga/YGNode.h>
#include <yoga/YGNodeLayout.h>
#include <yoga/YGNodeStyle.h>
#include <yoga/YGPixelGrid.h>
#include <yoga/YGValue.h>
#include <yoga/YGConfig.h> // IWYU pragma: export
#include <yoga/YGEnums.h> // IWYU pragma: export
#include <yoga/YGMacros.h> // IWYU pragma: export
#include <yoga/YGNode.h> // IWYU pragma: export
#include <yoga/YGNodeLayout.h> // IWYU pragma: export
#include <yoga/YGNodeStyle.h> // IWYU pragma: export
#include <yoga/YGPixelGrid.h> // IWYU pragma: export
#include <yoga/YGValue.h> // IWYU pragma: export

View File

@@ -415,6 +415,12 @@ static void measureNodeWithoutChildren(
Dimension::Height);
}
inline bool isFixedSize(float dim, SizingMode sizingMode) {
return sizingMode == SizingMode::StretchFit ||
(yoga::isDefined(dim) && sizingMode == SizingMode::FitContent &&
dim <= 0.0);
}
static bool measureNodeWithFixedSize(
yoga::Node* const node,
const Direction direction,
@@ -424,12 +430,8 @@ static bool measureNodeWithFixedSize(
const SizingMode heightSizingMode,
const float ownerWidth,
const float ownerHeight) {
if ((yoga::isDefined(availableWidth) &&
widthSizingMode == SizingMode::FitContent && availableWidth <= 0.0f) ||
(yoga::isDefined(availableHeight) &&
heightSizingMode == SizingMode::FitContent && availableHeight <= 0.0f) ||
(widthSizingMode == SizingMode::StretchFit &&
heightSizingMode == SizingMode::StretchFit)) {
if (isFixedSize(availableWidth, widthSizingMode) &&
isFixedSize(availableHeight, heightSizingMode)) {
node->setLayoutMeasuredDimension(
boundAxis(
node,
@@ -476,16 +478,19 @@ static void zeroOutLayoutRecursively(yoga::Node* const node) {
}
static void cleanupContentsNodesRecursively(yoga::Node* const node) {
for (auto child : node->getChildren()) {
if (child->style().display() == Display::Contents) {
child->getLayout() = {};
child->setLayoutDimension(0, Dimension::Width);
child->setLayoutDimension(0, Dimension::Height);
child->setHasNewLayout(true);
child->setDirty(false);
child->cloneChildrenIfNeeded();
if (node->hasContentsChildren()) [[unlikely]] {
node->cloneContentsChildrenIfNeeded();
for (auto child : node->getChildren()) {
if (child->style().display() == Display::Contents) {
child->getLayout() = {};
child->setLayoutDimension(0, Dimension::Width);
child->setLayoutDimension(0, Dimension::Height);
child->setHasNewLayout(true);
child->setDirty(false);
child->cloneChildrenIfNeeded();
cleanupContentsNodesRecursively(child);
cleanupContentsNodesRecursively(child);
}
}
}
}
@@ -1213,10 +1218,10 @@ static void calculateLayoutImpl(
const float ownerWidth,
const float ownerHeight,
const bool performLayout,
const LayoutPassReason reason,
LayoutData& layoutMarkerData,
const uint32_t depth,
const uint32_t generationCount,
const LayoutPassReason reason) {
const uint32_t generationCount) {
yoga::assertFatalWithNode(
node,
yoga::isUndefined(availableWidth)
@@ -1780,7 +1785,7 @@ static void calculateLayoutImpl(
crossAxis,
direction,
unclampedCrossDim,
ownerHeight,
crossAxisOwnerSize,
ownerWidth) -
paddingAndBorderAxisCross;
@@ -2268,10 +2273,10 @@ bool calculateLayoutInternal(
ownerWidth,
ownerHeight,
performLayout,
reason,
layoutMarkerData,
depth,
generationCount,
reason);
generationCount);
layout->lastOwnerDirection = ownerDirection;
layout->configVersion = node->getConfig()->getVersion();

View File

@@ -17,7 +17,7 @@ FlexLine calculateFlexLine(
yoga::Node* const node,
const Direction ownerDirection,
const float ownerWidth,
const float mainAxisownerSize,
const float mainAxisOwnerSize,
const float availableInnerWidth,
const float availableInnerMainDim,
Node::LayoutableChildren::Iterator& iterator,
@@ -70,7 +70,7 @@ FlexLine calculateFlexLine(
direction,
mainAxis,
child->getLayout().computedFlexBasis,
mainAxisownerSize,
mainAxisOwnerSize,
ownerWidth)
.unwrap();

View File

@@ -66,7 +66,7 @@ FlexLine calculateFlexLine(
yoga::Node* node,
Direction ownerDirection,
float ownerWidth,
float mainAxisownerSize,
float mainAxisOwnerSize,
float availableInnerWidth,
float availableInnerMainDim,
Node::LayoutableChildren::Iterator& iterator,

View File

@@ -66,7 +66,8 @@ void roundLayoutResultsToPixelGrid(
yoga::Node* const node,
const double absoluteLeft,
const double absoluteTop) {
const auto pointScaleFactor = node->getConfig()->getPointScaleFactor();
const auto pointScaleFactor =
static_cast<double>(node->getConfig()->getPointScaleFactor());
const double nodeLeft = node->getLayout().position(PhysicalEdge::Left);
const double nodeTop = node->getLayout().position(PhysicalEdge::Top);
@@ -80,7 +81,7 @@ void roundLayoutResultsToPixelGrid(
const double absoluteNodeRight = absoluteNodeLeft + nodeWidth;
const double absoluteNodeBottom = absoluteNodeTop + nodeHeight;
if (pointScaleFactor != 0.0f) {
if (pointScaleFactor != 0.0) {
// If a node has a custom measure function we never want to round down its
// size as this could lead to unwanted text truncation.
const bool textRounding = node->getNodeType() == NodeType::Text;
@@ -96,32 +97,34 @@ void roundLayoutResultsToPixelGrid(
// We multiply dimension by scale factor and if the result is close to the
// whole number, we don't have any fraction To verify if the result is close
// to whole number we want to check both floor and ceil numbers
const bool hasFractionalWidth =
!yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 0) &&
!yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 1.0);
const bool hasFractionalHeight =
!yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 0) &&
!yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 1.0);
node->setLayoutDimension(
const double scaledNodeWith = nodeWidth * pointScaleFactor;
const bool hasFractionalWidth =
!yoga::inexactEquals(round(scaledNodeWith), scaledNodeWith);
const double scaledNodeHeight = nodeHeight * pointScaleFactor;
const bool hasFractionalHeight =
!yoga::inexactEquals(round(scaledNodeHeight), scaledNodeHeight);
node->getLayout().setDimension(
Dimension::Width,
roundValueToPixelGrid(
absoluteNodeRight,
pointScaleFactor,
(textRounding && hasFractionalWidth),
(textRounding && !hasFractionalWidth)) -
roundValueToPixelGrid(
absoluteNodeLeft, pointScaleFactor, false, textRounding),
Dimension::Width);
absoluteNodeLeft, pointScaleFactor, false, textRounding));
node->setLayoutDimension(
node->getLayout().setDimension(
Dimension::Height,
roundValueToPixelGrid(
absoluteNodeBottom,
pointScaleFactor,
(textRounding && hasFractionalHeight),
(textRounding && !hasFractionalHeight)) -
roundValueToPixelGrid(
absoluteNodeTop, pointScaleFactor, false, textRounding),
Dimension::Height);
absoluteNodeTop, pointScaleFactor, false, textRounding));
}
for (yoga::Node* child : node->getChildren()) {

View File

@@ -19,6 +19,7 @@ namespace facebook::yoga {
#if defined(__cpp_exceptions)
throw std::logic_error(message);
#else
static_cast<void>(message); // Unused
std::terminate();
#endif
}

View File

@@ -36,12 +36,12 @@ enum struct LayoutPassReason : int {
};
struct LayoutData {
int layouts;
int measures;
uint32_t maxMeasureCache;
int cachedLayouts;
int cachedMeasures;
int measureCallbacks;
int layouts = 0;
int measures = 0;
uint32_t maxMeasureCache = 0;
int cachedLayouts = 0;
int cachedMeasures = 0;
int measureCallbacks = 0;
std::array<int, static_cast<uint8_t>(LayoutPassReason::COUNT)>
measureCallbackReasonsCount;
};

View File

@@ -66,10 +66,18 @@ struct LayoutResults {
return measuredDimensions_[yoga::to_underlying(axis)];
}
float rawDimension(Dimension axis) const {
return rawDimensions_[yoga::to_underlying(axis)];
}
void setMeasuredDimension(Dimension axis, float dimension) {
measuredDimensions_[yoga::to_underlying(axis)] = dimension;
}
void setRawDimension(Dimension axis, float dimension) {
rawDimensions_[yoga::to_underlying(axis)] = dimension;
}
float position(PhysicalEdge physicalEdge) const {
return position_[yoga::to_underlying(physicalEdge)];
}
@@ -113,6 +121,7 @@ struct LayoutResults {
std::array<float, 2> dimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 2> measuredDimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 2> rawDimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 4> position_ = {};
std::array<float, 4> margin_ = {};
std::array<float, 4> border_ = {};

View File

@@ -181,6 +181,17 @@ void Node::setDirty(bool isDirty) {
}
}
void Node::setChildren(const std::vector<Node*>& children) {
children_ = children;
contentsChildrenCount_ = 0;
for (const auto& child : children) {
if (child->style().display() == Display::Contents) {
contentsChildrenCount_++;
}
}
}
bool Node::removeChild(Node* child) {
auto p = std::find(children_.begin(), children_.end(), child);
if (p != children_.end()) {
@@ -245,8 +256,9 @@ void Node::setLayoutHadOverflow(bool hadOverflow) {
layout_.setHadOverflow(hadOverflow);
}
void Node::setLayoutDimension(float LengthValue, Dimension dimension) {
layout_.setDimension(dimension, LengthValue);
void Node::setLayoutDimension(float lengthValue, Dimension dimension) {
layout_.setDimension(dimension, lengthValue);
layout_.setRawDimension(dimension, lengthValue);
}
// If both left and right are defined, then use left. Otherwise return +left or
@@ -379,6 +391,23 @@ void Node::cloneChildrenIfNeeded() {
if (child->getOwner() != this) {
child = resolveRef(config_->cloneNode(child, this, i));
child->setOwner(this);
if (child->hasContentsChildren()) [[unlikely]] {
child->cloneContentsChildrenIfNeeded();
}
}
i += 1;
}
}
void Node::cloneContentsChildrenIfNeeded() {
size_t i = 0;
for (Node*& child : children_) {
if (child->style().display() == Display::Contents &&
child->getOwner() != this) {
child = resolveRef(config_->cloneNode(child, this, i));
child->setOwner(this);
child->cloneChildrenIfNeeded();
}
i += 1;
}

View File

@@ -96,6 +96,10 @@ class YG_EXPORT Node : public ::YGNode {
return config_->hasErrata(errata);
}
bool hasContentsChildren() const {
return contentsChildrenCount_ != 0;
}
YGDirtiedFunc getDirtiedFunc() const {
return dirtiedFunc_;
}
@@ -244,22 +248,19 @@ class YG_EXPORT Node : public ::YGNode {
owner_ = owner;
}
void setChildren(const std::vector<Node*>& children) {
children_ = children;
}
// TODO: rvalue override for setChildren
void setConfig(Config* config);
void setDirty(bool isDirty);
void setChildren(const std::vector<Node*>& children);
void setLayoutLastOwnerDirection(Direction direction);
void setLayoutComputedFlexBasis(FloatOptional computedFlexBasis);
void setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration);
void setLayoutMeasuredDimension(float measuredDimension, Dimension dimension);
void setLayoutHadOverflow(bool hadOverflow);
void setLayoutDimension(float LengthValue, Dimension dimension);
void setLayoutDimension(float lengthValue, Dimension dimension);
void setLayoutDirection(Direction direction);
void setLayoutMargin(float margin, PhysicalEdge edge);
void setLayoutBorder(float border, PhysicalEdge edge);
@@ -286,6 +287,7 @@ class YG_EXPORT Node : public ::YGNode {
void removeChild(size_t index);
void cloneChildrenIfNeeded();
void cloneContentsChildrenIfNeeded();
void markDirtyAndPropagate();
float resolveFlexGrow() const;
float resolveFlexShrink() const;