| 1 | /* |
| 2 | * (C) 1999-2003 Lars Knoll (knoll@kde.org) |
| 3 | * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 4 | * |
| 5 | * This library is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU Library General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the License, or (at your option) any later version. |
| 9 | * |
| 10 | * This library is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * Library General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU Library General Public License |
| 16 | * along with this library; see the file COPYING.LIB. If not, write to |
| 17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 18 | * Boston, MA 02110-1301, USA. |
| 19 | */ |
| 20 | |
| 21 | #pragma once |
| 22 | |
| 23 | #include "CSSPropertyNames.h" |
| 24 | #include <wtf/Function.h> |
| 25 | #include <wtf/HashMap.h> |
| 26 | #include <wtf/RefCounted.h> |
| 27 | #include <wtf/RefPtr.h> |
| 28 | #include <wtf/TypeCasts.h> |
| 29 | #include <wtf/URLHash.h> |
| 30 | |
| 31 | namespace WebCore { |
| 32 | |
| 33 | class CSSCustomPropertyValue; |
| 34 | class CSSStyleDeclaration; |
| 35 | class CachedResource; |
| 36 | class DeprecatedCSSOMValue; |
| 37 | class StyleSheetContents; |
| 38 | |
| 39 | enum CSSPropertyID : uint16_t; |
| 40 | |
| 41 | class CSSValue : public RefCounted<CSSValue> { |
| 42 | public: |
| 43 | enum Type { |
| 44 | CSS_INHERIT = 0, |
| 45 | CSS_PRIMITIVE_VALUE = 1, |
| 46 | CSS_VALUE_LIST = 2, |
| 47 | CSS_CUSTOM = 3, |
| 48 | CSS_INITIAL = 4, |
| 49 | CSS_UNSET = 5, |
| 50 | CSS_REVERT = 6 |
| 51 | }; |
| 52 | |
| 53 | // Override RefCounted's deref() to ensure operator delete is called on |
| 54 | // the appropriate subclass type. |
| 55 | void deref() |
| 56 | { |
| 57 | if (derefBase()) |
| 58 | destroy(); |
| 59 | } |
| 60 | |
| 61 | Type cssValueType() const; |
| 62 | String cssText() const; |
| 63 | |
| 64 | bool isPrimitiveValue() const { return m_classType == PrimitiveClass; } |
| 65 | bool isValueList() const { return m_classType >= ValueListClass; } |
| 66 | |
| 67 | bool isBaseValueList() const { return m_classType == ValueListClass; } |
| 68 | |
| 69 | |
| 70 | bool isAspectRatioValue() const { return m_classType == AspectRatioClass; } |
| 71 | bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; } |
| 72 | bool isCanvasValue() const { return m_classType == CanvasClass; } |
| 73 | bool isCrossfadeValue() const { return m_classType == CrossfadeClass; } |
| 74 | bool isCursorImageValue() const { return m_classType == CursorImageClass; } |
| 75 | bool isCustomPropertyValue() const { return m_classType == CustomPropertyClass; } |
| 76 | bool isFunctionValue() const { return m_classType == FunctionClass; } |
| 77 | bool isFontFeatureValue() const { return m_classType == FontFeatureClass; } |
| 78 | #if ENABLE(VARIATION_FONTS) |
| 79 | bool isFontVariationValue() const { return m_classType == FontVariationClass; } |
| 80 | #endif |
| 81 | bool isFontFaceSrcValue() const { return m_classType == FontFaceSrcClass; } |
| 82 | bool isFontValue() const { return m_classType == FontClass; } |
| 83 | bool isFontStyleValue() const { return m_classType == FontStyleClass; } |
| 84 | bool isFontStyleRangeValue() const { return m_classType == FontStyleRangeClass; } |
| 85 | bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= ConicGradientClass; } |
| 86 | bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= ConicGradientClass; } |
| 87 | bool isNamedImageValue() const { return m_classType == NamedImageClass; } |
| 88 | bool isImageSetValue() const { return m_classType == ImageSetClass; } |
| 89 | bool isImageValue() const { return m_classType == ImageClass; } |
| 90 | bool isImplicitInitialValue() const; |
| 91 | bool isInheritedValue() const { return m_classType == InheritedClass; } |
| 92 | bool isInitialValue() const { return m_classType == InitialClass; } |
| 93 | bool isUnsetValue() const { return m_classType == UnsetClass; } |
| 94 | bool isRevertValue() const { return m_classType == RevertClass; } |
| 95 | bool isGlobalKeyword() const { return isInheritedValue() || isInitialValue() || isUnsetValue() || isRevertValue(); } |
| 96 | bool treatAsInitialValue(CSSPropertyID) const; |
| 97 | bool treatAsInheritedValue(CSSPropertyID) const; |
| 98 | bool isLinearGradientValue() const { return m_classType == LinearGradientClass; } |
| 99 | bool isRadialGradientValue() const { return m_classType == RadialGradientClass; } |
| 100 | bool isConicGradientValue() const { return m_classType == ConicGradientClass; } |
| 101 | bool isReflectValue() const { return m_classType == ReflectClass; } |
| 102 | bool isShadowValue() const { return m_classType == ShadowClass; } |
| 103 | bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; } |
| 104 | bool isStepsTimingFunctionValue() const { return m_classType == StepsTimingFunctionClass; } |
| 105 | bool isSpringTimingFunctionValue() const { return m_classType == SpringTimingFunctionClass; } |
| 106 | bool isLineBoxContainValue() const { return m_classType == LineBoxContainClass; } |
| 107 | bool isCalcValue() const {return m_classType == CalculationClass; } |
| 108 | bool isFilterImageValue() const { return m_classType == FilterImageClass; } |
| 109 | #if ENABLE(CSS_PAINTING_API) |
| 110 | bool isPaintImageValue() const { return m_classType == PaintImageClass; } |
| 111 | #endif |
| 112 | bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; } |
| 113 | bool isGridAutoRepeatValue() const { return m_classType == GridAutoRepeatClass; } |
| 114 | bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; } |
| 115 | bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; } |
| 116 | bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; } |
| 117 | |
| 118 | bool isCustomIdentValue() const { return m_classType == CustomIdentClass; } |
| 119 | bool isVariableReferenceValue() const { return m_classType == VariableReferenceClass; } |
| 120 | bool isPendingSubstitutionValue() const { return m_classType == PendingSubstitutionValueClass; } |
| 121 | |
| 122 | bool hasVariableReferences() const { return isVariableReferenceValue() || isPendingSubstitutionValue(); } |
| 123 | |
| 124 | Ref<DeprecatedCSSOMValue> createDeprecatedCSSOMWrapper(CSSStyleDeclaration&) const; |
| 125 | |
| 126 | bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const; |
| 127 | |
| 128 | // What properties does this value rely on (eg, font-size for em units) |
| 129 | void collectDirectComputationalDependencies(HashSet<CSSPropertyID>&) const; |
| 130 | // What properties in the root element does this value rely on (eg. font-size for rem units) |
| 131 | void collectDirectRootComputationalDependencies(HashSet<CSSPropertyID>&) const; |
| 132 | |
| 133 | bool equals(const CSSValue&) const; |
| 134 | bool operator==(const CSSValue& other) const { return equals(other); } |
| 135 | |
| 136 | protected: |
| 137 | |
| 138 | static const size_t ClassTypeBits = 6; |
| 139 | enum ClassType { |
| 140 | PrimitiveClass, |
| 141 | |
| 142 | // Image classes. |
| 143 | ImageClass, |
| 144 | CursorImageClass, |
| 145 | |
| 146 | // Image generator classes. |
| 147 | CanvasClass, |
| 148 | #if ENABLE(CSS_PAINTING_API) |
| 149 | PaintImageClass, |
| 150 | #endif |
| 151 | NamedImageClass, |
| 152 | CrossfadeClass, |
| 153 | FilterImageClass, |
| 154 | LinearGradientClass, |
| 155 | RadialGradientClass, |
| 156 | ConicGradientClass, |
| 157 | |
| 158 | // Timing function classes. |
| 159 | CubicBezierTimingFunctionClass, |
| 160 | StepsTimingFunctionClass, |
| 161 | SpringTimingFunctionClass, |
| 162 | |
| 163 | // Other class types. |
| 164 | AspectRatioClass, |
| 165 | BorderImageSliceClass, |
| 166 | FontFeatureClass, |
| 167 | #if ENABLE(VARIATION_FONTS) |
| 168 | FontVariationClass, |
| 169 | #endif |
| 170 | FontClass, |
| 171 | FontStyleClass, |
| 172 | FontStyleRangeClass, |
| 173 | FontFaceSrcClass, |
| 174 | FunctionClass, |
| 175 | |
| 176 | InheritedClass, |
| 177 | InitialClass, |
| 178 | UnsetClass, |
| 179 | RevertClass, |
| 180 | |
| 181 | ReflectClass, |
| 182 | ShadowClass, |
| 183 | UnicodeRangeClass, |
| 184 | LineBoxContainClass, |
| 185 | CalculationClass, |
| 186 | GridTemplateAreasClass, |
| 187 | |
| 188 | CSSContentDistributionClass, |
| 189 | |
| 190 | CustomIdentClass, |
| 191 | |
| 192 | CustomPropertyClass, |
| 193 | VariableReferenceClass, |
| 194 | PendingSubstitutionValueClass, |
| 195 | |
| 196 | // List class types must appear after ValueListClass. Note CSSFunctionValue |
| 197 | // is deliberately excluded, since we don't want it exposed to the CSS OM |
| 198 | // as a list. |
| 199 | ValueListClass, |
| 200 | ImageSetClass, |
| 201 | GridLineNamesClass, |
| 202 | GridAutoRepeatClass, |
| 203 | // Do not append non-list class types here. |
| 204 | }; |
| 205 | |
| 206 | public: |
| 207 | static const size_t ValueListSeparatorBits = 2; |
| 208 | enum ValueListSeparator { |
| 209 | SpaceSeparator, |
| 210 | CommaSeparator, |
| 211 | SlashSeparator |
| 212 | }; |
| 213 | |
| 214 | protected: |
| 215 | ClassType classType() const { return static_cast<ClassType>(m_classType); } |
| 216 | |
| 217 | explicit CSSValue(ClassType classType) |
| 218 | : m_primitiveUnitType(0) |
| 219 | , m_hasCachedCSSText(false) |
| 220 | , m_isQuirkValue(false) |
| 221 | , m_valueListSeparator(SpaceSeparator) |
| 222 | , m_classType(classType) |
| 223 | { |
| 224 | } |
| 225 | |
| 226 | // NOTE: This class is non-virtual for memory and performance reasons. |
| 227 | // Don't go making it virtual again unless you know exactly what you're doing! |
| 228 | |
| 229 | ~CSSValue() = default; |
| 230 | |
| 231 | private: |
| 232 | WEBCORE_EXPORT void destroy(); |
| 233 | |
| 234 | protected: |
| 235 | // The bits in this section are only used by specific subclasses but kept here |
| 236 | // to maximize struct packing. |
| 237 | |
| 238 | // CSSPrimitiveValue bits: |
| 239 | unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitType |
| 240 | mutable unsigned m_hasCachedCSSText : 1; |
| 241 | unsigned m_isQuirkValue : 1; |
| 242 | |
| 243 | unsigned m_valueListSeparator : ValueListSeparatorBits; |
| 244 | |
| 245 | private: |
| 246 | unsigned m_classType : ClassTypeBits; // ClassType |
| 247 | |
| 248 | friend class CSSValueList; |
| 249 | }; |
| 250 | |
| 251 | template<typename CSSValueType> |
| 252 | inline bool compareCSSValueVector(const Vector<Ref<CSSValueType>>& firstVector, const Vector<Ref<CSSValueType>>& secondVector) |
| 253 | { |
| 254 | size_t size = firstVector.size(); |
| 255 | if (size != secondVector.size()) |
| 256 | return false; |
| 257 | |
| 258 | for (size_t i = 0; i < size; ++i) { |
| 259 | auto& firstPtr = firstVector[i]; |
| 260 | auto& secondPtr = secondVector[i]; |
| 261 | if (firstPtr.ptr() == secondPtr.ptr() || firstPtr->equals(secondPtr)) |
| 262 | continue; |
| 263 | return false; |
| 264 | } |
| 265 | return true; |
| 266 | } |
| 267 | |
| 268 | template<typename CSSValueType> |
| 269 | inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second) |
| 270 | { |
| 271 | return first ? second && first->equals(*second) : !second; |
| 272 | } |
| 273 | |
| 274 | template<typename CSSValueType> |
| 275 | inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueType>& second) |
| 276 | { |
| 277 | return first.get().equals(second); |
| 278 | } |
| 279 | |
| 280 | typedef HashMap<AtomicString, RefPtr<CSSCustomPropertyValue>> CustomPropertyValueMap; |
| 281 | |
| 282 | } // namespace WebCore |
| 283 | |
| 284 | #define SPECIALIZE_TYPE_TRAITS_CSS_VALUE(ToValueTypeName, predicate) \ |
| 285 | SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \ |
| 286 | static bool isType(const WebCore::CSSValue& value) { return value.predicate; } \ |
| 287 | SPECIALIZE_TYPE_TRAITS_END() |
| 288 | |