#pragma once
#include "CSSPropertyNames.h"
#include <wtf/Function.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/TypeCasts.h>
#include <wtf/URLHash.h>
namespace WebCore {
class CSSCustomPropertyValue;
class CSSStyleDeclaration;
class CachedResource;
class DeprecatedCSSOMValue;
class StyleSheetContents;
enum CSSPropertyID : uint16_t;
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(CSSValue);
class CSSValue {
WTF_MAKE_NONCOPYABLE(CSSValue);
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(CSSValue);
public:
enum Type {
CSS_INHERIT = 0,
CSS_PRIMITIVE_VALUE = 1,
CSS_VALUE_LIST = 2,
CSS_CUSTOM = 3,
CSS_INITIAL = 4,
CSS_UNSET = 5,
CSS_REVERT = 6
};
static constexpr unsigned refCountFlagIsStatic = 0x1;
static constexpr unsigned refCountIncrement = 0x2; void ref() const
{
m_refCount += refCountIncrement;
}
bool hasOneRef() const { return m_refCount == refCountIncrement; }
unsigned refCount() const { return m_refCount / refCountIncrement; }
bool hasAtLeastOneRef() const { return m_refCount; }
void deref()
{
unsigned tempRefCount = m_refCount - refCountIncrement;
if (!tempRefCount) {
destroy();
return;
}
m_refCount = tempRefCount;
}
Type cssValueType() const;
String cssText() const;
bool isPrimitiveValue() const { return m_classType == PrimitiveClass; }
bool isValueList() const { return m_classType >= ValueListClass; }
bool isBaseValueList() const { return m_classType == ValueListClass; }
bool isAspectRatioValue() const { return m_classType == AspectRatioClass; }
bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
bool isCanvasValue() const { return m_classType == CanvasClass; }
bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
bool isCursorImageValue() const { return m_classType == CursorImageClass; }
bool isCustomPropertyValue() const { return m_classType == CustomPropertyClass; }
bool isFunctionValue() const { return m_classType == FunctionClass; }
bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
bool isFontVariationValue() const { return m_classType == FontVariationClass; }
bool isFontFaceSrcValue() const { return m_classType == FontFaceSrcClass; }
bool isFontValue() const { return m_classType == FontClass; }
bool isFontStyleValue() const { return m_classType == FontStyleClass; }
bool isFontStyleRangeValue() const { return m_classType == FontStyleRangeClass; }
bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= ConicGradientClass; }
bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= ConicGradientClass; }
bool isNamedImageValue() const { return m_classType == NamedImageClass; }
bool isImageSetValue() const { return m_classType == ImageSetClass; }
bool isImageValue() const { return m_classType == ImageClass; }
bool isImplicitInitialValue() const;
bool isInheritedValue() const { return m_classType == InheritedClass; }
bool isInitialValue() const { return m_classType == InitialClass; }
bool isUnsetValue() const { return m_classType == UnsetClass; }
bool isRevertValue() const { return m_classType == RevertClass; }
bool isGlobalKeyword() const { return isInheritedValue() || isInitialValue() || isUnsetValue() || isRevertValue(); }
bool treatAsInitialValue(CSSPropertyID) const;
bool treatAsInheritedValue(CSSPropertyID) const;
bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
bool isRadialGradientValue() const { return m_classType == RadialGradientClass; }
bool isConicGradientValue() const { return m_classType == ConicGradientClass; }
bool isReflectValue() const { return m_classType == ReflectClass; }
bool isShadowValue() const { return m_classType == ShadowClass; }
bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; }
bool isStepsTimingFunctionValue() const { return m_classType == StepsTimingFunctionClass; }
bool isSpringTimingFunctionValue() const { return m_classType == SpringTimingFunctionClass; }
bool isLineBoxContainValue() const { return m_classType == LineBoxContainClass; }
bool isCalcValue() const {return m_classType == CalculationClass; }
bool isFilterImageValue() const { return m_classType == FilterImageClass; }
#if ENABLE(CSS_PAINTING_API)
bool isPaintImageValue() const { return m_classType == PaintImageClass; }
#endif
bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; }
bool isGridAutoRepeatValue() const { return m_classType == GridAutoRepeatClass; }
bool isGridIntegerRepeatValue() const { return m_classType == GridIntegerRepeatClass; }
bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
bool isCustomIdentValue() const { return m_classType == CustomIdentClass; }
bool isVariableReferenceValue() const { return m_classType == VariableReferenceClass; }
bool isPendingSubstitutionValue() const { return m_classType == PendingSubstitutionValueClass; }
bool hasVariableReferences() const { return isVariableReferenceValue() || isPendingSubstitutionValue(); }
Ref<DeprecatedCSSOMValue> createDeprecatedCSSOMWrapper(CSSStyleDeclaration&) const;
bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const;
void collectDirectComputationalDependencies(HashSet<CSSPropertyID>&) const;
void collectDirectRootComputationalDependencies(HashSet<CSSPropertyID>&) const;
bool equals(const CSSValue&) const;
bool operator==(const CSSValue& other) const { return equals(other); }
protected:
static const size_t ClassTypeBits = 6;
enum ClassType {
PrimitiveClass,
ImageClass,
CursorImageClass,
CanvasClass,
#if ENABLE(CSS_PAINTING_API)
PaintImageClass,
#endif
NamedImageClass,
CrossfadeClass,
FilterImageClass,
LinearGradientClass,
RadialGradientClass,
ConicGradientClass,
CubicBezierTimingFunctionClass,
StepsTimingFunctionClass,
SpringTimingFunctionClass,
AspectRatioClass,
BorderImageSliceClass,
FontFeatureClass,
FontVariationClass,
FontClass,
FontStyleClass,
FontStyleRangeClass,
FontFaceSrcClass,
FunctionClass,
InheritedClass,
InitialClass,
UnsetClass,
RevertClass,
ReflectClass,
ShadowClass,
UnicodeRangeClass,
LineBoxContainClass,
CalculationClass,
GridTemplateAreasClass,
CSSContentDistributionClass,
CustomIdentClass,
CustomPropertyClass,
VariableReferenceClass,
PendingSubstitutionValueClass,
ValueListClass,
ImageSetClass,
GridLineNamesClass,
GridAutoRepeatClass,
GridIntegerRepeatClass,
};
public:
static const size_t ValueListSeparatorBits = 2;
enum ValueListSeparator {
SpaceSeparator,
CommaSeparator,
SlashSeparator
};
enum StaticCSSValueTag { StaticCSSValue };
protected:
ClassType classType() const { return static_cast<ClassType>(m_classType); }
explicit CSSValue(ClassType classType)
: m_primitiveUnitType(0)
, m_hasCachedCSSText(false)
, m_valueListSeparator(SpaceSeparator)
, m_classType(classType)
{
}
void makeStatic()
{
m_refCount |= refCountFlagIsStatic;
}
~CSSValue() = default;
private:
WEBCORE_EXPORT void destroy();
mutable unsigned m_refCount { refCountIncrement };
protected:
unsigned m_primitiveUnitType : 7; mutable unsigned m_hasCachedCSSText : 1;
unsigned m_valueListSeparator : ValueListSeparatorBits;
private:
unsigned m_classType : ClassTypeBits;
friend class CSSValueList;
};
template<typename CSSValueType>
inline bool compareCSSValueVector(const Vector<Ref<CSSValueType>>& firstVector, const Vector<Ref<CSSValueType>>& secondVector)
{
size_t size = firstVector.size();
if (size != secondVector.size())
return false;
for (size_t i = 0; i < size; ++i) {
auto& firstPtr = firstVector[i];
auto& secondPtr = secondVector[i];
if (firstPtr.ptr() == secondPtr.ptr() || firstPtr->equals(secondPtr))
continue;
return false;
}
return true;
}
template<typename CSSValueType>
inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second)
{
return first ? second && first->equals(*second) : !second;
}
template<typename CSSValueType>
inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueType>& second)
{
return first.get().equals(second);
}
typedef HashMap<AtomString, RefPtr<CSSCustomPropertyValue>> CustomPropertyValueMap;
}
#define SPECIALIZE_TYPE_TRAITS_CSS_VALUE(ToValueTypeName, predicate) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
static bool isType(const WebCore::CSSValue& value) { return value.predicate; } \
SPECIALIZE_TYPE_TRAITS_END()