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,
|
float marginColumn,
|
||||||
YGConfigRef config) {
|
YGConfigRef config) {
|
||||||
return yoga::canUseCachedMeasurement(
|
return yoga::canUseCachedMeasurement(
|
||||||
scopedEnum(widthMode),
|
sizingMode(scopedEnum(widthMode)),
|
||||||
availableWidth,
|
availableWidth,
|
||||||
scopedEnum(heightMode),
|
sizingMode(scopedEnum(heightMode)),
|
||||||
availableHeight,
|
availableHeight,
|
||||||
scopedEnum(lastWidthMode),
|
sizingMode(scopedEnum(lastWidthMode)),
|
||||||
lastAvailableWidth,
|
lastAvailableWidth,
|
||||||
scopedEnum(lastHeightMode),
|
sizingMode(scopedEnum(lastHeightMode)),
|
||||||
lastAvailableHeight,
|
lastAvailableHeight,
|
||||||
lastComputedWidth,
|
lastComputedWidth,
|
||||||
lastComputedHeight,
|
lastComputedHeight,
|
||||||
|
@@ -186,6 +186,19 @@ typedef struct YGSize {
|
|||||||
} 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.
|
* @returns the size of the leaf node, measured under the given contraints.
|
||||||
*/
|
*/
|
||||||
typedef YGSize (*YGMeasureFunc)(
|
typedef YGSize (*YGMeasureFunc)(
|
||||||
|
@@ -12,51 +12,52 @@
|
|||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
static inline bool sizeIsExactAndMatchesOldMeasuredSize(
|
static inline bool sizeIsExactAndMatchesOldMeasuredSize(
|
||||||
MeasureMode sizeMode,
|
SizingMode sizeMode,
|
||||||
float size,
|
float size,
|
||||||
float lastComputedSize) {
|
float lastComputedSize) {
|
||||||
return sizeMode == MeasureMode::Exactly &&
|
return sizeMode == SizingMode::StretchFit &&
|
||||||
yoga::inexactEquals(size, lastComputedSize);
|
yoga::inexactEquals(size, lastComputedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool oldSizeIsUnspecifiedAndStillFits(
|
static inline bool oldSizeIsMaxContentAndStillFits(
|
||||||
MeasureMode sizeMode,
|
SizingMode sizeMode,
|
||||||
float size,
|
float size,
|
||||||
MeasureMode lastSizeMode,
|
SizingMode lastSizeMode,
|
||||||
float lastComputedSize) {
|
float lastComputedSize) {
|
||||||
return sizeMode == MeasureMode::AtMost &&
|
return sizeMode == SizingMode::FitContent &&
|
||||||
lastSizeMode == MeasureMode::Undefined &&
|
lastSizeMode == SizingMode::MaxContent &&
|
||||||
(size >= lastComputedSize || yoga::inexactEquals(size, lastComputedSize));
|
(size >= lastComputedSize || yoga::inexactEquals(size, lastComputedSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool newMeasureSizeIsStricterAndStillValid(
|
static inline bool newSizeIsStricterAndStillValid(
|
||||||
MeasureMode sizeMode,
|
SizingMode sizeMode,
|
||||||
float size,
|
float size,
|
||||||
MeasureMode lastSizeMode,
|
SizingMode lastSizeMode,
|
||||||
float lastSize,
|
float lastSize,
|
||||||
float lastComputedSize) {
|
float lastComputedSize) {
|
||||||
return lastSizeMode == MeasureMode::AtMost &&
|
return lastSizeMode == SizingMode::FitContent &&
|
||||||
sizeMode == MeasureMode::AtMost && !std::isnan(lastSize) &&
|
sizeMode == SizingMode::FitContent && yoga::isDefined(lastSize) &&
|
||||||
!std::isnan(size) && !std::isnan(lastComputedSize) && lastSize > size &&
|
yoga::isDefined(size) && yoga::isDefined(lastComputedSize) &&
|
||||||
|
lastSize > size &&
|
||||||
(lastComputedSize <= size || yoga::inexactEquals(size, lastComputedSize));
|
(lastComputedSize <= size || yoga::inexactEquals(size, lastComputedSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canUseCachedMeasurement(
|
bool canUseCachedMeasurement(
|
||||||
const MeasureMode widthMode,
|
const SizingMode widthMode,
|
||||||
const float availableWidth,
|
const float availableWidth,
|
||||||
const MeasureMode heightMode,
|
const SizingMode heightMode,
|
||||||
const float availableHeight,
|
const float availableHeight,
|
||||||
const MeasureMode lastWidthMode,
|
const SizingMode lastWidthMode,
|
||||||
const float lastAvailableWidth,
|
const float lastAvailableWidth,
|
||||||
const MeasureMode lastHeightMode,
|
const SizingMode lastHeightMode,
|
||||||
const float lastAvailableHeight,
|
const float lastAvailableHeight,
|
||||||
const float lastComputedWidth,
|
const float lastComputedWidth,
|
||||||
const float lastComputedHeight,
|
const float lastComputedHeight,
|
||||||
const float marginRow,
|
const float marginRow,
|
||||||
const float marginColumn,
|
const float marginColumn,
|
||||||
const yoga::Config* const config) {
|
const yoga::Config* const config) {
|
||||||
if ((!std::isnan(lastComputedHeight) && lastComputedHeight < 0) ||
|
if ((yoga::isDefined(lastComputedHeight) && lastComputedHeight < 0) ||
|
||||||
(!std::isnan(lastComputedWidth) && lastComputedWidth < 0)) {
|
((yoga::isDefined(lastComputedWidth)) && lastComputedWidth < 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,33 +88,32 @@ bool canUseCachedMeasurement(
|
|||||||
hasSameWidthSpec ||
|
hasSameWidthSpec ||
|
||||||
sizeIsExactAndMatchesOldMeasuredSize(
|
sizeIsExactAndMatchesOldMeasuredSize(
|
||||||
widthMode, availableWidth - marginRow, lastComputedWidth) ||
|
widthMode, availableWidth - marginRow, lastComputedWidth) ||
|
||||||
oldSizeIsUnspecifiedAndStillFits(
|
oldSizeIsMaxContentAndStillFits(
|
||||||
widthMode,
|
widthMode,
|
||||||
availableWidth - marginRow,
|
availableWidth - marginRow,
|
||||||
lastWidthMode,
|
lastWidthMode,
|
||||||
lastComputedWidth) ||
|
lastComputedWidth) ||
|
||||||
newMeasureSizeIsStricterAndStillValid(
|
newSizeIsStricterAndStillValid(
|
||||||
widthMode,
|
widthMode,
|
||||||
availableWidth - marginRow,
|
availableWidth - marginRow,
|
||||||
lastWidthMode,
|
lastWidthMode,
|
||||||
lastAvailableWidth,
|
lastAvailableWidth,
|
||||||
lastComputedWidth);
|
lastComputedWidth);
|
||||||
|
|
||||||
const bool heightIsCompatible =
|
const bool heightIsCompatible = hasSameHeightSpec ||
|
||||||
hasSameHeightSpec ||
|
|
||||||
sizeIsExactAndMatchesOldMeasuredSize(
|
sizeIsExactAndMatchesOldMeasuredSize(
|
||||||
heightMode, availableHeight - marginColumn, lastComputedHeight) ||
|
heightMode,
|
||||||
oldSizeIsUnspecifiedAndStillFits(
|
availableHeight - marginColumn,
|
||||||
heightMode,
|
lastComputedHeight) ||
|
||||||
availableHeight - marginColumn,
|
oldSizeIsMaxContentAndStillFits(heightMode,
|
||||||
lastHeightMode,
|
availableHeight - marginColumn,
|
||||||
lastComputedHeight) ||
|
lastHeightMode,
|
||||||
newMeasureSizeIsStricterAndStillValid(
|
lastComputedHeight) ||
|
||||||
heightMode,
|
newSizeIsStricterAndStillValid(heightMode,
|
||||||
availableHeight - marginColumn,
|
availableHeight - marginColumn,
|
||||||
lastHeightMode,
|
lastHeightMode,
|
||||||
lastAvailableHeight,
|
lastAvailableHeight,
|
||||||
lastComputedHeight);
|
lastComputedHeight);
|
||||||
|
|
||||||
return widthIsCompatible && heightIsCompatible;
|
return widthIsCompatible && heightIsCompatible;
|
||||||
}
|
}
|
||||||
|
@@ -7,19 +7,19 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <yoga/algorithm/SizingMode.h>
|
||||||
#include <yoga/config/Config.h>
|
#include <yoga/config/Config.h>
|
||||||
#include <yoga/enums/MeasureMode.h>
|
|
||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
bool canUseCachedMeasurement(
|
bool canUseCachedMeasurement(
|
||||||
MeasureMode widthMode,
|
SizingMode widthMode,
|
||||||
float availableWidth,
|
float availableWidth,
|
||||||
MeasureMode heightMode,
|
SizingMode heightMode,
|
||||||
float availableHeight,
|
float availableHeight,
|
||||||
MeasureMode lastWidthMode,
|
SizingMode lastWidthMode,
|
||||||
float lastAvailableWidth,
|
float lastAvailableWidth,
|
||||||
MeasureMode lastHeightMode,
|
SizingMode lastHeightMode,
|
||||||
float lastAvailableHeight,
|
float lastAvailableHeight,
|
||||||
float lastComputedWidth,
|
float lastComputedWidth,
|
||||||
float lastComputedHeight,
|
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 <stdexcept>
|
||||||
|
|
||||||
|
#include <yoga/config/Config.h>
|
||||||
#include <yoga/debug/AssertFatal.h>
|
#include <yoga/debug/AssertFatal.h>
|
||||||
#include <yoga/debug/Log.h>
|
#include <yoga/debug/Log.h>
|
||||||
|
#include <yoga/node/Node.h>
|
||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
|
@@ -8,11 +8,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <yoga/Yoga.h>
|
#include <yoga/Yoga.h>
|
||||||
#include <yoga/config/Config.h>
|
|
||||||
#include <yoga/node/Node.h>
|
|
||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
class Config;
|
||||||
|
|
||||||
[[noreturn]] void fatalWithMessage(const char* message);
|
[[noreturn]] void fatalWithMessage(const char* message);
|
||||||
|
|
||||||
void assertFatal(bool condition, const char* message);
|
void assertFatal(bool condition, const char* message);
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <yoga/Yoga.h>
|
#include <yoga/Yoga.h>
|
||||||
|
|
||||||
#include <yoga/enums/MeasureMode.h>
|
#include <yoga/algorithm/SizingMode.h>
|
||||||
#include <yoga/numeric/Comparison.h>
|
#include <yoga/numeric/Comparison.h>
|
||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
@@ -19,15 +19,15 @@ namespace facebook::yoga {
|
|||||||
struct CachedMeasurement {
|
struct CachedMeasurement {
|
||||||
float availableWidth{-1};
|
float availableWidth{-1};
|
||||||
float availableHeight{-1};
|
float availableHeight{-1};
|
||||||
MeasureMode widthMeasureMode{MeasureMode::Undefined};
|
SizingMode widthSizingMode{SizingMode::MaxContent};
|
||||||
MeasureMode heightMeasureMode{MeasureMode::Undefined};
|
SizingMode heightSizingMode{SizingMode::MaxContent};
|
||||||
|
|
||||||
float computedWidth{-1};
|
float computedWidth{-1};
|
||||||
float computedHeight{-1};
|
float computedHeight{-1};
|
||||||
|
|
||||||
bool operator==(CachedMeasurement measurement) const {
|
bool operator==(CachedMeasurement measurement) const {
|
||||||
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
|
bool isEqual = widthSizingMode == measurement.widthSizingMode &&
|
||||||
heightMeasureMode == measurement.heightMeasureMode;
|
heightSizingMode == measurement.heightSizingMode;
|
||||||
|
|
||||||
if (!yoga::isUndefined(availableWidth) ||
|
if (!yoga::isUndefined(availableWidth) ||
|
||||||
!yoga::isUndefined(measurement.availableWidth)) {
|
!yoga::isUndefined(measurement.availableWidth)) {
|
||||||
|
Reference in New Issue
Block a user