Use CSS terminology for sizing rules (#1460)
Summary: X-link: https://github.com/facebook/react-native/pull/41390 Pull Request resolved: https://github.com/facebook/yoga/pull/1460 Yoga passes `MeasureMode`/`YGMeasureMode` to express constraints in how a box should be measured, given definite or indefinite available space. This is modeled after Android [MeasureSpec](https://developer.android.com/reference/android/view/View.MeasureSpec), with a table above `calculateLayoutImpl()` explaining the CSS terms they map to. This can be confusing when flipping between the spec, and code. This switches internal usages to the CSS terms, but leaves around `YGMeasureMode` since it is the public API passed to measure functions. Reviewed By: joevilches Differential Revision: D51068417 fbshipit-source-id: 0a76266a4e7e0cc39996164607229c3c41de2818
This commit is contained in:
committed by
Facebook GitHub Bot
parent
aca02406ef
commit
a121483e81
@@ -351,13 +351,13 @@ bool YGNodeCanUseCachedMeasurement(
|
||||
float marginColumn,
|
||||
YGConfigRef config) {
|
||||
return yoga::canUseCachedMeasurement(
|
||||
scopedEnum(widthMode),
|
||||
sizingMode(scopedEnum(widthMode)),
|
||||
availableWidth,
|
||||
scopedEnum(heightMode),
|
||||
sizingMode(scopedEnum(heightMode)),
|
||||
availableHeight,
|
||||
scopedEnum(lastWidthMode),
|
||||
sizingMode(scopedEnum(lastWidthMode)),
|
||||
lastAvailableWidth,
|
||||
scopedEnum(lastHeightMode),
|
||||
sizingMode(scopedEnum(lastHeightMode)),
|
||||
lastAvailableHeight,
|
||||
lastComputedWidth,
|
||||
lastComputedHeight,
|
||||
|
@@ -186,6 +186,19 @@ typedef struct YGSize {
|
||||
} YGSize;
|
||||
|
||||
/**
|
||||
* Returns the computed dimensions of the node, following the contraints of
|
||||
* `widthMode` and `heightMode`:
|
||||
*
|
||||
* YGMeasureModeUndefined: The parent has not imposed any constraint on the
|
||||
* child. It can be whatever size it wants.
|
||||
*
|
||||
* YGMeasureModeAtMost: The child can be as large as it wants up to the
|
||||
* specified size.
|
||||
*
|
||||
* YGMeasureModeExactly: The parent has determined an exact size for the
|
||||
* child. The child is going to be given those bounds regardless of how big it
|
||||
* wants to be.
|
||||
*
|
||||
* @returns the size of the leaf node, measured under the given contraints.
|
||||
*/
|
||||
typedef YGSize (*YGMeasureFunc)(
|
||||
|
@@ -12,51 +12,52 @@
|
||||
namespace facebook::yoga {
|
||||
|
||||
static inline bool sizeIsExactAndMatchesOldMeasuredSize(
|
||||
MeasureMode sizeMode,
|
||||
SizingMode sizeMode,
|
||||
float size,
|
||||
float lastComputedSize) {
|
||||
return sizeMode == MeasureMode::Exactly &&
|
||||
return sizeMode == SizingMode::StretchFit &&
|
||||
yoga::inexactEquals(size, lastComputedSize);
|
||||
}
|
||||
|
||||
static inline bool oldSizeIsUnspecifiedAndStillFits(
|
||||
MeasureMode sizeMode,
|
||||
static inline bool oldSizeIsMaxContentAndStillFits(
|
||||
SizingMode sizeMode,
|
||||
float size,
|
||||
MeasureMode lastSizeMode,
|
||||
SizingMode lastSizeMode,
|
||||
float lastComputedSize) {
|
||||
return sizeMode == MeasureMode::AtMost &&
|
||||
lastSizeMode == MeasureMode::Undefined &&
|
||||
return sizeMode == SizingMode::FitContent &&
|
||||
lastSizeMode == SizingMode::MaxContent &&
|
||||
(size >= lastComputedSize || yoga::inexactEquals(size, lastComputedSize));
|
||||
}
|
||||
|
||||
static inline bool newMeasureSizeIsStricterAndStillValid(
|
||||
MeasureMode sizeMode,
|
||||
static inline bool newSizeIsStricterAndStillValid(
|
||||
SizingMode sizeMode,
|
||||
float size,
|
||||
MeasureMode lastSizeMode,
|
||||
SizingMode lastSizeMode,
|
||||
float lastSize,
|
||||
float lastComputedSize) {
|
||||
return lastSizeMode == MeasureMode::AtMost &&
|
||||
sizeMode == MeasureMode::AtMost && !std::isnan(lastSize) &&
|
||||
!std::isnan(size) && !std::isnan(lastComputedSize) && lastSize > size &&
|
||||
return lastSizeMode == SizingMode::FitContent &&
|
||||
sizeMode == SizingMode::FitContent && yoga::isDefined(lastSize) &&
|
||||
yoga::isDefined(size) && yoga::isDefined(lastComputedSize) &&
|
||||
lastSize > size &&
|
||||
(lastComputedSize <= size || yoga::inexactEquals(size, lastComputedSize));
|
||||
}
|
||||
|
||||
bool canUseCachedMeasurement(
|
||||
const MeasureMode widthMode,
|
||||
const SizingMode widthMode,
|
||||
const float availableWidth,
|
||||
const MeasureMode heightMode,
|
||||
const SizingMode heightMode,
|
||||
const float availableHeight,
|
||||
const MeasureMode lastWidthMode,
|
||||
const SizingMode lastWidthMode,
|
||||
const float lastAvailableWidth,
|
||||
const MeasureMode lastHeightMode,
|
||||
const SizingMode lastHeightMode,
|
||||
const float lastAvailableHeight,
|
||||
const float lastComputedWidth,
|
||||
const float lastComputedHeight,
|
||||
const float marginRow,
|
||||
const float marginColumn,
|
||||
const yoga::Config* const config) {
|
||||
if ((!std::isnan(lastComputedHeight) && lastComputedHeight < 0) ||
|
||||
(!std::isnan(lastComputedWidth) && lastComputedWidth < 0)) {
|
||||
if ((yoga::isDefined(lastComputedHeight) && lastComputedHeight < 0) ||
|
||||
((yoga::isDefined(lastComputedWidth)) && lastComputedWidth < 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -87,29 +88,28 @@ bool canUseCachedMeasurement(
|
||||
hasSameWidthSpec ||
|
||||
sizeIsExactAndMatchesOldMeasuredSize(
|
||||
widthMode, availableWidth - marginRow, lastComputedWidth) ||
|
||||
oldSizeIsUnspecifiedAndStillFits(
|
||||
oldSizeIsMaxContentAndStillFits(
|
||||
widthMode,
|
||||
availableWidth - marginRow,
|
||||
lastWidthMode,
|
||||
lastComputedWidth) ||
|
||||
newMeasureSizeIsStricterAndStillValid(
|
||||
newSizeIsStricterAndStillValid(
|
||||
widthMode,
|
||||
availableWidth - marginRow,
|
||||
lastWidthMode,
|
||||
lastAvailableWidth,
|
||||
lastComputedWidth);
|
||||
|
||||
const bool heightIsCompatible =
|
||||
hasSameHeightSpec ||
|
||||
const bool heightIsCompatible = hasSameHeightSpec ||
|
||||
sizeIsExactAndMatchesOldMeasuredSize(
|
||||
heightMode, availableHeight - marginColumn, lastComputedHeight) ||
|
||||
oldSizeIsUnspecifiedAndStillFits(
|
||||
heightMode,
|
||||
availableHeight - marginColumn,
|
||||
lastComputedHeight) ||
|
||||
oldSizeIsMaxContentAndStillFits(heightMode,
|
||||
availableHeight - marginColumn,
|
||||
lastHeightMode,
|
||||
lastComputedHeight) ||
|
||||
newMeasureSizeIsStricterAndStillValid(
|
||||
heightMode,
|
||||
newSizeIsStricterAndStillValid(heightMode,
|
||||
availableHeight - marginColumn,
|
||||
lastHeightMode,
|
||||
lastAvailableHeight,
|
||||
|
@@ -7,19 +7,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <yoga/algorithm/SizingMode.h>
|
||||
#include <yoga/config/Config.h>
|
||||
#include <yoga/enums/MeasureMode.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
bool canUseCachedMeasurement(
|
||||
MeasureMode widthMode,
|
||||
SizingMode widthMode,
|
||||
float availableWidth,
|
||||
MeasureMode heightMode,
|
||||
SizingMode heightMode,
|
||||
float availableHeight,
|
||||
MeasureMode lastWidthMode,
|
||||
SizingMode lastWidthMode,
|
||||
float lastAvailableWidth,
|
||||
MeasureMode lastHeightMode,
|
||||
SizingMode lastHeightMode,
|
||||
float lastAvailableHeight,
|
||||
float lastComputedWidth,
|
||||
float lastComputedHeight,
|
||||
|
File diff suppressed because it is too large
Load Diff
73
yoga/algorithm/SizingMode.h
Normal file
73
yoga/algorithm/SizingMode.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <yoga/debug/AssertFatal.h>
|
||||
#include <yoga/enums/MeasureMode.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
/**
|
||||
* Corresponds to a CSS auto box sizes. Missing "min-content", as Yoga does not
|
||||
* current support automatic minimum sizes.
|
||||
* https://www.w3.org/TR/css-sizing-3/#auto-box-sizes
|
||||
* https://www.w3.org/TR/css-flexbox-1/#min-size-auto
|
||||
*/
|
||||
enum class SizingMode {
|
||||
/**
|
||||
* The size a box would take if its outer size filled the available space in
|
||||
* the given axis; in other words, the stretch fit into the available space,
|
||||
* if that is definite. Undefined if the available space is indefinite.
|
||||
*/
|
||||
StretchFit,
|
||||
|
||||
/**
|
||||
* A box’s “ideal” size in a given axis when given infinite available space.
|
||||
* Usually this is the smallest size the box could take in that axis while
|
||||
* still fitting around its contents, i.e. minimizing unfilled space while
|
||||
* avoiding overflow.
|
||||
*/
|
||||
MaxContent,
|
||||
|
||||
/**
|
||||
* If the available space in a given axis is definite, equal to
|
||||
* clamp(min-content size, stretch-fit size, max-content size) (i.e.
|
||||
* max(min-content size, min(max-content size, stretch-fit size))). When
|
||||
* sizing under a min-content constraint, equal to the min-content size.
|
||||
* Otherwise, equal to the max-content size in that axis.
|
||||
*/
|
||||
FitContent,
|
||||
};
|
||||
|
||||
inline MeasureMode measureMode(SizingMode mode) {
|
||||
switch (mode) {
|
||||
case SizingMode::StretchFit:
|
||||
return MeasureMode::Exactly;
|
||||
case SizingMode::MaxContent:
|
||||
return MeasureMode::Undefined;
|
||||
case SizingMode::FitContent:
|
||||
return MeasureMode::AtMost;
|
||||
}
|
||||
|
||||
fatalWithMessage("Invalid SizingMode");
|
||||
}
|
||||
|
||||
inline SizingMode sizingMode(MeasureMode mode) {
|
||||
switch (mode) {
|
||||
case MeasureMode::Exactly:
|
||||
return SizingMode::StretchFit;
|
||||
case MeasureMode::Undefined:
|
||||
return SizingMode::MaxContent;
|
||||
case MeasureMode::AtMost:
|
||||
return SizingMode::FitContent;
|
||||
}
|
||||
|
||||
fatalWithMessage("Invalid MeasureMode");
|
||||
}
|
||||
|
||||
} // namespace facebook::yoga
|
@@ -7,8 +7,10 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <yoga/config/Config.h>
|
||||
#include <yoga/debug/AssertFatal.h>
|
||||
#include <yoga/debug/Log.h>
|
||||
#include <yoga/node/Node.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
|
@@ -8,11 +8,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <yoga/Yoga.h>
|
||||
#include <yoga/config/Config.h>
|
||||
#include <yoga/node/Node.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
class Node;
|
||||
class Config;
|
||||
|
||||
[[noreturn]] void fatalWithMessage(const char* message);
|
||||
|
||||
void assertFatal(bool condition, const char* message);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
#include <yoga/enums/MeasureMode.h>
|
||||
#include <yoga/algorithm/SizingMode.h>
|
||||
#include <yoga/numeric/Comparison.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
@@ -19,15 +19,15 @@ namespace facebook::yoga {
|
||||
struct CachedMeasurement {
|
||||
float availableWidth{-1};
|
||||
float availableHeight{-1};
|
||||
MeasureMode widthMeasureMode{MeasureMode::Undefined};
|
||||
MeasureMode heightMeasureMode{MeasureMode::Undefined};
|
||||
SizingMode widthSizingMode{SizingMode::MaxContent};
|
||||
SizingMode heightSizingMode{SizingMode::MaxContent};
|
||||
|
||||
float computedWidth{-1};
|
||||
float computedHeight{-1};
|
||||
|
||||
bool operator==(CachedMeasurement measurement) const {
|
||||
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
|
||||
heightMeasureMode == measurement.heightMeasureMode;
|
||||
bool isEqual = widthSizingMode == measurement.widthSizingMode &&
|
||||
heightSizingMode == measurement.heightSizingMode;
|
||||
|
||||
if (!yoga::isUndefined(availableWidth) ||
|
||||
!yoga::isUndefined(measurement.availableWidth)) {
|
||||
|
Reference in New Issue
Block a user