1/*
2 * Copyright (C) 2011 Andreas Kling (kling@webkit.org)
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27#include "config.h"
28#include "core/css/CSSValue.h"
29
30#include "core/css/CSSArrayFunctionValue.h"
31#include "core/css/CSSAspectRatioValue.h"
32#include "core/css/CSSBorderImageSliceValue.h"
33#include "core/css/CSSCalculationValue.h"
34#include "core/css/CSSCanvasValue.h"
35#include "core/css/CSSCrossfadeValue.h"
36#include "core/css/CSSCursorImageValue.h"
37#include "core/css/CSSFilterValue.h"
38#include "core/css/CSSFontFaceSrcValue.h"
39#include "core/css/CSSFunctionValue.h"
40#include "core/css/CSSGradientValue.h"
41#include "core/css/CSSGridTemplateValue.h"
42#include "core/css/CSSImageSetValue.h"
43#include "core/css/CSSImageValue.h"
44#include "core/css/CSSInheritedValue.h"
45#include "core/css/CSSInitialValue.h"
46#include "core/css/CSSLineBoxContainValue.h"
47#include "core/css/CSSMixFunctionValue.h"
48#include "core/css/CSSPrimitiveValue.h"
49#include "core/css/CSSReflectValue.h"
50#include "core/css/CSSSVGDocumentValue.h"
51#include "core/css/CSSShaderValue.h"
52#include "core/css/CSSTimingFunctionValue.h"
53#include "core/css/CSSTransformValue.h"
54#include "core/css/CSSUnicodeRangeValue.h"
55#include "core/css/CSSValueList.h"
56#include "core/css/CSSVariableValue.h"
57#include "core/css/FontFeatureValue.h"
58#include "core/css/FontValue.h"
59#include "core/css/ShadowValue.h"
60#include "core/svg/SVGColor.h"
61#include "core/svg/SVGPaint.h"
62
63namespace WebCore {
64
65struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> {
66    uint32_t bitfields;
67};
68
69COMPILE_ASSERT(sizeof(CSSValue) == sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small);
70
71class TextCloneCSSValue : public CSSValue {
72public:
73    static PassRefPtr<TextCloneCSSValue> create(ClassType classType, const String& text) { return adoptRef(new TextCloneCSSValue(classType, text)); }
74
75    String cssText() const { return m_cssText; }
76
77private:
78    TextCloneCSSValue(ClassType classType, const String& text)
79        : CSSValue(classType, /*isCSSOMSafe*/ true)
80        , m_cssText(text)
81    {
82        m_isTextClone = true;
83    }
84
85    String m_cssText;
86};
87
88bool CSSValue::isImplicitInitialValue() const
89{
90    return m_classType == InitialClass && static_cast<const CSSInitialValue*>(this)->isImplicit();
91}
92
93CSSValue::Type CSSValue::cssValueType() const
94{
95    if (isInheritedValue())
96        return CSS_INHERIT;
97    if (isPrimitiveValue())
98        return CSS_PRIMITIVE_VALUE;
99    if (isValueList())
100        return CSS_VALUE_LIST;
101    if (isInitialValue())
102        return CSS_INITIAL;
103    return CSS_CUSTOM;
104}
105
106void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
107{
108    // This should get called for internal instances only.
109    ASSERT(!isCSSOMSafe());
110
111    if (isPrimitiveValue())
112        toCSSPrimitiveValue(this)->addSubresourceStyleURLs(urls, styleSheet);
113    else if (isValueList())
114        toCSSValueList(this)->addSubresourceStyleURLs(urls, styleSheet);
115    else if (classType() == FontFaceSrcClass)
116        static_cast<const CSSFontFaceSrcValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
117    else if (classType() == ReflectClass)
118        static_cast<const CSSReflectValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
119}
120
121bool CSSValue::hasFailedOrCanceledSubresources() const
122{
123    // This should get called for internal instances only.
124    ASSERT(!isCSSOMSafe());
125
126    if (isValueList())
127        return toCSSValueList(this)->hasFailedOrCanceledSubresources();
128    if (classType() == FontFaceSrcClass)
129        return static_cast<const CSSFontFaceSrcValue*>(this)->hasFailedOrCanceledSubresources();
130    if (classType() == ImageClass)
131        return toCSSImageValue(this)->hasFailedOrCanceledSubresources();
132    if (classType() == CrossfadeClass)
133        return static_cast<const CSSCrossfadeValue*>(this)->hasFailedOrCanceledSubresources();
134    if (classType() == ImageSetClass)
135        return static_cast<const CSSImageSetValue*>(this)->hasFailedOrCanceledSubresources();
136
137    return false;
138}
139
140template<class ChildClassType>
141inline static bool compareCSSValues(const CSSValue& first, const CSSValue& second)
142{
143    return static_cast<const ChildClassType&>(first).equals(static_cast<const ChildClassType&>(second));
144}
145
146bool CSSValue::equals(const CSSValue& other) const
147{
148    if (m_isTextClone) {
149        ASSERT(isCSSOMSafe());
150        return static_cast<const TextCloneCSSValue*>(this)->cssText() == other.cssText();
151    }
152
153    if (m_classType == other.m_classType) {
154        switch (m_classType) {
155        case AspectRatioClass:
156            return compareCSSValues<CSSAspectRatioValue>(*this, other);
157        case BorderImageSliceClass:
158            return compareCSSValues<CSSBorderImageSliceValue>(*this, other);
159        case CanvasClass:
160            return compareCSSValues<CSSCanvasValue>(*this, other);
161        case CursorImageClass:
162            return compareCSSValues<CSSCursorImageValue>(*this, other);
163        case FontClass:
164            return compareCSSValues<FontValue>(*this, other);
165        case FontFaceSrcClass:
166            return compareCSSValues<CSSFontFaceSrcValue>(*this, other);
167        case FontFeatureClass:
168            return compareCSSValues<FontFeatureValue>(*this, other);
169        case FunctionClass:
170            return compareCSSValues<CSSFunctionValue>(*this, other);
171        case LinearGradientClass:
172            return compareCSSValues<CSSLinearGradientValue>(*this, other);
173        case RadialGradientClass:
174            return compareCSSValues<CSSRadialGradientValue>(*this, other);
175        case CrossfadeClass:
176            return compareCSSValues<CSSCrossfadeValue>(*this, other);
177        case ImageClass:
178            return compareCSSValues<CSSImageValue>(*this, other);
179        case InheritedClass:
180            return compareCSSValues<CSSInheritedValue>(*this, other);
181        case InitialClass:
182            return compareCSSValues<CSSInitialValue>(*this, other);
183        case GridTemplateClass:
184            return compareCSSValues<CSSGridTemplateValue>(*this, other);
185        case PrimitiveClass:
186            return compareCSSValues<CSSPrimitiveValue>(*this, other);
187        case ReflectClass:
188            return compareCSSValues<CSSReflectValue>(*this, other);
189        case ShadowClass:
190            return compareCSSValues<ShadowValue>(*this, other);
191        case LinearTimingFunctionClass:
192            return compareCSSValues<CSSLinearTimingFunctionValue>(*this, other);
193        case CubicBezierTimingFunctionClass:
194            return compareCSSValues<CSSCubicBezierTimingFunctionValue>(*this, other);
195        case StepsTimingFunctionClass:
196            return compareCSSValues<CSSStepsTimingFunctionValue>(*this, other);
197        case UnicodeRangeClass:
198            return compareCSSValues<CSSUnicodeRangeValue>(*this, other);
199        case ValueListClass:
200            return compareCSSValues<CSSValueList>(*this, other);
201        case CSSTransformClass:
202            return compareCSSValues<CSSTransformValue>(*this, other);
203        case LineBoxContainClass:
204            return compareCSSValues<CSSLineBoxContainValue>(*this, other);
205        case CalculationClass:
206            return compareCSSValues<CSSCalcValue>(*this, other);
207        case ImageSetClass:
208            return compareCSSValues<CSSImageSetValue>(*this, other);
209        case CSSFilterClass:
210            return compareCSSValues<CSSFilterValue>(*this, other);
211        case CSSArrayFunctionValueClass:
212            return compareCSSValues<CSSArrayFunctionValue>(*this, other);
213        case CSSMixFunctionValueClass:
214            return compareCSSValues<CSSMixFunctionValue>(*this, other);
215        case CSSShaderClass:
216            return compareCSSValues<CSSShaderValue>(*this, other);
217        case VariableClass:
218            return compareCSSValues<CSSVariableValue>(*this, other);
219        case SVGColorClass:
220            return compareCSSValues<SVGColor>(*this, other);
221        case SVGPaintClass:
222            return compareCSSValues<SVGPaint>(*this, other);
223        case CSSSVGDocumentClass:
224            return compareCSSValues<CSSSVGDocumentValue>(*this, other);
225        default:
226            ASSERT_NOT_REACHED();
227            return false;
228        }
229    } else if (m_classType == ValueListClass && other.m_classType != ValueListClass)
230        return toCSSValueList(this)->equals(other);
231    else if (m_classType != ValueListClass && other.m_classType == ValueListClass)
232        return static_cast<const CSSValueList&>(other).equals(*this);
233    return false;
234}
235
236String CSSValue::cssText() const
237{
238    if (m_isTextClone) {
239         ASSERT(isCSSOMSafe());
240        return static_cast<const TextCloneCSSValue*>(this)->cssText();
241    }
242    ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
243
244    switch (classType()) {
245    case AspectRatioClass:
246        return static_cast<const CSSAspectRatioValue*>(this)->customCssText();
247    case BorderImageSliceClass:
248        return static_cast<const CSSBorderImageSliceValue*>(this)->customCssText();
249    case CanvasClass:
250        return static_cast<const CSSCanvasValue*>(this)->customCssText();
251    case CursorImageClass:
252        return static_cast<const CSSCursorImageValue*>(this)->customCssText();
253    case FontClass:
254        return static_cast<const FontValue*>(this)->customCssText();
255    case FontFaceSrcClass:
256        return static_cast<const CSSFontFaceSrcValue*>(this)->customCssText();
257    case FontFeatureClass:
258        return static_cast<const FontFeatureValue*>(this)->customCssText();
259    case FunctionClass:
260        return static_cast<const CSSFunctionValue*>(this)->customCssText();
261    case LinearGradientClass:
262        return static_cast<const CSSLinearGradientValue*>(this)->customCssText();
263    case RadialGradientClass:
264        return static_cast<const CSSRadialGradientValue*>(this)->customCssText();
265    case CrossfadeClass:
266        return static_cast<const CSSCrossfadeValue*>(this)->customCssText();
267    case ImageClass:
268        return toCSSImageValue(this)->customCssText();
269    case InheritedClass:
270        return static_cast<const CSSInheritedValue*>(this)->customCssText();
271    case InitialClass:
272        return static_cast<const CSSInitialValue*>(this)->customCssText();
273    case GridTemplateClass:
274        return static_cast<const CSSGridTemplateValue*>(this)->customCssText();
275    case PrimitiveClass:
276        return toCSSPrimitiveValue(this)->customCssText();
277    case ReflectClass:
278        return static_cast<const CSSReflectValue*>(this)->customCssText();
279    case ShadowClass:
280        return static_cast<const ShadowValue*>(this)->customCssText();
281    case LinearTimingFunctionClass:
282        return static_cast<const CSSLinearTimingFunctionValue*>(this)->customCssText();
283    case CubicBezierTimingFunctionClass:
284        return static_cast<const CSSCubicBezierTimingFunctionValue*>(this)->customCssText();
285    case StepsTimingFunctionClass:
286        return static_cast<const CSSStepsTimingFunctionValue*>(this)->customCssText();
287    case UnicodeRangeClass:
288        return static_cast<const CSSUnicodeRangeValue*>(this)->customCssText();
289    case ValueListClass:
290        return toCSSValueList(this)->customCssText();
291    case CSSTransformClass:
292        return static_cast<const CSSTransformValue*>(this)->customCssText();
293    case LineBoxContainClass:
294        return static_cast<const CSSLineBoxContainValue*>(this)->customCssText();
295    case CalculationClass:
296        return static_cast<const CSSCalcValue*>(this)->customCssText();
297    case ImageSetClass:
298        return static_cast<const CSSImageSetValue*>(this)->customCssText();
299    case CSSFilterClass:
300        return static_cast<const CSSFilterValue*>(this)->customCssText();
301    case CSSArrayFunctionValueClass:
302        return static_cast<const CSSArrayFunctionValue*>(this)->customCssText();
303    case CSSMixFunctionValueClass:
304        return static_cast<const CSSMixFunctionValue*>(this)->customCssText();
305    case CSSShaderClass:
306        return static_cast<const CSSShaderValue*>(this)->customCssText();
307    case VariableClass:
308        return toCSSVariableValue(this)->value();
309    case SVGColorClass:
310        return static_cast<const SVGColor*>(this)->customCssText();
311    case SVGPaintClass:
312        return static_cast<const SVGPaint*>(this)->customCssText();
313    case CSSSVGDocumentClass:
314        return static_cast<const CSSSVGDocumentValue*>(this)->customCssText();
315    }
316    ASSERT_NOT_REACHED();
317    return String();
318}
319
320String CSSValue::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
321{
322    switch (classType()) {
323    case PrimitiveClass:
324        return toCSSPrimitiveValue(this)->customSerializeResolvingVariables(variables);
325    case ReflectClass:
326        return static_cast<const CSSReflectValue*>(this)->customSerializeResolvingVariables(variables);
327    case ValueListClass:
328        return toCSSValueList(this)->customSerializeResolvingVariables(variables);
329    case CSSTransformClass:
330        return static_cast<const CSSTransformValue*>(this)->customSerializeResolvingVariables(variables);
331    default:
332        return cssText();
333    }
334}
335
336void CSSValue::destroy()
337{
338    if (m_isTextClone) {
339        ASSERT(isCSSOMSafe());
340        delete static_cast<TextCloneCSSValue*>(this);
341        return;
342    }
343    ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
344
345    switch (classType()) {
346    case AspectRatioClass:
347        delete static_cast<CSSAspectRatioValue*>(this);
348        return;
349    case BorderImageSliceClass:
350        delete static_cast<CSSBorderImageSliceValue*>(this);
351        return;
352    case CanvasClass:
353        delete static_cast<CSSCanvasValue*>(this);
354        return;
355    case CursorImageClass:
356        delete static_cast<CSSCursorImageValue*>(this);
357        return;
358    case FontClass:
359        delete static_cast<FontValue*>(this);
360        return;
361    case FontFaceSrcClass:
362        delete static_cast<CSSFontFaceSrcValue*>(this);
363        return;
364    case FontFeatureClass:
365        delete static_cast<FontFeatureValue*>(this);
366        return;
367    case FunctionClass:
368        delete static_cast<CSSFunctionValue*>(this);
369        return;
370    case LinearGradientClass:
371        delete static_cast<CSSLinearGradientValue*>(this);
372        return;
373    case RadialGradientClass:
374        delete static_cast<CSSRadialGradientValue*>(this);
375        return;
376    case CrossfadeClass:
377        delete static_cast<CSSCrossfadeValue*>(this);
378        return;
379    case ImageClass:
380        delete toCSSImageValue(this);
381        return;
382    case InheritedClass:
383        delete static_cast<CSSInheritedValue*>(this);
384        return;
385    case InitialClass:
386        delete static_cast<CSSInitialValue*>(this);
387        return;
388    case GridTemplateClass:
389        delete static_cast<CSSGridTemplateValue*>(this);
390        return;
391    case PrimitiveClass:
392        delete toCSSPrimitiveValue(this);
393        return;
394    case ReflectClass:
395        delete static_cast<CSSReflectValue*>(this);
396        return;
397    case ShadowClass:
398        delete static_cast<ShadowValue*>(this);
399        return;
400    case LinearTimingFunctionClass:
401        delete static_cast<CSSLinearTimingFunctionValue*>(this);
402        return;
403    case CubicBezierTimingFunctionClass:
404        delete static_cast<CSSCubicBezierTimingFunctionValue*>(this);
405        return;
406    case StepsTimingFunctionClass:
407        delete static_cast<CSSStepsTimingFunctionValue*>(this);
408        return;
409    case UnicodeRangeClass:
410        delete static_cast<CSSUnicodeRangeValue*>(this);
411        return;
412    case ValueListClass:
413        delete toCSSValueList(this);
414        return;
415    case CSSTransformClass:
416        delete static_cast<CSSTransformValue*>(this);
417        return;
418    case LineBoxContainClass:
419        delete static_cast<CSSLineBoxContainValue*>(this);
420        return;
421    case CalculationClass:
422        delete static_cast<CSSCalcValue*>(this);
423        return;
424    case ImageSetClass:
425        delete static_cast<CSSImageSetValue*>(this);
426        return;
427    case CSSFilterClass:
428        delete static_cast<CSSFilterValue*>(this);
429        return;
430    case CSSArrayFunctionValueClass:
431        delete static_cast<CSSArrayFunctionValue*>(this);
432        return;
433    case CSSMixFunctionValueClass:
434        delete static_cast<CSSMixFunctionValue*>(this);
435        return;
436    case CSSShaderClass:
437        delete static_cast<CSSShaderValue*>(this);
438        return;
439    case VariableClass:
440        delete toCSSVariableValue(this);
441        return;
442    case SVGColorClass:
443        delete static_cast<SVGColor*>(this);
444        return;
445    case SVGPaintClass:
446        delete static_cast<SVGPaint*>(this);
447        return;
448    case CSSSVGDocumentClass:
449        delete static_cast<CSSSVGDocumentValue*>(this);
450        return;
451    }
452    ASSERT_NOT_REACHED();
453}
454
455PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const
456{
457    switch (classType()) {
458    case PrimitiveClass:
459        return toCSSPrimitiveValue(this)->cloneForCSSOM();
460    case ValueListClass:
461        return toCSSValueList(this)->cloneForCSSOM();
462    case ImageClass:
463    case CursorImageClass:
464        return toCSSImageValue(this)->cloneForCSSOM();
465    case CSSFilterClass:
466        return static_cast<const CSSFilterValue*>(this)->cloneForCSSOM();
467    case CSSArrayFunctionValueClass:
468        return static_cast<const CSSArrayFunctionValue*>(this)->cloneForCSSOM();
469    case CSSMixFunctionValueClass:
470        return static_cast<const CSSMixFunctionValue*>(this)->cloneForCSSOM();
471    case CSSTransformClass:
472        return static_cast<const CSSTransformValue*>(this)->cloneForCSSOM();
473    case ImageSetClass:
474        return static_cast<const CSSImageSetValue*>(this)->cloneForCSSOM();
475    case SVGColorClass:
476        return static_cast<const SVGColor*>(this)->cloneForCSSOM();
477    case SVGPaintClass:
478        return static_cast<const SVGPaint*>(this)->cloneForCSSOM();
479    default:
480        ASSERT(!isSubtypeExposedToCSSOM());
481        return TextCloneCSSValue::create(classType(), cssText());
482    }
483}
484
485}
486