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
30namespace WebCore {
31
32class StyleSheetContents;
33
34// FIXME: The current CSSValue and subclasses should be turned into internal types (StyleValue).
35// The few subtypes that are actually exposed in CSSOM can be seen in the cloneForCSSOM() function.
36// They should be handled by separate wrapper classes.
37
38// Please don't expose more CSSValue types to the web.
39class CSSValue : public RefCounted<CSSValue> {
40public:
41    enum Type {
42        CSS_INHERIT = 0,
43        CSS_PRIMITIVE_VALUE = 1,
44        CSS_VALUE_LIST = 2,
45        CSS_CUSTOM = 3,
46        CSS_INITIAL = 4
47
48    };
49
50    // Override RefCounted's deref() to ensure operator delete is called on
51    // the appropriate subclass type.
52    void deref()
53    {
54        if (derefBase())
55            destroy();
56    }
57
58    Type cssValueType() const;
59
60    String cssText() const;
61    void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented.
62
63    bool isPrimitiveValue() const { return m_classType == PrimitiveClass; }
64    bool isValueList() const { return m_classType >= ValueListClass; }
65
66    bool isBaseValueList() const { return m_classType == ValueListClass; }
67
68
69    bool isAspectRatioValue() const { return m_classType == AspectRatioClass; }
70    bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
71    bool isCanvasValue() const { return m_classType == CanvasClass; }
72    bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
73    bool isCursorImageValue() const { return m_classType == CursorImageClass; }
74    bool isFunctionValue() const { return m_classType == FunctionClass; }
75    bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
76    bool isFontFaceSrcValue() const { return m_classType == FontFaceSrcClass; }
77    bool isFontValue() const { return m_classType == FontClass; }
78    bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
79    bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= RadialGradientClass; }
80#if ENABLE(CSS_IMAGE_SET)
81    bool isImageSetValue() const { return m_classType == ImageSetClass; }
82#endif
83    bool isImageValue() const { return m_classType == ImageClass; }
84    bool isImplicitInitialValue() const;
85    bool isInheritedValue() const { return m_classType == InheritedClass; }
86    bool isInitialValue() const { return m_classType == InitialClass; }
87    bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
88    bool isRadialGradientValue() const { return m_classType == RadialGradientClass; }
89    bool isReflectValue() const { return m_classType == ReflectClass; }
90    bool isShadowValue() const { return m_classType == ShadowClass; }
91    bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; }
92    bool isStepsTimingFunctionValue() const { return m_classType == StepsTimingFunctionClass; }
93    bool isWebKitCSSTransformValue() const { return m_classType == WebKitCSSTransformClass; }
94    bool isLineBoxContainValue() const { return m_classType == LineBoxContainClass; }
95    bool isCalcValue() const {return m_classType == CalculationClass; }
96#if ENABLE(CSS_FILTERS)
97    bool isFilterImageValue() const { return m_classType == FilterImageClass; }
98    bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; }
99#endif // ENABLE(CSS_FILTERS)
100#if ENABLE(CSS_GRID_LAYOUT)
101    bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
102    bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
103#endif
104    bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; }
105    bool isSVGPaint() const { return m_classType == SVGPaintClass; }
106    bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
107
108    bool isCSSOMSafe() const { return m_isCSSOMSafe; }
109    bool isSubtypeExposedToCSSOM() const
110    {
111        return isPrimitiveValue()
112            || isSVGColor()
113            || isValueList();
114    }
115
116    PassRefPtr<CSSValue> cloneForCSSOM() const;
117
118    void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
119
120    bool hasFailedOrCanceledSubresources() const;
121
122    bool equals(const CSSValue&) const;
123
124protected:
125
126    static const size_t ClassTypeBits = 6;
127    enum ClassType {
128        PrimitiveClass,
129
130        // Image classes.
131        ImageClass,
132        CursorImageClass,
133
134        // Image generator classes.
135        CanvasClass,
136        CrossfadeClass,
137#if ENABLE(CSS_FILTERS)
138        FilterImageClass,
139#endif
140        LinearGradientClass,
141        RadialGradientClass,
142
143        // Timing function classes.
144        CubicBezierTimingFunctionClass,
145        StepsTimingFunctionClass,
146
147        // Other class types.
148        AspectRatioClass,
149        BorderImageSliceClass,
150        FontFeatureClass,
151        FontClass,
152        FontFaceSrcClass,
153        FunctionClass,
154
155        InheritedClass,
156        InitialClass,
157
158        ReflectClass,
159        ShadowClass,
160        UnicodeRangeClass,
161        LineBoxContainClass,
162        CalculationClass,
163#if ENABLE(CSS_GRID_LAYOUT)
164        GridTemplateAreasClass,
165#endif
166        SVGColorClass,
167        SVGPaintClass,
168
169        // List class types must appear after ValueListClass.
170        ValueListClass,
171#if ENABLE(CSS_IMAGE_SET)
172        ImageSetClass,
173#endif
174#if ENABLE(CSS_FILTERS)
175        WebKitCSSFilterClass,
176#endif
177        WebKitCSSTransformClass,
178#if ENABLE(CSS_GRID_LAYOUT)
179        GridLineNamesClass,
180#endif
181        // Do not append non-list class types here.
182    };
183
184    static const size_t ValueListSeparatorBits = 2;
185    enum ValueListSeparator {
186        SpaceSeparator,
187        CommaSeparator,
188        SlashSeparator
189    };
190
191    ClassType classType() const { return static_cast<ClassType>(m_classType); }
192
193    explicit CSSValue(ClassType classType, bool isCSSOMSafe = false)
194        : m_isCSSOMSafe(isCSSOMSafe)
195        , m_isTextClone(false)
196        , m_primitiveUnitType(0)
197        , m_hasCachedCSSText(false)
198        , m_isQuirkValue(false)
199        , m_valueListSeparator(SpaceSeparator)
200        , m_classType(classType)
201    {
202    }
203
204    // NOTE: This class is non-virtual for memory and performance reasons.
205    // Don't go making it virtual again unless you know exactly what you're doing!
206
207    ~CSSValue() { }
208
209private:
210    void destroy();
211
212protected:
213    unsigned m_isCSSOMSafe : 1;
214    unsigned m_isTextClone : 1;
215    // The bits in this section are only used by specific subclasses but kept here
216    // to maximize struct packing.
217
218    // CSSPrimitiveValue bits:
219    unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes
220    mutable unsigned m_hasCachedCSSText : 1;
221    unsigned m_isQuirkValue : 1;
222
223    unsigned m_valueListSeparator : ValueListSeparatorBits;
224
225private:
226    unsigned m_classType : ClassTypeBits; // ClassType
227};
228
229template<typename CSSValueType>
230inline bool compareCSSValueVector(const Vector<RefPtr<CSSValueType>>& firstVector, const Vector<RefPtr<CSSValueType>>& secondVector)
231{
232    size_t size = firstVector.size();
233    if (size != secondVector.size())
234        return false;
235
236    for (size_t i = 0; i < size; i++) {
237        const RefPtr<CSSValueType>& firstPtr = firstVector[i];
238        const RefPtr<CSSValueType>& secondPtr = secondVector[i];
239        if (firstPtr == secondPtr || (firstPtr && secondPtr && firstPtr->equals(*secondPtr)))
240            continue;
241        return false;
242    }
243    return true;
244}
245
246template<typename CSSValueType>
247inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second)
248{
249    return first ? second && first->equals(*second) : !second;
250}
251
252template<typename CSSValueType>
253inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueType>& second)
254{
255    return first.get().equals(second.get());
256}
257
258#define CSS_VALUE_TYPE_CASTS(ToValueTypeName, predicate) \
259    TYPE_CASTS_BASE(ToValueTypeName, CSSValue, value, value->predicate, value.predicate)
260
261} // namespace WebCore
262
263#endif // CSSValue_h
264