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 "CSSValue.h"
29
30#include "CSSAspectRatioValue.h"
31#include "CSSBorderImageSliceValue.h"
32#include "CSSCalculationValue.h"
33#include "CSSCanvasValue.h"
34#include "CSSCrossfadeValue.h"
35#include "CSSCursorImageValue.h"
36#include "CSSFontFaceSrcValue.h"
37#include "CSSFunctionValue.h"
38#include "CSSGradientValue.h"
39#include "CSSImageGeneratorValue.h"
40#include "CSSImageSetValue.h"
41#include "CSSImageValue.h"
42#include "CSSInheritedValue.h"
43#include "CSSInitialValue.h"
44#include "CSSLineBoxContainValue.h"
45#include "CSSPrimitiveValue.h"
46#include "CSSReflectValue.h"
47#include "CSSTimingFunctionValue.h"
48#include "CSSUnicodeRangeValue.h"
49#include "CSSValueList.h"
50#if ENABLE(CSS_VARIABLES)
51#include "CSSVariableValue.h"
52#endif
53#include "FontValue.h"
54#include "FontFeatureValue.h"
55#include "ShadowValue.h"
56#include "SVGColor.h"
57#include "SVGPaint.h"
58#include "WebKitCSSArrayFunctionValue.h"
59#include "WebKitCSSFilterValue.h"
60#include "WebKitCSSMatFunctionValue.h"
61#include "WebKitCSSMixFunctionValue.h"
62#include "WebKitCSSShaderValue.h"
63#include "WebKitCSSTransformValue.h"
64
65#if ENABLE(SVG)
66#include "WebKitCSSSVGDocumentValue.h"
67#endif
68
69namespace WebCore {
70
71struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> {
72    uint32_t bitfields;
73};
74
75COMPILE_ASSERT(sizeof(CSSValue) == sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small);
76
77class TextCloneCSSValue : public CSSValue {
78public:
79    static PassRefPtr<TextCloneCSSValue> create(ClassType classType, const String& text) { return adoptRef(new TextCloneCSSValue(classType, text)); }
80
81    String cssText() const { return m_cssText; }
82
83private:
84    TextCloneCSSValue(ClassType classType, const String& text)
85        : CSSValue(classType, /*isCSSOMSafe*/ true)
86        , m_cssText(text)
87    {
88        m_isTextClone = true;
89    }
90
91    String m_cssText;
92};
93
94bool CSSValue::isImplicitInitialValue() const
95{
96    return m_classType == InitialClass && static_cast<const CSSInitialValue*>(this)->isImplicit();
97}
98
99CSSValue::Type CSSValue::cssValueType() const
100{
101    if (isInheritedValue())
102        return CSS_INHERIT;
103    if (isPrimitiveValue())
104        return CSS_PRIMITIVE_VALUE;
105    if (isValueList())
106        return CSS_VALUE_LIST;
107    if (isInitialValue())
108        return CSS_INITIAL;
109    return CSS_CUSTOM;
110}
111
112void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
113{
114    // This should get called for internal instances only.
115    ASSERT(!isCSSOMSafe());
116
117    if (isPrimitiveValue())
118        static_cast<const CSSPrimitiveValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
119    else if (isValueList())
120        static_cast<const CSSValueList*>(this)->addSubresourceStyleURLs(urls, styleSheet);
121    else if (classType() == FontFaceSrcClass)
122        static_cast<const CSSFontFaceSrcValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
123    else if (classType() == ReflectClass)
124        static_cast<const CSSReflectValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
125}
126
127bool CSSValue::hasFailedOrCanceledSubresources() const
128{
129    // This should get called for internal instances only.
130    ASSERT(!isCSSOMSafe());
131
132    if (isValueList())
133        return static_cast<const CSSValueList*>(this)->hasFailedOrCanceledSubresources();
134    if (classType() == FontFaceSrcClass)
135        return static_cast<const CSSFontFaceSrcValue*>(this)->hasFailedOrCanceledSubresources();
136    if (classType() == ImageClass)
137        return static_cast<const CSSImageValue*>(this)->hasFailedOrCanceledSubresources();
138    if (classType() == CrossfadeClass)
139        return static_cast<const CSSCrossfadeValue*>(this)->hasFailedOrCanceledSubresources();
140#if ENABLE(CSS_IMAGE_SET)
141    if (classType() == ImageSetClass)
142        return static_cast<const CSSImageSetValue*>(this)->hasFailedOrCanceledSubresources();
143#endif
144    return false;
145}
146
147template<class ChildClassType>
148inline static bool compareCSSValues(const CSSValue& first, const CSSValue& second)
149{
150    return static_cast<const ChildClassType&>(first).equals(static_cast<const ChildClassType&>(second));
151}
152
153bool CSSValue::equals(const CSSValue& other) const
154{
155    if (m_isTextClone) {
156        ASSERT(isCSSOMSafe());
157        return static_cast<const TextCloneCSSValue*>(this)->cssText() == other.cssText();
158    }
159
160    if (m_classType == other.m_classType) {
161        switch (m_classType) {
162        case AspectRatioClass:
163            return compareCSSValues<CSSAspectRatioValue>(*this, other);
164        case BorderImageSliceClass:
165            return compareCSSValues<CSSBorderImageSliceValue>(*this, other);
166        case CanvasClass:
167            return compareCSSValues<CSSCanvasValue>(*this, other);
168        case CursorImageClass:
169            return compareCSSValues<CSSCursorImageValue>(*this, other);
170        case FontClass:
171            return compareCSSValues<FontValue>(*this, other);
172        case FontFaceSrcClass:
173            return compareCSSValues<CSSFontFaceSrcValue>(*this, other);
174        case FontFeatureClass:
175            return compareCSSValues<FontFeatureValue>(*this, other);
176        case FunctionClass:
177            return compareCSSValues<CSSFunctionValue>(*this, other);
178        case LinearGradientClass:
179            return compareCSSValues<CSSLinearGradientValue>(*this, other);
180        case RadialGradientClass:
181            return compareCSSValues<CSSRadialGradientValue>(*this, other);
182        case CrossfadeClass:
183            return compareCSSValues<CSSCrossfadeValue>(*this, other);
184        case ImageClass:
185            return compareCSSValues<CSSImageValue>(*this, other);
186        case InheritedClass:
187            return compareCSSValues<CSSInheritedValue>(*this, other);
188        case InitialClass:
189            return compareCSSValues<CSSInitialValue>(*this, other);
190        case PrimitiveClass:
191            return compareCSSValues<CSSPrimitiveValue>(*this, other);
192        case ReflectClass:
193            return compareCSSValues<CSSReflectValue>(*this, other);
194        case ShadowClass:
195            return compareCSSValues<ShadowValue>(*this, other);
196        case LinearTimingFunctionClass:
197            return compareCSSValues<CSSLinearTimingFunctionValue>(*this, other);
198        case CubicBezierTimingFunctionClass:
199            return compareCSSValues<CSSCubicBezierTimingFunctionValue>(*this, other);
200        case StepsTimingFunctionClass:
201            return compareCSSValues<CSSStepsTimingFunctionValue>(*this, other);
202        case UnicodeRangeClass:
203            return compareCSSValues<CSSUnicodeRangeValue>(*this, other);
204        case ValueListClass:
205            return compareCSSValues<CSSValueList>(*this, other);
206        case WebKitCSSTransformClass:
207            return compareCSSValues<WebKitCSSTransformValue>(*this, other);
208        case LineBoxContainClass:
209            return compareCSSValues<CSSLineBoxContainValue>(*this, other);
210        case CalculationClass:
211            return compareCSSValues<CSSCalcValue>(*this, other);
212#if ENABLE(CSS_IMAGE_SET)
213        case ImageSetClass:
214            return compareCSSValues<CSSImageSetValue>(*this, other);
215#endif
216#if ENABLE(CSS_FILTERS)
217        case WebKitCSSFilterClass:
218            return compareCSSValues<WebKitCSSFilterValue>(*this, other);
219#if ENABLE(CSS_SHADERS)
220        case WebKitCSSArrayFunctionValueClass:
221            return compareCSSValues<WebKitCSSArrayFunctionValue>(*this, other);
222        case WebKitCSSMatFunctionValueClass:
223            return compareCSSValues<WebKitCSSMatFunctionValue>(*this, other);
224        case WebKitCSSMixFunctionValueClass:
225            return compareCSSValues<WebKitCSSMixFunctionValue>(*this, other);
226        case WebKitCSSShaderClass:
227            return compareCSSValues<WebKitCSSShaderValue>(*this, other);
228#endif
229#endif
230#if ENABLE(CSS_VARIABLES)
231        case VariableClass:
232            return compareCSSValues<CSSVariableValue>(*this, other);
233#endif
234#if ENABLE(SVG)
235        case SVGColorClass:
236            return compareCSSValues<SVGColor>(*this, other);
237        case SVGPaintClass:
238            return compareCSSValues<SVGPaint>(*this, other);
239        case WebKitCSSSVGDocumentClass:
240            return compareCSSValues<WebKitCSSSVGDocumentValue>(*this, other);
241#endif
242        default:
243            ASSERT_NOT_REACHED();
244            return false;
245        }
246    } else if (m_classType == ValueListClass && other.m_classType != ValueListClass)
247        return static_cast<const CSSValueList*>(this)->equals(other);
248    else if (m_classType != ValueListClass && other.m_classType == ValueListClass)
249        return static_cast<const CSSValueList&>(other).equals(*this);
250    return false;
251}
252
253String CSSValue::cssText() const
254{
255    if (m_isTextClone) {
256         ASSERT(isCSSOMSafe());
257        return static_cast<const TextCloneCSSValue*>(this)->cssText();
258    }
259    ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
260
261    switch (classType()) {
262    case AspectRatioClass:
263        return static_cast<const CSSAspectRatioValue*>(this)->customCssText();
264    case BorderImageSliceClass:
265        return static_cast<const CSSBorderImageSliceValue*>(this)->customCssText();
266    case CanvasClass:
267        return static_cast<const CSSCanvasValue*>(this)->customCssText();
268    case CursorImageClass:
269        return static_cast<const CSSCursorImageValue*>(this)->customCssText();
270    case FontClass:
271        return static_cast<const FontValue*>(this)->customCssText();
272    case FontFaceSrcClass:
273        return static_cast<const CSSFontFaceSrcValue*>(this)->customCssText();
274    case FontFeatureClass:
275        return static_cast<const FontFeatureValue*>(this)->customCssText();
276    case FunctionClass:
277        return static_cast<const CSSFunctionValue*>(this)->customCssText();
278    case LinearGradientClass:
279        return static_cast<const CSSLinearGradientValue*>(this)->customCssText();
280    case RadialGradientClass:
281        return static_cast<const CSSRadialGradientValue*>(this)->customCssText();
282    case CrossfadeClass:
283        return static_cast<const CSSCrossfadeValue*>(this)->customCssText();
284    case ImageClass:
285        return static_cast<const CSSImageValue*>(this)->customCssText();
286    case InheritedClass:
287        return static_cast<const CSSInheritedValue*>(this)->customCssText();
288    case InitialClass:
289        return static_cast<const CSSInitialValue*>(this)->customCssText();
290    case PrimitiveClass:
291        return static_cast<const CSSPrimitiveValue*>(this)->customCssText();
292    case ReflectClass:
293        return static_cast<const CSSReflectValue*>(this)->customCssText();
294    case ShadowClass:
295        return static_cast<const ShadowValue*>(this)->customCssText();
296    case LinearTimingFunctionClass:
297        return static_cast<const CSSLinearTimingFunctionValue*>(this)->customCssText();
298    case CubicBezierTimingFunctionClass:
299        return static_cast<const CSSCubicBezierTimingFunctionValue*>(this)->customCssText();
300    case StepsTimingFunctionClass:
301        return static_cast<const CSSStepsTimingFunctionValue*>(this)->customCssText();
302    case UnicodeRangeClass:
303        return static_cast<const CSSUnicodeRangeValue*>(this)->customCssText();
304    case ValueListClass:
305        return static_cast<const CSSValueList*>(this)->customCssText();
306    case WebKitCSSTransformClass:
307        return static_cast<const WebKitCSSTransformValue*>(this)->customCssText();
308    case LineBoxContainClass:
309        return static_cast<const CSSLineBoxContainValue*>(this)->customCssText();
310    case CalculationClass:
311        return static_cast<const CSSCalcValue*>(this)->customCssText();
312#if ENABLE(CSS_IMAGE_SET)
313    case ImageSetClass:
314        return static_cast<const CSSImageSetValue*>(this)->customCssText();
315#endif
316#if ENABLE(CSS_FILTERS)
317    case WebKitCSSFilterClass:
318        return static_cast<const WebKitCSSFilterValue*>(this)->customCssText();
319#if ENABLE(CSS_SHADERS)
320    case WebKitCSSArrayFunctionValueClass:
321        return static_cast<const WebKitCSSArrayFunctionValue*>(this)->customCssText();
322    case WebKitCSSMatFunctionValueClass:
323        return static_cast<const WebKitCSSMatFunctionValue*>(this)->customCssText();
324    case WebKitCSSMixFunctionValueClass:
325        return static_cast<const WebKitCSSMixFunctionValue*>(this)->customCssText();
326    case WebKitCSSShaderClass:
327        return static_cast<const WebKitCSSShaderValue*>(this)->customCssText();
328#endif
329#endif
330#if ENABLE(CSS_VARIABLES)
331    case VariableClass:
332        return static_cast<const CSSVariableValue*>(this)->value();
333#endif
334#if ENABLE(SVG)
335    case SVGColorClass:
336        return static_cast<const SVGColor*>(this)->customCssText();
337    case SVGPaintClass:
338        return static_cast<const SVGPaint*>(this)->customCssText();
339    case WebKitCSSSVGDocumentClass:
340        return static_cast<const WebKitCSSSVGDocumentValue*>(this)->customCssText();
341#endif
342    }
343    ASSERT_NOT_REACHED();
344    return String();
345}
346
347#if ENABLE(CSS_VARIABLES)
348String CSSValue::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
349{
350    switch (classType()) {
351    case PrimitiveClass:
352        return static_cast<const CSSPrimitiveValue*>(this)->customSerializeResolvingVariables(variables);
353    case ReflectClass:
354        return static_cast<const CSSReflectValue*>(this)->customSerializeResolvingVariables(variables);
355    case ValueListClass:
356        return static_cast<const CSSValueList*>(this)->customSerializeResolvingVariables(variables);
357    case WebKitCSSTransformClass:
358        return static_cast<const WebKitCSSTransformValue*>(this)->customSerializeResolvingVariables(variables);
359    default:
360        return cssText();
361    }
362}
363#endif
364
365void CSSValue::destroy()
366{
367    if (m_isTextClone) {
368        ASSERT(isCSSOMSafe());
369        delete static_cast<TextCloneCSSValue*>(this);
370        return;
371    }
372    ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
373
374    switch (classType()) {
375    case AspectRatioClass:
376        delete static_cast<CSSAspectRatioValue*>(this);
377        return;
378    case BorderImageSliceClass:
379        delete static_cast<CSSBorderImageSliceValue*>(this);
380        return;
381    case CanvasClass:
382        delete static_cast<CSSCanvasValue*>(this);
383        return;
384    case CursorImageClass:
385        delete static_cast<CSSCursorImageValue*>(this);
386        return;
387    case FontClass:
388        delete static_cast<FontValue*>(this);
389        return;
390    case FontFaceSrcClass:
391        delete static_cast<CSSFontFaceSrcValue*>(this);
392        return;
393    case FontFeatureClass:
394        delete static_cast<FontFeatureValue*>(this);
395        return;
396    case FunctionClass:
397        delete static_cast<CSSFunctionValue*>(this);
398        return;
399    case LinearGradientClass:
400        delete static_cast<CSSLinearGradientValue*>(this);
401        return;
402    case RadialGradientClass:
403        delete static_cast<CSSRadialGradientValue*>(this);
404        return;
405    case CrossfadeClass:
406        delete static_cast<CSSCrossfadeValue*>(this);
407        return;
408    case ImageClass:
409        delete static_cast<CSSImageValue*>(this);
410        return;
411    case InheritedClass:
412        delete static_cast<CSSInheritedValue*>(this);
413        return;
414    case InitialClass:
415        delete static_cast<CSSInitialValue*>(this);
416        return;
417    case PrimitiveClass:
418        delete static_cast<CSSPrimitiveValue*>(this);
419        return;
420    case ReflectClass:
421        delete static_cast<CSSReflectValue*>(this);
422        return;
423    case ShadowClass:
424        delete static_cast<ShadowValue*>(this);
425        return;
426    case LinearTimingFunctionClass:
427        delete static_cast<CSSLinearTimingFunctionValue*>(this);
428        return;
429    case CubicBezierTimingFunctionClass:
430        delete static_cast<CSSCubicBezierTimingFunctionValue*>(this);
431        return;
432    case StepsTimingFunctionClass:
433        delete static_cast<CSSStepsTimingFunctionValue*>(this);
434        return;
435    case UnicodeRangeClass:
436        delete static_cast<CSSUnicodeRangeValue*>(this);
437        return;
438    case ValueListClass:
439        delete static_cast<CSSValueList*>(this);
440        return;
441    case WebKitCSSTransformClass:
442        delete static_cast<WebKitCSSTransformValue*>(this);
443        return;
444    case LineBoxContainClass:
445        delete static_cast<CSSLineBoxContainValue*>(this);
446        return;
447    case CalculationClass:
448        delete static_cast<CSSCalcValue*>(this);
449        return;
450#if ENABLE(CSS_IMAGE_SET)
451    case ImageSetClass:
452        delete static_cast<CSSImageSetValue*>(this);
453        return;
454#endif
455#if ENABLE(CSS_FILTERS)
456    case WebKitCSSFilterClass:
457        delete static_cast<WebKitCSSFilterValue*>(this);
458        return;
459#if ENABLE(CSS_SHADERS)
460    case WebKitCSSArrayFunctionValueClass:
461        delete static_cast<WebKitCSSArrayFunctionValue*>(this);
462        return;
463    case WebKitCSSMatFunctionValueClass:
464        delete static_cast<WebKitCSSMatFunctionValue*>(this);
465        return;
466    case WebKitCSSMixFunctionValueClass:
467        delete static_cast<WebKitCSSMixFunctionValue*>(this);
468        return;
469    case WebKitCSSShaderClass:
470        delete static_cast<WebKitCSSShaderValue*>(this);
471        return;
472#endif
473#endif
474#if ENABLE(CSS_VARIABLES)
475    case VariableClass:
476        delete static_cast<CSSVariableValue*>(this);
477        return;
478#endif
479#if ENABLE(SVG)
480    case SVGColorClass:
481        delete static_cast<SVGColor*>(this);
482        return;
483    case SVGPaintClass:
484        delete static_cast<SVGPaint*>(this);
485        return;
486    case WebKitCSSSVGDocumentClass:
487        delete static_cast<WebKitCSSSVGDocumentValue*>(this);
488        return;
489#endif
490    }
491    ASSERT_NOT_REACHED();
492}
493
494PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const
495{
496    switch (classType()) {
497    case PrimitiveClass:
498        return static_cast<const CSSPrimitiveValue*>(this)->cloneForCSSOM();
499    case ValueListClass:
500        return static_cast<const CSSValueList*>(this)->cloneForCSSOM();
501    case ImageClass:
502    case CursorImageClass:
503        return static_cast<const CSSImageValue*>(this)->cloneForCSSOM();
504#if ENABLE(CSS_FILTERS)
505    case WebKitCSSFilterClass:
506        return static_cast<const WebKitCSSFilterValue*>(this)->cloneForCSSOM();
507#if ENABLE(CSS_SHADERS)
508    case WebKitCSSArrayFunctionValueClass:
509        return static_cast<const WebKitCSSArrayFunctionValue*>(this)->cloneForCSSOM();
510    case WebKitCSSMatFunctionValueClass:
511        return static_cast<const WebKitCSSMatFunctionValue*>(this)->cloneForCSSOM();
512    case WebKitCSSMixFunctionValueClass:
513        return static_cast<const WebKitCSSMixFunctionValue*>(this)->cloneForCSSOM();
514#endif
515#endif
516    case WebKitCSSTransformClass:
517        return static_cast<const WebKitCSSTransformValue*>(this)->cloneForCSSOM();
518#if ENABLE(CSS_IMAGE_SET)
519    case ImageSetClass:
520        return static_cast<const CSSImageSetValue*>(this)->cloneForCSSOM();
521#endif
522#if ENABLE(SVG)
523    case SVGColorClass:
524        return static_cast<const SVGColor*>(this)->cloneForCSSOM();
525    case SVGPaintClass:
526        return static_cast<const SVGPaint*>(this)->cloneForCSSOM();
527#endif
528    default:
529        ASSERT(!isSubtypeExposedToCSSOM());
530        return TextCloneCSSValue::create(classType(), cssText());
531    }
532}
533
534}
535