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
31namespace WebCore {
32
33class CSSCustomPropertyValue;
34class CSSStyleDeclaration;
35class CachedResource;
36class DeprecatedCSSOMValue;
37class StyleSheetContents;
38
39enum CSSPropertyID : uint16_t;
40
41class CSSValue : public RefCounted<CSSValue> {
42public:
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
136protected:
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
206public:
207 static const size_t ValueListSeparatorBits = 2;
208 enum ValueListSeparator {
209 SpaceSeparator,
210 CommaSeparator,
211 SlashSeparator
212 };
213
214protected:
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
231private:
232 WEBCORE_EXPORT void destroy();
233
234protected:
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
245private:
246 unsigned m_classType : ClassTypeBits; // ClassType
247
248friend class CSSValueList;
249};
250
251template<typename CSSValueType>
252inline 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
268template<typename CSSValueType>
269inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second)
270{
271 return first ? second && first->equals(*second) : !second;
272}
273
274template<typename CSSValueType>
275inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueType>& second)
276{
277 return first.get().equals(second);
278}
279
280typedef HashMap<AtomicString, RefPtr<CSSCustomPropertyValue>> CustomPropertyValueMap;
281
282} // namespace WebCore
283
284#define SPECIALIZE_TYPE_TRAITS_CSS_VALUE(ToValueTypeName, predicate) \
285SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
286 static bool isType(const WebCore::CSSValue& value) { return value.predicate; } \
287SPECIALIZE_TYPE_TRAITS_END()
288