Add support for the CSS 'unset' keyword.
[WebKit-https.git] / Source / WebCore / css / CSSValue.h
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 #ifndef CSSValue_h
22 #define CSSValue_h
23
24 #include "ExceptionCode.h"
25 #include "URLHash.h"
26 #include <wtf/ListHashSet.h>
27 #include <wtf/RefCounted.h>
28 #include <wtf/RefPtr.h>
29 #include <wtf/TypeCasts.h>
30
31 namespace WebCore {
32
33 class CachedResource;
34 class StyleSheetContents;
35 enum CSSPropertyID : uint16_t;
36
37 // FIXME: The current CSSValue and subclasses should be turned into internal types (StyleValue).
38 // The few subtypes that are actually exposed in CSSOM can be seen in the cloneForCSSOM() function.
39 // They should be handled by separate wrapper classes.
40
41 // Please don't expose more CSSValue types to the web.
42 class CSSValue : public RefCounted<CSSValue> {
43 public:
44     enum Type {
45         CSS_INHERIT = 0,
46         CSS_PRIMITIVE_VALUE = 1,
47         CSS_VALUE_LIST = 2,
48         CSS_CUSTOM = 3,
49         CSS_INITIAL = 4,
50         CSS_UNSET = 5
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
63     String cssText() const;
64
65     void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented.
66
67     bool isPrimitiveValue() const { return m_classType == PrimitiveClass; }
68     bool isValueList() const { return m_classType >= ValueListClass; }
69     
70     bool isBaseValueList() const { return m_classType == ValueListClass; }
71         
72
73     bool isAspectRatioValue() const { return m_classType == AspectRatioClass; }
74     bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
75     bool isCanvasValue() const { return m_classType == CanvasClass; }
76     bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
77     bool isCursorImageValue() const { return m_classType == CursorImageClass; }
78     bool isCustomPropertyValue() const { return m_classType == CustomPropertyClass; }
79     bool isInvalidCustomPropertyValue() const;
80     bool isVariableDependentValue() const { return m_classType == VariableDependentClass; }
81     bool isVariableValue() const { return m_classType == VariableClass; }
82     bool isFunctionValue() const { return m_classType == FunctionClass; }
83     bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
84     bool isFontFaceSrcValue() const { return m_classType == FontFaceSrcClass; }
85     bool isFontValue() const { return m_classType == FontClass; }
86     bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
87     bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= RadialGradientClass; }
88     bool isNamedImageValue() const { return m_classType == NamedImageClass; }
89 #if ENABLE(CSS_IMAGE_SET)
90     bool isImageSetValue() const { return m_classType == ImageSetClass; }
91 #endif
92     bool isImageValue() const { return m_classType == ImageClass; }
93     bool isImplicitInitialValue() const;
94     bool isInheritedValue() const { return m_classType == InheritedClass; }
95     bool isInitialValue() const { return m_classType == InitialClass; }
96     bool isUnsetValue() const { return m_classType == UnsetClass; }
97     bool treatAsInitialValue(CSSPropertyID) const;
98     bool treatAsInheritedValue(CSSPropertyID) const;
99     bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
100     bool isRadialGradientValue() const { return m_classType == RadialGradientClass; }
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 isWebKitCSSTransformValue() const { return m_classType == WebKitCSSTransformClass; }
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     bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; }
110     bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; }
111 #if ENABLE(CSS_GRID_LAYOUT)
112     bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
113     bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
114 #endif
115     bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; }
116     bool isSVGPaint() const { return m_classType == SVGPaintClass; }
117     bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
118
119 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
120     bool isAnimationTriggerScrollValue() const { return m_classType == AnimationTriggerScrollClass; }
121 #endif
122
123     bool isCSSOMSafe() const { return m_isCSSOMSafe; }
124     bool isSubtypeExposedToCSSOM() const
125     { 
126         return isPrimitiveValue() 
127             || isSVGColor()
128             || isValueList();
129     }
130
131     RefPtr<CSSValue> cloneForCSSOM() const;
132
133     void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
134
135     bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
136
137     bool equals(const CSSValue&) const;
138
139 protected:
140
141     static const size_t ClassTypeBits = 6;
142     enum ClassType {
143         PrimitiveClass,
144
145         // Image classes.
146         ImageClass,
147         CursorImageClass,
148
149         // Image generator classes.
150         CanvasClass,
151         NamedImageClass,
152         CrossfadeClass,
153         FilterImageClass,
154         LinearGradientClass,
155         RadialGradientClass,
156
157         // Timing function classes.
158         CubicBezierTimingFunctionClass,
159         StepsTimingFunctionClass,
160
161         // Other class types.
162         AspectRatioClass,
163         BorderImageSliceClass,
164         FontFeatureClass,
165         FontClass,
166         FontFaceSrcClass,
167         FunctionClass,
168
169         InheritedClass,
170         InitialClass,
171         UnsetClass,
172
173         ReflectClass,
174         ShadowClass,
175         UnicodeRangeClass,
176         LineBoxContainClass,
177         CalculationClass,
178 #if ENABLE(CSS_GRID_LAYOUT)
179         GridTemplateAreasClass,
180 #endif
181         SVGColorClass,
182         SVGPaintClass,
183
184 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
185         AnimationTriggerScrollClass,
186 #endif
187
188         CSSContentDistributionClass,
189         CustomPropertyClass,
190         VariableDependentClass,
191         VariableClass,
192
193         // List class types must appear after ValueListClass.
194         ValueListClass,
195 #if ENABLE(CSS_IMAGE_SET)
196         ImageSetClass,
197 #endif
198         WebKitCSSFilterClass,
199         WebKitCSSTransformClass,
200 #if ENABLE(CSS_GRID_LAYOUT)
201         GridLineNamesClass,
202 #endif
203         // Do not append non-list class types here.
204     };
205
206     static const size_t ValueListSeparatorBits = 2;
207     enum ValueListSeparator {
208         SpaceSeparator,
209         CommaSeparator,
210         SlashSeparator
211     };
212
213     ClassType classType() const { return static_cast<ClassType>(m_classType); }
214
215     explicit CSSValue(ClassType classType, bool isCSSOMSafe = false)
216         : m_isCSSOMSafe(isCSSOMSafe)
217         , m_isTextClone(false)
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() { }
230
231 private:
232     WEBCORE_EXPORT void destroy();
233
234 protected:
235     unsigned m_isCSSOMSafe : 1;
236     unsigned m_isTextClone : 1;
237     // The bits in this section are only used by specific subclasses but kept here
238     // to maximize struct packing.
239
240     // CSSPrimitiveValue bits:
241     unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes
242     mutable unsigned m_hasCachedCSSText : 1;
243     unsigned m_isQuirkValue : 1;
244
245     unsigned m_valueListSeparator : ValueListSeparatorBits;
246
247 private:
248     unsigned m_classType : ClassTypeBits; // ClassType
249     
250 friend class CSSValueList;
251 };
252
253 template<typename CSSValueType>
254 inline bool compareCSSValueVector(const Vector<RefPtr<CSSValueType>>& firstVector, const Vector<RefPtr<CSSValueType>>& secondVector)
255 {
256     size_t size = firstVector.size();
257     if (size != secondVector.size())
258         return false;
259
260     for (size_t i = 0; i < size; i++) {
261         const RefPtr<CSSValueType>& firstPtr = firstVector[i];
262         const RefPtr<CSSValueType>& secondPtr = secondVector[i];
263         if (firstPtr == secondPtr || (firstPtr && secondPtr && firstPtr->equals(*secondPtr)))
264             continue;
265         return false;
266     }
267     return true;
268 }
269
270 template<typename CSSValueType>
271 inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second)
272 {
273     return first ? second && first->equals(*second) : !second;
274 }
275
276 template<typename CSSValueType>
277 inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueType>& second)
278 {
279     return first.get().equals(second);
280 }
281
282 typedef HashMap<AtomicString, RefPtr<CSSValue>> CustomPropertyValueMap;
283
284 } // namespace WebCore
285
286 #define SPECIALIZE_TYPE_TRAITS_CSS_VALUE(ToValueTypeName, predicate) \
287 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
288     static bool isType(const WebCore::CSSValue& value) { return value.predicate; } \
289 SPECIALIZE_TYPE_TRAITS_END()
290
291 #endif // CSSValue_h