Back out "Back out "[yoga][intrinsic sizing] Modify private apis to set, store, and get intrinsic sizing keywords"" #1756

Closed
joevilches wants to merge 1 commits from export-D66662662 into main
17 changed files with 317 additions and 54 deletions
Showing only changes of commit edc236dfc8 - Show all commits

View File

@@ -8,7 +8,15 @@ import os
ENUMS = { ENUMS = {
"Direction": ["Inherit", "LTR", "RTL"], "Direction": ["Inherit", "LTR", "RTL"],
"Unit": ["Undefined", "Point", "Percent", "Auto"], "Unit": [
"Undefined",
"Point",
"Percent",
"Auto",
"MaxContent",
"FitContent",
"Stretch",
],
"FlexDirection": ["Column", "ColumnReverse", "Row", "RowReverse"], "FlexDirection": ["Column", "ColumnReverse", "Row", "RowReverse"],
"Justify": [ "Justify": [
"FlexStart", "FlexStart",

View File

@@ -13,7 +13,10 @@ public enum YogaUnit {
UNDEFINED(0), UNDEFINED(0),
POINT(1), POINT(1),
PERCENT(2), PERCENT(2),
AUTO(3); AUTO(3),
MAX_CONTENT(4),
FIT_CONTENT(5),
STRETCH(6);
private final int mIntValue; private final int mIntValue;
@@ -31,6 +34,9 @@ public enum YogaUnit {
case 1: return POINT; case 1: return POINT;
case 2: return PERCENT; case 2: return PERCENT;
case 3: return AUTO; case 3: return AUTO;
case 4: return MAX_CONTENT;
case 5: return FIT_CONTENT;
case 6: return STRETCH;
default: throw new IllegalArgumentException("Unknown enum value: " + value); default: throw new IllegalArgumentException("Unknown enum value: " + value);
} }
} }

View File

@@ -125,6 +125,9 @@ export enum Unit {
Point = 1, Point = 1,
Percent = 2, Percent = 2,
Auto = 3, Auto = 3,
MaxContent = 4,
FitContent = 5,
Stretch = 6,
} }
export enum Wrap { export enum Wrap {
@@ -203,6 +206,9 @@ const constants = {
UNIT_POINT: Unit.Point, UNIT_POINT: Unit.Point,
UNIT_PERCENT: Unit.Percent, UNIT_PERCENT: Unit.Percent,
UNIT_AUTO: Unit.Auto, UNIT_AUTO: Unit.Auto,
UNIT_MAX_CONTENT: Unit.MaxContent,
UNIT_FIT_CONTENT: Unit.FitContent,
UNIT_STRETCH: Unit.Stretch,
WRAP_NO_WRAP: Wrap.NoWrap, WRAP_NO_WRAP: Wrap.NoWrap,
WRAP_WRAP: Wrap.Wrap, WRAP_WRAP: Wrap.Wrap,
WRAP_WRAP_REVERSE: Wrap.WrapReverse, WRAP_WRAP_REVERSE: Wrap.WrapReverse,

View File

@@ -128,4 +128,19 @@ TEST(StyleValuePool, store_undefined_after_large_int) {
EXPECT_EQ(pool.getLength(handle), StyleLength::undefined()); EXPECT_EQ(pool.getLength(handle), StyleLength::undefined());
} }
TEST(StyleValuePool, store_keywords) {
StyleValuePool pool;
StyleValueHandle handleMaxContent;
StyleValueHandle handleFitContent;
StyleValueHandle handleStretch;
pool.store(handleMaxContent, StyleSizeLength::ofMaxContent());
pool.store(handleFitContent, StyleSizeLength::ofFitContent());
pool.store(handleStretch, StyleSizeLength::ofStretch());
EXPECT_EQ(pool.getSize(handleMaxContent), StyleSizeLength::ofMaxContent());
EXPECT_EQ(pool.getSize(handleFitContent), StyleSizeLength::ofFitContent());
EXPECT_EQ(pool.getSize(handleStretch), StyleSizeLength::ofStretch());
}
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -245,6 +245,12 @@ const char* YGUnitToString(const YGUnit value) {
return "percent"; return "percent";
case YGUnitAuto: case YGUnitAuto:
return "auto"; return "auto";
case YGUnitMaxContent:
return "max-content";
case YGUnitFitContent:
return "fit-content";
case YGUnitStretch:
return "stretch";
} }
return "unknown"; return "unknown";
} }

View File

@@ -131,7 +131,10 @@ YG_ENUM_DECL(
YGUnitUndefined, YGUnitUndefined,
YGUnitPoint, YGUnitPoint,
YGUnitPercent, YGUnitPercent,
YGUnitAuto) YGUnitAuto,
YGUnitMaxContent,
YGUnitFitContent,
YGUnitStretch)
YG_ENUM_DECL( YG_ENUM_DECL(
YGWrap, YGWrap,

View File

@@ -177,19 +177,19 @@ float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) {
void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>( updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::points(flexBasis)); node, StyleSizeLength::points(flexBasis));
} }
void YGNodeStyleSetFlexBasisPercent( void YGNodeStyleSetFlexBasisPercent(
const YGNodeRef node, const YGNodeRef node,
const float flexBasisPercent) { const float flexBasisPercent) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>( updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::percent(flexBasisPercent)); node, StyleSizeLength::percent(flexBasisPercent));
} }
void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>( updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::ofAuto()); node, StyleSizeLength::ofAuto());
} }
YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) {
@@ -308,17 +308,17 @@ YGBoxSizing YGNodeStyleGetBoxSizing(const YGNodeConstRef node) {
void YGNodeStyleSetWidth(YGNodeRef node, float points) { void YGNodeStyleSetWidth(YGNodeRef node, float points) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::points(points)); node, Dimension::Width, StyleSizeLength::points(points));
} }
void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::percent(percent)); node, Dimension::Width, StyleSizeLength::percent(percent));
} }
void YGNodeStyleSetWidthAuto(YGNodeRef node) { void YGNodeStyleSetWidthAuto(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::ofAuto()); node, Dimension::Width, StyleSizeLength::ofAuto());
} }
YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { YGValue YGNodeStyleGetWidth(YGNodeConstRef node) {
@@ -327,17 +327,17 @@ YGValue YGNodeStyleGetWidth(YGNodeConstRef node) {
void YGNodeStyleSetHeight(YGNodeRef node, float points) { void YGNodeStyleSetHeight(YGNodeRef node, float points) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::points(points)); node, Dimension::Height, StyleSizeLength::points(points));
} }
void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::percent(percent)); node, Dimension::Height, StyleSizeLength::percent(percent));
} }
void YGNodeStyleSetHeightAuto(YGNodeRef node) { void YGNodeStyleSetHeightAuto(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>( updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::ofAuto()); node, Dimension::Height, StyleSizeLength::ofAuto());
} }
YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { YGValue YGNodeStyleGetHeight(YGNodeConstRef node) {
@@ -346,12 +346,12 @@ YGValue YGNodeStyleGetHeight(YGNodeConstRef node) {
void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) {
updateStyle<&Style::minDimension, &Style::setMinDimension>( updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleLength::points(minWidth)); node, Dimension::Width, StyleSizeLength::points(minWidth));
} }
void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) {
updateStyle<&Style::minDimension, &Style::setMinDimension>( updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleLength::percent(minWidth)); node, Dimension::Width, StyleSizeLength::percent(minWidth));
} }
YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) {
@@ -360,14 +360,14 @@ YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) {
void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) {
updateStyle<&Style::minDimension, &Style::setMinDimension>( updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleLength::points(minHeight)); node, Dimension::Height, StyleSizeLength::points(minHeight));
} }
void YGNodeStyleSetMinHeightPercent( void YGNodeStyleSetMinHeightPercent(
const YGNodeRef node, const YGNodeRef node,
const float minHeight) { const float minHeight) {
updateStyle<&Style::minDimension, &Style::setMinDimension>( updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleLength::percent(minHeight)); node, Dimension::Height, StyleSizeLength::percent(minHeight));
} }
YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) {
@@ -376,12 +376,12 @@ YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) {
void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>( updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleLength::points(maxWidth)); node, Dimension::Width, StyleSizeLength::points(maxWidth));
} }
void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>( updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleLength::percent(maxWidth)); node, Dimension::Width, StyleSizeLength::percent(maxWidth));
} }
YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) {
@@ -390,14 +390,14 @@ YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) {
void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>( updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleLength::points(maxHeight)); node, Dimension::Height, StyleSizeLength::points(maxHeight));
} }
void YGNodeStyleSetMaxHeightPercent( void YGNodeStyleSetMaxHeightPercent(
const YGNodeRef node, const YGNodeRef node,
const float maxHeight) { const float maxHeight) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>( updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleLength::percent(maxHeight)); node, Dimension::Height, StyleSizeLength::percent(maxHeight));
} }
YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) {

View File

@@ -65,6 +65,9 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
switch (lhs.unit) { switch (lhs.unit) {
case YGUnitUndefined: case YGUnitUndefined:
case YGUnitAuto: case YGUnitAuto:
case YGUnitFitContent:
case YGUnitMaxContent:
case YGUnitStretch:
return true; return true;
case YGUnitPoint: case YGUnitPoint:
case YGUnitPercent: case YGUnitPercent:

View File

@@ -741,7 +741,7 @@ static float distributeFreeSpaceSecondPass(
marginCross; marginCross;
const bool isLoosePercentageMeasurement = const bool isLoosePercentageMeasurement =
currentLineChild->getProcessedDimension(dimension(crossAxis)) currentLineChild->getProcessedDimension(dimension(crossAxis))
.unit() == Unit::Percent && .isPercent() &&
sizingModeCrossDim != SizingMode::StretchFit; sizingModeCrossDim != SizingMode::StretchFit;
childCrossSizingMode = childCrossSizingMode =
yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement

View File

@@ -20,11 +20,14 @@ enum class Unit : uint8_t {
Point = YGUnitPoint, Point = YGUnitPoint,
Percent = YGUnitPercent, Percent = YGUnitPercent,
Auto = YGUnitAuto, Auto = YGUnitAuto,
MaxContent = YGUnitMaxContent,
FitContent = YGUnitFitContent,
Stretch = YGUnitStretch,
}; };
template <> template <>
constexpr int32_t ordinalCount<Unit>() { constexpr int32_t ordinalCount<Unit>() {
return 4; return 7;
} }
constexpr Unit scopedEnum(YGUnit unscoped) { constexpr Unit scopedEnum(YGUnit unscoped) {

View File

@@ -314,16 +314,16 @@ void Node::setPosition(
crossAxisTrailingEdge); crossAxisTrailingEdge);
} }
Style::Length Node::processFlexBasis() const { Style::SizeLength Node::processFlexBasis() const {
Style::Length flexBasis = style_.flexBasis(); Style::SizeLength flexBasis = style_.flexBasis();
if (flexBasis.unit() != Unit::Auto && flexBasis.unit() != Unit::Undefined) { if (!flexBasis.isAuto() && !flexBasis.isUndefined()) {
return flexBasis; return flexBasis;
} }
if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) { if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) {
return config_->useWebDefaults() ? StyleLength::ofAuto() return config_->useWebDefaults() ? StyleSizeLength::ofAuto()
: StyleLength::points(0); : StyleSizeLength::points(0);
} }
return StyleLength::ofAuto(); return StyleSizeLength::ofAuto();
} }
FloatOptional Node::resolveFlexBasis( FloatOptional Node::resolveFlexBasis(

View File

@@ -172,7 +172,7 @@ class YG_EXPORT Node : public ::YGNode {
return isDirty_; return isDirty_;
} }
Style::Length getProcessedDimension(Dimension dimension) const { Style::SizeLength getProcessedDimension(Dimension dimension) const {
return processedDimensions_[static_cast<size_t>(dimension)]; return processedDimensions_[static_cast<size_t>(dimension)];
} }
@@ -268,7 +268,7 @@ class YG_EXPORT Node : public ::YGNode {
void setPosition(Direction direction, float ownerWidth, float ownerHeight); void setPosition(Direction direction, float ownerWidth, float ownerHeight);
// Other methods // Other methods
Style::Length processFlexBasis() const; Style::SizeLength processFlexBasis() const;
FloatOptional resolveFlexBasis( FloatOptional resolveFlexBasis(
Direction direction, Direction direction,
FlexDirection flexDirection, FlexDirection flexDirection,
@@ -322,8 +322,8 @@ class YG_EXPORT Node : public ::YGNode {
Node* owner_ = nullptr; Node* owner_ = nullptr;
std::vector<Node*> children_; std::vector<Node*> children_;
const Config* config_; const Config* config_;
std::array<Style::Length, 2> processedDimensions_{ std::array<Style::SizeLength, 2> processedDimensions_{
{StyleLength::undefined(), StyleLength::undefined()}}; {StyleSizeLength::undefined(), StyleSizeLength::undefined()}};
}; };
inline Node* resolveRef(const YGNodeRef ref) { inline Node* resolveRef(const YGNodeRef ref) {

View File

@@ -30,6 +30,7 @@
#include <yoga/enums/Wrap.h> #include <yoga/enums/Wrap.h>
#include <yoga/numeric/FloatOptional.h> #include <yoga/numeric/FloatOptional.h>
#include <yoga/style/StyleLength.h> #include <yoga/style/StyleLength.h>
#include <yoga/style/StyleSizeLength.h>
#include <yoga/style/StyleValuePool.h> #include <yoga/style/StyleValuePool.h>
namespace facebook::yoga { namespace facebook::yoga {
@@ -37,6 +38,7 @@ namespace facebook::yoga {
class YG_EXPORT Style { class YG_EXPORT Style {
public: public:
using Length = StyleLength; using Length = StyleLength;
using SizeLength = StyleSizeLength;
static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexGrow = 0.0f;
static constexpr float DefaultFlexShrink = 0.0f; static constexpr float DefaultFlexShrink = 0.0f;
@@ -133,10 +135,10 @@ class YG_EXPORT Style {
pool_.store(flexShrink_, value); pool_.store(flexShrink_, value);
} }
Style::Length flexBasis() const { Style::SizeLength flexBasis() const {
return pool_.getLength(flexBasis_); return pool_.getSize(flexBasis_);
} }
void setFlexBasis(Style::Length value) { void setFlexBasis(Style::SizeLength value) {
pool_.store(flexBasis_, value); pool_.store(flexBasis_, value);
} }
@@ -175,17 +177,17 @@ class YG_EXPORT Style {
pool_.store(gap_[yoga::to_underlying(gutter)], value); pool_.store(gap_[yoga::to_underlying(gutter)], value);
} }
Style::Length dimension(Dimension axis) const { Style::SizeLength dimension(Dimension axis) const {
return pool_.getLength(dimensions_[yoga::to_underlying(axis)]); return pool_.getSize(dimensions_[yoga::to_underlying(axis)]);
} }
void setDimension(Dimension axis, Style::Length value) { void setDimension(Dimension axis, Style::SizeLength value) {
pool_.store(dimensions_[yoga::to_underlying(axis)], value); pool_.store(dimensions_[yoga::to_underlying(axis)], value);
} }
Style::Length minDimension(Dimension axis) const { Style::SizeLength minDimension(Dimension axis) const {
return pool_.getLength(minDimensions_[yoga::to_underlying(axis)]); return pool_.getSize(minDimensions_[yoga::to_underlying(axis)]);
} }
void setMinDimension(Dimension axis, Style::Length value) { void setMinDimension(Dimension axis, Style::SizeLength value) {
pool_.store(minDimensions_[yoga::to_underlying(axis)], value); pool_.store(minDimensions_[yoga::to_underlying(axis)], value);
} }
@@ -207,10 +209,10 @@ class YG_EXPORT Style {
: FloatOptional{0.0}); : FloatOptional{0.0});
} }
Style::Length maxDimension(Dimension axis) const { Style::SizeLength maxDimension(Dimension axis) const {
return pool_.getLength(maxDimensions_[yoga::to_underlying(axis)]); return pool_.getSize(maxDimensions_[yoga::to_underlying(axis)]);
} }
void setMaxDimension(Dimension axis, Style::Length value) { void setMaxDimension(Dimension axis, Style::SizeLength value) {
pool_.store(maxDimensions_[yoga::to_underlying(axis)], value); pool_.store(maxDimensions_[yoga::to_underlying(axis)], value);
} }

View File

@@ -19,13 +19,11 @@ namespace facebook::yoga {
* 3. A CSS <length-percentage> value: * 3. A CSS <length-percentage> value:
* a. <length> value (e.g. 10px) * a. <length> value (e.g. 10px)
* b. <percentage> value of a reference <length> * b. <percentage> value of a reference <length>
* 4. (soon) A math function which returns a <length-percentage> value
* *
* References: * References:
* 1. https://www.w3.org/TR/css-values-4/#lengths * 1. https://www.w3.org/TR/css-values-4/#lengths
* 2. https://www.w3.org/TR/css-values-4/#percentage-value * 2. https://www.w3.org/TR/css-values-4/#percentage-value
* 3. https://www.w3.org/TR/css-values-4/#mixed-percentages * 3. https://www.w3.org/TR/css-values-4/#mixed-percentages
* 4. https://www.w3.org/TR/css-values-4/#math
*/ */
class StyleLength { class StyleLength {
public: public:
@@ -59,6 +57,14 @@ class StyleLength {
return unit_ == Unit::Undefined; return unit_ == Unit::Undefined;
} }
constexpr bool isPoints() const {
return unit_ == Unit::Point;
}
constexpr bool isPercent() const {
return unit_ == Unit::Percent;
}
constexpr bool isDefined() const { constexpr bool isDefined() const {
return !isUndefined(); return !isUndefined();
} }
@@ -67,10 +73,6 @@ class StyleLength {
return value_; return value_;
} }
constexpr Unit unit() const {
return unit_;
}
constexpr FloatOptional resolve(float referenceLength) { constexpr FloatOptional resolve(float referenceLength) {
switch (unit_) { switch (unit_) {
case Unit::Point: case Unit::Point:
@@ -90,6 +92,11 @@ class StyleLength {
return value_ == rhs.value_ && unit_ == rhs.unit_; return value_ == rhs.value_ && unit_ == rhs.unit_;
} }
constexpr bool inexactEquals(const StyleLength& other) const {
return unit_ == other.unit_ &&
facebook::yoga::inexactEquals(value_, other.value_);
}
private: private:
// We intentionally do not allow direct construction using value and unit, to // We intentionally do not allow direct construction using value and unit, to
// avoid invalid, or redundant combinations. // avoid invalid, or redundant combinations.
@@ -101,7 +108,7 @@ class StyleLength {
}; };
inline bool inexactEquals(const StyleLength& a, const StyleLength& b) { inline bool inexactEquals(const StyleLength& a, const StyleLength& b) {
return a.unit() == b.unit() && inexactEquals(a.value(), b.value()); return a.inexactEquals(b);
} }
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -0,0 +1,139 @@
/*
* 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/enums/Unit.h>
#include <yoga/numeric/FloatOptional.h>
namespace facebook::yoga {
/**
* This class represents a CSS Value for sizes (e.g. width, height, min-width,
* etc.). It may be one of:
* 1. Undefined
* 2. A keyword (e.g. auto, max-content, stretch, etc.)
* 3. A CSS <length-percentage> value:
* a. <length> value (e.g. 10px)
* b. <percentage> value of a reference <length>
*
* References:
* 1. https://www.w3.org/TR/css-values-4/#lengths
* 2. https://www.w3.org/TR/css-values-4/#percentage-value
* 3. https://www.w3.org/TR/css-values-4/#mixed-percentages
*/
class StyleSizeLength {
public:
constexpr StyleSizeLength() = default;
constexpr static StyleSizeLength points(float value) {
return yoga::isUndefined(value) || yoga::isinf(value)
? undefined()
: StyleSizeLength{FloatOptional{value}, Unit::Point};
}
constexpr static StyleSizeLength percent(float value) {
return yoga::isUndefined(value) || yoga::isinf(value)
? undefined()
: StyleSizeLength{FloatOptional{value}, Unit::Percent};
}
constexpr static StyleSizeLength ofAuto() {
return StyleSizeLength{{}, Unit::Auto};
}
constexpr static StyleSizeLength ofMaxContent() {
return StyleSizeLength{{}, Unit::MaxContent};
}
constexpr static StyleSizeLength ofFitContent() {
return StyleSizeLength{{}, Unit::FitContent};
}
constexpr static StyleSizeLength ofStretch() {
return StyleSizeLength{{}, Unit::Stretch};
}
constexpr static StyleSizeLength undefined() {
return StyleSizeLength{{}, Unit::Undefined};
}
constexpr bool isAuto() const {
return unit_ == Unit::Auto;
}
constexpr bool isMaxContent() const {
return unit_ == Unit::MaxContent;
}
constexpr bool isFitContent() const {
return unit_ == Unit::FitContent;
}
constexpr bool isStretch() const {
return unit_ == Unit::Stretch;
}
constexpr bool isUndefined() const {
return unit_ == Unit::Undefined;
}
constexpr bool isDefined() const {
return !isUndefined();
}
constexpr bool isPoints() const {
return unit_ == Unit::Point;
}
constexpr bool isPercent() const {
return unit_ == Unit::Percent;
}
constexpr FloatOptional value() const {
return value_;
}
constexpr FloatOptional resolve(float referenceLength) {
switch (unit_) {
case Unit::Point:
return value_;
case Unit::Percent:
return FloatOptional{value_.unwrap() * referenceLength * 0.01f};
default:
return FloatOptional{};
}
}
explicit constexpr operator YGValue() const {
return YGValue{value_.unwrap(), unscopedEnum(unit_)};
}
constexpr bool operator==(const StyleSizeLength& rhs) const {
return value_ == rhs.value_ && unit_ == rhs.unit_;
}
constexpr bool inexactEquals(const StyleSizeLength& other) const {
return unit_ == other.unit_ &&
facebook::yoga::inexactEquals(value_, other.value_);
}
private:
// We intentionally do not allow direct construction using value and unit, to
// avoid invalid, or redundant combinations.
constexpr StyleSizeLength(FloatOptional value, Unit unit)
: value_(value), unit_(unit) {}
FloatOptional value_{};
Unit unit_{Unit::Undefined};
};
inline bool inexactEquals(const StyleSizeLength& a, const StyleSizeLength& b) {
return a.inexactEquals(b);
}
} // namespace facebook::yoga

View File

@@ -62,8 +62,16 @@ class StyleValueHandle {
Percent, Percent,
Number, Number,
Auto, Auto,
Keyword
}; };
// Intentionally leaving out auto as a fast path
enum class Keyword : uint8_t { MaxContent, FitContent, Stretch };
constexpr bool isKeyword(Keyword keyword) const {
return type() == Type::Keyword && value() == static_cast<uint16_t>(keyword);
}
constexpr Type type() const { constexpr Type type() const {
return static_cast<Type>(repr_ & kHandleTypeMask); return static_cast<Type>(repr_ & kHandleTypeMask);
} }

View File

@@ -13,6 +13,7 @@
#include <yoga/numeric/FloatOptional.h> #include <yoga/numeric/FloatOptional.h>
#include <yoga/style/SmallValueBuffer.h> #include <yoga/style/SmallValueBuffer.h>
#include <yoga/style/StyleLength.h> #include <yoga/style/StyleLength.h>
#include <yoga/style/StyleSizeLength.h>
#include <yoga/style/StyleValueHandle.h> #include <yoga/style/StyleValueHandle.h>
namespace facebook::yoga { namespace facebook::yoga {
@@ -32,13 +33,30 @@ class StyleValuePool {
} else if (length.isAuto()) { } else if (length.isAuto()) {
handle.setType(StyleValueHandle::Type::Auto); handle.setType(StyleValueHandle::Type::Auto);
} else { } else {
auto type = length.unit() == Unit::Point auto type = length.isPoints() ? StyleValueHandle::Type::Point
? StyleValueHandle::Type::Point : StyleValueHandle::Type::Percent;
: StyleValueHandle::Type::Percent;
storeValue(handle, length.value().unwrap(), type); storeValue(handle, length.value().unwrap(), type);
} }
} }
void store(StyleValueHandle& handle, StyleSizeLength sizeValue) {
if (sizeValue.isUndefined()) {
handle.setType(StyleValueHandle::Type::Undefined);
} else if (sizeValue.isAuto()) {
handle.setType(StyleValueHandle::Type::Auto);
} else if (sizeValue.isMaxContent()) {
storeKeyword(handle, StyleValueHandle::Keyword::MaxContent);
} else if (sizeValue.isStretch()) {
storeKeyword(handle, StyleValueHandle::Keyword::Stretch);
} else if (sizeValue.isFitContent()) {
storeKeyword(handle, StyleValueHandle::Keyword::FitContent);
} else {
auto type = sizeValue.isPoints() ? StyleValueHandle::Type::Point
: StyleValueHandle::Type::Percent;
storeValue(handle, sizeValue.value().unwrap(), type);
}
}
void store(StyleValueHandle& handle, FloatOptional number) { void store(StyleValueHandle& handle, FloatOptional number) {
if (number.isUndefined()) { if (number.isUndefined()) {
handle.setType(StyleValueHandle::Type::Undefined); handle.setType(StyleValueHandle::Type::Undefined);
@@ -66,6 +84,31 @@ class StyleValuePool {
} }
} }
StyleSizeLength getSize(StyleValueHandle handle) const {
if (handle.isUndefined()) {
return StyleSizeLength::undefined();
} else if (handle.isAuto()) {
return StyleSizeLength::ofAuto();
} else if (handle.isKeyword(StyleValueHandle::Keyword::MaxContent)) {
return StyleSizeLength::ofMaxContent();
} else if (handle.isKeyword(StyleValueHandle::Keyword::FitContent)) {
return StyleSizeLength::ofFitContent();
} else if (handle.isKeyword(StyleValueHandle::Keyword::Stretch)) {
return StyleSizeLength::ofStretch();
} else {
assert(
handle.type() == StyleValueHandle::Type::Point ||
handle.type() == StyleValueHandle::Type::Percent);
float value = (handle.isValueIndexed())
? std::bit_cast<float>(buffer_.get32(handle.value()))
: unpackInlineInteger(handle.value());
return handle.type() == StyleValueHandle::Type::Point
? StyleSizeLength::points(value)
: StyleSizeLength::percent(value);
}
}
FloatOptional getNumber(StyleValueHandle handle) const { FloatOptional getNumber(StyleValueHandle handle) const {
if (handle.isUndefined()) { if (handle.isUndefined()) {
return FloatOptional{}; return FloatOptional{};
@@ -98,6 +141,20 @@ class StyleValuePool {
} }
} }
void storeKeyword(
StyleValueHandle& handle,
StyleValueHandle::Keyword keyword) {
handle.setType(StyleValueHandle::Type::Keyword);
if (handle.isValueIndexed()) {
auto newIndex =
buffer_.replace(handle.value(), static_cast<uint32_t>(keyword));
handle.setValue(newIndex);
} else {
handle.setValue(static_cast<uint16_t>(keyword));
}
}
static constexpr bool isIntegerPackable(float f) { static constexpr bool isIntegerPackable(float f) {
constexpr uint16_t kMaxInlineAbsValue = (1 << 11) - 1; constexpr uint16_t kMaxInlineAbsValue = (1 << 11) - 1;