mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
CSSDeclaredStyle
Summary: Adds a sparse `CSSDeclaredStyle` structure to represent the collection of declarations from the user, before being further processed/computed. This will later be procssed into computed style. Also fixes up some bad naming wrt specified value and declared value. Changelog: [Internal] Reviewed By: joevilches Differential Revision: D53696422 fbshipit-source-id: 4258c86a29a0b2251c969b299b5b4703c06696db
This commit is contained in:
committed by
Facebook GitHub Bot
parent
516c4ccb71
commit
f2d09651e0
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 <algorithm>
|
||||
#include <bitset>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/renderer/css/CSSParser.h>
|
||||
#include <react/renderer/css/CSSProperties.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* CSSDeclaredStyle represents the set of style declarations on an element set
|
||||
* by the user. Users should generally not read from CSSDeclaredStyle directly,
|
||||
* and should instead use the computed style calculated on ShadowTree commit.
|
||||
*/
|
||||
class CSSDeclaredStyle {
|
||||
public:
|
||||
template <CSSProp Prop>
|
||||
void set(const CSSDeclaredValue<Prop>& value) {
|
||||
using DeclaredValueT = std::remove_cvref_t<CSSDeclaredValue<Prop>>;
|
||||
static_assert(sizeof(value) <= sizeof(PropMapping::value));
|
||||
static_assert(std::is_trivially_destructible_v<DeclaredValueT>);
|
||||
|
||||
if (specifiedProperties_.test(to_underlying(Prop))) {
|
||||
auto it = std::lower_bound(
|
||||
properties_.begin(), properties_.end(), PropMapping{Prop, {}});
|
||||
react_native_assert(it->prop == Prop);
|
||||
std::construct_at(
|
||||
reinterpret_cast<DeclaredValueT*>(it->value.data()), value);
|
||||
} else {
|
||||
auto it = std::upper_bound(
|
||||
properties_.begin(), properties_.end(), PropMapping{Prop, {}});
|
||||
it = properties_.insert(it, {Prop, {}});
|
||||
std::construct_at(
|
||||
reinterpret_cast<DeclaredValueT*>(it->value.data()), value);
|
||||
specifiedProperties_.set(to_underlying(Prop));
|
||||
}
|
||||
}
|
||||
|
||||
template <CSSProp Prop>
|
||||
void set(std::string_view value) {
|
||||
set<Prop>(parseCSSProp<Prop>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the declared value, represented as the "unset" keyword if never
|
||||
* specified. Additional shorthands can be provided in order
|
||||
* of precedence if Prop is unset.
|
||||
*/
|
||||
template <CSSProp Prop, CSSProp... ShorthandsT>
|
||||
CSSDeclaredValue<Prop> get() const {
|
||||
if (specifiedProperties_.test(to_underlying(Prop))) {
|
||||
auto it = std::lower_bound(
|
||||
properties_.begin(), properties_.end(), PropMapping{Prop, {}});
|
||||
react_native_assert(it->prop == Prop);
|
||||
|
||||
CSSDeclaredValue<Prop> value{*std::launder(
|
||||
reinterpret_cast<const CSSDeclaredValue<Prop>*>(it->value.data()))};
|
||||
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (sizeof...(ShorthandsT) == 0) {
|
||||
return {};
|
||||
} else {
|
||||
return get<ShorthandsT...>();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const CSSDeclaredStyle& rhs) const = default;
|
||||
|
||||
private:
|
||||
struct PropMapping {
|
||||
CSSProp prop;
|
||||
std::array<
|
||||
std::byte,
|
||||
sizeof(CSSValueVariant<
|
||||
CSSWideKeyword,
|
||||
CSSKeyword,
|
||||
CSSLength,
|
||||
CSSNumber,
|
||||
CSSPercentage,
|
||||
CSSRatio>)>
|
||||
value;
|
||||
|
||||
constexpr bool operator<(const PropMapping& rhs) const {
|
||||
return to_underlying(prop) < to_underlying(rhs.prop);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<PropMapping> properties_;
|
||||
std::bitset<kCSSPropCount> specifiedProperties_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -212,7 +212,7 @@ CSSValueVariant<AllowedTypesT...> parseCSSComponentValue(std::string_view css) {
|
||||
template <CSSProp Prop>
|
||||
constexpr auto parseCSSProp(std::string_view css) {
|
||||
// For now we only allow parsing props composed of a single component value.
|
||||
CSSSpecifiedValue<Prop> value;
|
||||
CSSDeclaredValue<Prop> value;
|
||||
parseCSSComponentValue(css, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -137,16 +137,22 @@ struct CSSPropDefinition {};
|
||||
template <CSSProp P>
|
||||
using CSSAllowedKeywords = typename CSSPropDefinition<P>::Keyword;
|
||||
|
||||
template <CSSProp P>
|
||||
using CSSDeclaredValue = typename CSSPropDefinition<P>::DeclaredValue;
|
||||
|
||||
template <CSSProp P>
|
||||
using CSSSpecifiedValue = typename CSSPropDefinition<P>::SpecifiedValue;
|
||||
|
||||
template <CSSProp P>
|
||||
using CSSComputedValue = typename CSSPropDefinition<P>::ComputedValue;
|
||||
|
||||
struct CSSComputeContext {
|
||||
bool isRTL{false};
|
||||
bool useWebDefaults{false};
|
||||
bool swapLeftAndRight{false};
|
||||
/**
|
||||
* Whether to behave in accordance with W3C specs, or to incorporate React
|
||||
* Native specific tweaks to defaults and computation.
|
||||
*/
|
||||
enum class CSSFlavor {
|
||||
W3C,
|
||||
ReactNative,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -168,16 +174,18 @@ struct CSSPropDefinition<CSSProp::AlignContent> {
|
||||
End = to_underlying(CSSKeyword::End),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::Stretch)
|
||||
: SpecifiedValue::keyword(Keyword::FlexStart);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C
|
||||
? DeclaredValue::keyword(Keyword::Stretch)
|
||||
: DeclaredValue::keyword(Keyword::FlexStart);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -198,15 +206,16 @@ struct CSSPropDefinition<CSSProp::AlignItems> {
|
||||
End = to_underlying(CSSKeyword::End),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Stretch);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Stretch);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -228,15 +237,16 @@ struct CSSPropDefinition<CSSProp::AlignSelf> {
|
||||
End = to_underlying(CSSKeyword::End),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Auto);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Auto);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -250,15 +260,16 @@ struct CSSPropDefinition<CSSProp::AspectRatio> {
|
||||
Auto = to_underlying(CSSKeyword::Auto),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSRatio>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSRatio>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSRatio>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSRatio>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Auto);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Auto);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -268,16 +279,17 @@ struct CSSPropDefinition<CSSProp::AspectRatio> {
|
||||
*/
|
||||
template <>
|
||||
struct CSSPropDefinition<CSSProp::BorderRadius> {
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::length(0.0f, CSSLengthUnit::Px);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::length(0.0f, CSSLengthUnit::Px);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -332,16 +344,17 @@ struct CSSPropDefinition<CSSProp::BorderStyle> {
|
||||
Outset = to_underlying(CSSKeyword::Outset),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::None)
|
||||
: SpecifiedValue::keyword(Keyword::Solid);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::None)
|
||||
: DeclaredValue::keyword(Keyword::Solid);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -397,16 +410,18 @@ struct CSSPropDefinition<CSSProp::BorderWidth> {
|
||||
Thick = to_underlying(CSSKeyword::Thick),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSLength>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSLength>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSLength, CSSKeyword>;
|
||||
using ComputedValue = CSSValueVariant<CSSLength>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::Medium)
|
||||
: SpecifiedValue::length(0.0f, CSSLengthUnit::Px);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C
|
||||
? DeclaredValue::keyword(Keyword::Medium)
|
||||
: DeclaredValue::length(0.0f, CSSLengthUnit::Px);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -477,15 +492,16 @@ struct CSSPropDefinition<CSSProp::Direction> {
|
||||
Rtl = to_underlying(CSSKeyword::Rtl),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Ltr);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Ltr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -507,16 +523,17 @@ struct CSSPropDefinition<CSSProp::Display> {
|
||||
InlineGrid = to_underlying(CSSKeyword::InlineGrid),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::Inline)
|
||||
: SpecifiedValue::keyword(Keyword::Flex);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Inline)
|
||||
: DeclaredValue::keyword(Keyword::Flex);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -534,15 +551,16 @@ struct CSSPropDefinition<CSSProp::Flex> {
|
||||
None = to_underlying(CSSKeyword::None),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSNumber>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSNumber>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSNumber>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSNumber>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::number(0.0f);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::number(0.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -557,16 +575,17 @@ struct CSSPropDefinition<CSSProp::FlexBasis> {
|
||||
Content = to_underlying(CSSKeyword::Content),
|
||||
};
|
||||
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, Keyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Auto);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Auto);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -583,16 +602,17 @@ struct CSSPropDefinition<CSSProp::FlexDirection> {
|
||||
ColumnReverse = to_underlying(CSSKeyword::ColumnReverse),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::Row)
|
||||
: SpecifiedValue::keyword(Keyword::Column);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Row)
|
||||
: DeclaredValue::keyword(Keyword::Column);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -602,15 +622,16 @@ struct CSSPropDefinition<CSSProp::FlexDirection> {
|
||||
*/
|
||||
template <>
|
||||
struct CSSPropDefinition<CSSProp::FlexGrow> {
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSNumber>;
|
||||
using ComputedValue = CSSValueVariant<CSSNumber>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::number(0.0f);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::number(0.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -620,16 +641,17 @@ struct CSSPropDefinition<CSSProp::FlexGrow> {
|
||||
*/
|
||||
template <>
|
||||
struct CSSPropDefinition<CSSProp::FlexShrink> {
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSNumber>;
|
||||
using ComputedValue = CSSValueVariant<CSSNumber>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::number(1.0f)
|
||||
: SpecifiedValue::number(0.0f);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C ? DeclaredValue::number(1.0f)
|
||||
: DeclaredValue::number(0.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -645,15 +667,16 @@ struct CSSPropDefinition<CSSProp::FlexWrap> {
|
||||
WrapReverse = to_underlying(CSSKeyword::WrapReverse),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::NoWrap);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::NoWrap);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -667,15 +690,16 @@ struct CSSPropDefinition<CSSProp::Gap> {
|
||||
Normal = to_underlying(CSSKeyword::Normal),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSLength>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword, CSSLength>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSLength>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSLength>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Normal);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Normal);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -698,16 +722,17 @@ struct CSSPropDefinition<CSSProp::Height> {
|
||||
MinContent = to_underlying(CSSKeyword::MinContent),
|
||||
};
|
||||
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, Keyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Auto);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Auto);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -741,16 +766,17 @@ struct CSSPropDefinition<CSSProp::Inset> {
|
||||
Auto = to_underlying(CSSKeyword::Auto),
|
||||
};
|
||||
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, Keyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Auto);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Auto);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -815,15 +841,16 @@ struct CSSPropDefinition<CSSProp::JustifyContent> {
|
||||
End = to_underlying(CSSKeyword::End),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::FlexStart);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::FlexStart);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -837,16 +864,17 @@ struct CSSPropDefinition<CSSProp::Margin> {
|
||||
Auto = to_underlying(CSSKeyword::Auto),
|
||||
};
|
||||
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, Keyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<Keyword, CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::length(0.0f, CSSLengthUnit::Px);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::length(0.0f, CSSLengthUnit::Px);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -912,15 +940,16 @@ struct CSSPropDefinition<CSSProp::MarginVertical>
|
||||
*/
|
||||
template <>
|
||||
struct CSSPropDefinition<CSSProp::Opacity> {
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, CSSNumber>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSNumber>;
|
||||
using ComputedValue = CSSValueVariant<CSSNumber>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::number(1.0f);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::number(1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -938,15 +967,16 @@ struct CSSPropDefinition<CSSProp::Overflow> {
|
||||
Visible = to_underlying(CSSKeyword::Visible),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::keyword(Keyword::Visible);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::keyword(Keyword::Visible);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -956,16 +986,17 @@ struct CSSPropDefinition<CSSProp::Overflow> {
|
||||
*/
|
||||
template <>
|
||||
struct CSSPropDefinition<CSSProp::Padding> {
|
||||
using SpecifiedValue =
|
||||
using DeclaredValue =
|
||||
CSSValueVariant<CSSWideKeyword, CSSLength, CSSPercentage>;
|
||||
using SpecifiedValue = CSSValueVariant<CSSLength, CSSPercentage>;
|
||||
using ComputedValue = CSSValueVariant<CSSLength, CSSPercentage>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext&) {
|
||||
return SpecifiedValue::length(0.0f, CSSLengthUnit::Px);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor /*flavor*/) {
|
||||
return DeclaredValue::length(0.0f, CSSLengthUnit::Px);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1039,16 +1070,17 @@ struct CSSPropDefinition<CSSProp::Position> {
|
||||
Sticky = to_underlying(CSSKeyword::Sticky),
|
||||
};
|
||||
|
||||
using SpecifiedValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using DeclaredValue = CSSValueVariant<CSSWideKeyword, Keyword>;
|
||||
using SpecifiedValue = CSSValueVariant<Keyword>;
|
||||
using ComputedValue = CSSValueVariant<Keyword>;
|
||||
|
||||
constexpr static bool isInherited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr static SpecifiedValue initialValue(const CSSComputeContext& ctx) {
|
||||
return ctx.useWebDefaults ? SpecifiedValue::keyword(Keyword::Static)
|
||||
: SpecifiedValue::keyword(Keyword::Relative);
|
||||
constexpr static DeclaredValue initialValue(CSSFlavor flavor) {
|
||||
return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Static)
|
||||
: DeclaredValue::keyword(Keyword::Relative);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,9 +36,7 @@ enum class CSSValueType : uint8_t {
|
||||
*/
|
||||
template <typename T>
|
||||
concept CSSDataType = std::is_trivially_destructible_v<T> &&
|
||||
std::is_default_constructible_v<T> && requires() {
|
||||
sizeof(T);
|
||||
};
|
||||
std::is_copy_constructible_v<T> && std::is_default_constructible_v<T>;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 <react/renderer/css/CSSDeclaredStyle.h>
|
||||
#include <react/renderer/css/CSSParser.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
TEST(CSSDeclaredStyle, unset_keyword) {
|
||||
CSSDeclaredStyle style;
|
||||
auto value = style.get<CSSProp::FlexDirection>();
|
||||
EXPECT_EQ(value.type(), CSSValueType::CSSWideKeyword);
|
||||
EXPECT_EQ(value.getCSSWideKeyword(), CSSWideKeyword::Unset);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, unset_ratio) {
|
||||
CSSDeclaredStyle style;
|
||||
auto value = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(value.type(), CSSValueType::CSSWideKeyword);
|
||||
EXPECT_EQ(value.getCSSWideKeyword(), CSSWideKeyword::Unset);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, set_keyword) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::FlexDirection>("row");
|
||||
|
||||
auto value = style.get<CSSProp::FlexDirection>();
|
||||
EXPECT_EQ(value.type(), CSSValueType::Keyword);
|
||||
EXPECT_EQ(
|
||||
value.getKeyword(), CSSAllowedKeywords<CSSProp::FlexDirection>::Row);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, set_ratio) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::AspectRatio>("16 / 9");
|
||||
|
||||
auto value = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(value.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(value.getRatio().numerator, 16.0f);
|
||||
EXPECT_EQ(value.getRatio().denominator, 9.0f);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, overwrite_ratio) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::AspectRatio>("16 / 9");
|
||||
|
||||
auto value1 = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(value1.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(value1.getRatio().numerator, 16.0f);
|
||||
EXPECT_EQ(value1.getRatio().denominator, 9.0f);
|
||||
|
||||
style.set<CSSProp::AspectRatio>("4/3");
|
||||
|
||||
auto value2 = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(value2.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(value2.getRatio().numerator, 4.0f);
|
||||
EXPECT_EQ(value2.getRatio().denominator, 3.0f);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, set_multiple) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::FlexDirection>("row");
|
||||
style.set<CSSProp::AspectRatio>("16 / 9");
|
||||
|
||||
auto flexDirection = style.get<CSSProp::FlexDirection>();
|
||||
EXPECT_EQ(flexDirection.type(), CSSValueType::Keyword);
|
||||
EXPECT_EQ(
|
||||
flexDirection.getKeyword(),
|
||||
CSSAllowedKeywords<CSSProp::FlexDirection>::Row);
|
||||
|
||||
auto aspectRatio = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(aspectRatio.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(aspectRatio.getRatio().numerator, 16.0f);
|
||||
EXPECT_EQ(aspectRatio.getRatio().denominator, 9.0f);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, set_multiple_overwrite) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::FlexDirection>("row");
|
||||
style.set<CSSProp::AspectRatio>("16 / 9");
|
||||
style.set<CSSProp::FlexDirection>("column");
|
||||
|
||||
auto flexDirection = style.get<CSSProp::FlexDirection>();
|
||||
EXPECT_EQ(flexDirection.type(), CSSValueType::Keyword);
|
||||
EXPECT_EQ(
|
||||
flexDirection.getKeyword(),
|
||||
CSSAllowedKeywords<CSSProp::FlexDirection>::Column);
|
||||
|
||||
auto aspectRatio = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(aspectRatio.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(aspectRatio.getRatio().numerator, 16.0f);
|
||||
EXPECT_EQ(aspectRatio.getRatio().denominator, 9.0f);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, set_multiple_reset) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::FlexDirection>("row");
|
||||
style.set<CSSProp::AspectRatio>("16 / 9");
|
||||
style.set<CSSProp::FlexDirection>("");
|
||||
|
||||
auto flexDirection = style.get<CSSProp::FlexDirection>();
|
||||
EXPECT_EQ(flexDirection.type(), CSSValueType::CSSWideKeyword);
|
||||
EXPECT_EQ(flexDirection.getCSSWideKeyword(), CSSWideKeyword::Unset);
|
||||
|
||||
auto aspectRatio = style.get<CSSProp::AspectRatio>();
|
||||
EXPECT_EQ(aspectRatio.type(), CSSValueType::Ratio);
|
||||
EXPECT_EQ(aspectRatio.getRatio().numerator, 16.0f);
|
||||
EXPECT_EQ(aspectRatio.getRatio().denominator, 9.0f);
|
||||
}
|
||||
|
||||
TEST(CSSDeclaredStyle, get_with_precedence) {
|
||||
CSSDeclaredStyle style;
|
||||
|
||||
style.set<CSSProp::Margin>("1px");
|
||||
|
||||
auto margin1 = style.get<
|
||||
CSSProp::MarginStart,
|
||||
CSSProp::MarginLeft,
|
||||
CSSProp::MarginInline,
|
||||
CSSProp::MarginHorizontal,
|
||||
CSSProp::Margin>();
|
||||
|
||||
EXPECT_EQ(margin1.type(), CSSValueType::Length);
|
||||
EXPECT_EQ(margin1.getLength().value, 1.0f);
|
||||
EXPECT_EQ(margin1.getLength().unit, CSSLengthUnit::Px);
|
||||
|
||||
style.set<CSSProp::MarginLeft>("3px");
|
||||
auto margin2 = style.get<
|
||||
CSSProp::MarginStart,
|
||||
CSSProp::MarginLeft,
|
||||
CSSProp::MarginInline,
|
||||
CSSProp::MarginHorizontal,
|
||||
CSSProp::Margin>();
|
||||
|
||||
EXPECT_EQ(margin2.type(), CSSValueType::Length);
|
||||
EXPECT_EQ(margin2.getLength().value, 3.0f);
|
||||
EXPECT_EQ(margin2.getLength().unit, CSSLengthUnit::Px);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
Reference in New Issue
Block a user