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