/* * Copyright (C) 2011 Andreas Kling (kling@webkit.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "config.h" #include "core/css/CSSValue.h" #include "core/css/CSSAspectRatioValue.h" #include "core/css/CSSBorderImageSliceValue.h" #include "core/css/CSSCalculationValue.h" #include "core/css/CSSCanvasValue.h" #include "core/css/CSSCrossfadeValue.h" #include "core/css/CSSCursorImageValue.h" #include "core/css/CSSFilterValue.h" #include "core/css/CSSFontFaceSrcValue.h" #include "core/css/CSSFontFeatureValue.h" #include "core/css/CSSFontValue.h" #include "core/css/CSSFunctionValue.h" #include "core/css/CSSGradientValue.h" #include "core/css/CSSImageSetValue.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSInheritedValue.h" #include "core/css/CSSInitialValue.h" #include "core/css/CSSLineBoxContainValue.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSShadowValue.h" #include "core/css/CSSTimingFunctionValue.h" #include "core/css/CSSTransformValue.h" #include "core/css/CSSUnicodeRangeValue.h" #include "core/css/CSSValueList.h" namespace blink { struct SameSizeAsCSSValue : public RefCounted { uint32_t bitfields; }; COMPILE_ASSERT(sizeof(CSSValue) <= sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small); class TextCloneCSSValue : public CSSValue { public: static PassRefPtr create(ClassType classType, const String& text) { return adoptRef(new TextCloneCSSValue(classType, text)); } String cssText() const { return m_cssText; } private: TextCloneCSSValue(ClassType classType, const String& text) : CSSValue(classType, /*isCSSOMSafe*/ true) , m_cssText(text) { m_isTextClone = true; } String m_cssText; }; DEFINE_CSS_VALUE_TYPE_CASTS(TextCloneCSSValue, isTextCloneCSSValue()); bool CSSValue::isImplicitInitialValue() const { return m_classType == InitialClass && toCSSInitialValue(this)->isImplicit(); } CSSValue::Type CSSValue::cssValueType() const { if (isInheritedValue()) return CSS_INHERIT; if (isPrimitiveValue()) return CSS_PRIMITIVE_VALUE; if (isValueList()) return CSS_VALUE_LIST; if (isInitialValue()) return CSS_INITIAL; return CSS_CUSTOM; } bool CSSValue::hasFailedOrCanceledSubresources() const { // This should get called for internal instances only. ASSERT(!isCSSOMSafe()); if (isValueList()) return toCSSValueList(this)->hasFailedOrCanceledSubresources(); if (classType() == FontFaceSrcClass) return toCSSFontFaceSrcValue(this)->hasFailedOrCanceledSubresources(); if (classType() == ImageClass) return toCSSImageValue(this)->hasFailedOrCanceledSubresources(); if (classType() == CrossfadeClass) return toCSSCrossfadeValue(this)->hasFailedOrCanceledSubresources(); if (classType() == ImageSetClass) return toCSSImageSetValue(this)->hasFailedOrCanceledSubresources(); return false; } template inline static bool compareCSSValues(const CSSValue& first, const CSSValue& second) { return static_cast(first).equals(static_cast(second)); } bool CSSValue::equals(const CSSValue& other) const { if (m_isTextClone) { ASSERT(isCSSOMSafe()); return toTextCloneCSSValue(this)->cssText() == other.cssText(); } if (m_classType == other.m_classType) { switch (m_classType) { case AspectRatioClass: return compareCSSValues(*this, other); case BorderImageSliceClass: return compareCSSValues(*this, other); case CanvasClass: return compareCSSValues(*this, other); case CursorImageClass: return compareCSSValues(*this, other); case FontClass: return compareCSSValues(*this, other); case FontFaceSrcClass: return compareCSSValues(*this, other); case FontFeatureClass: return compareCSSValues(*this, other); case FunctionClass: return compareCSSValues(*this, other); case LinearGradientClass: return compareCSSValues(*this, other); case RadialGradientClass: return compareCSSValues(*this, other); case CrossfadeClass: return compareCSSValues(*this, other); case ImageClass: return compareCSSValues(*this, other); case InheritedClass: return compareCSSValues(*this, other); case InitialClass: return compareCSSValues(*this, other); case PrimitiveClass: return compareCSSValues(*this, other); case ShadowClass: return compareCSSValues(*this, other); case CubicBezierTimingFunctionClass: return compareCSSValues(*this, other); case StepsTimingFunctionClass: return compareCSSValues(*this, other); case UnicodeRangeClass: return compareCSSValues(*this, other); case ValueListClass: return compareCSSValues(*this, other); case CSSTransformClass: return compareCSSValues(*this, other); case LineBoxContainClass: return compareCSSValues(*this, other); case CalculationClass: return compareCSSValues(*this, other); case ImageSetClass: return compareCSSValues(*this, other); case CSSFilterClass: return compareCSSValues(*this, other); default: ASSERT_NOT_REACHED(); return false; } } else if (m_classType == ValueListClass && other.m_classType != ValueListClass) return toCSSValueList(this)->equals(other); else if (m_classType != ValueListClass && other.m_classType == ValueListClass) return static_cast(other).equals(*this); return false; } String CSSValue::cssText() const { if (m_isTextClone) { ASSERT(isCSSOMSafe()); return toTextCloneCSSValue(this)->cssText(); } ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM()); switch (classType()) { case AspectRatioClass: return toCSSAspectRatioValue(this)->customCSSText(); case BorderImageSliceClass: return toCSSBorderImageSliceValue(this)->customCSSText(); case CanvasClass: return toCSSCanvasValue(this)->customCSSText(); case CursorImageClass: return toCSSCursorImageValue(this)->customCSSText(); case FontClass: return toCSSFontValue(this)->customCSSText(); case FontFaceSrcClass: return toCSSFontFaceSrcValue(this)->customCSSText(); case FontFeatureClass: return toCSSFontFeatureValue(this)->customCSSText(); case FunctionClass: return toCSSFunctionValue(this)->customCSSText(); case LinearGradientClass: return toCSSLinearGradientValue(this)->customCSSText(); case RadialGradientClass: return toCSSRadialGradientValue(this)->customCSSText(); case CrossfadeClass: return toCSSCrossfadeValue(this)->customCSSText(); case ImageClass: return toCSSImageValue(this)->customCSSText(); case InheritedClass: return toCSSInheritedValue(this)->customCSSText(); case InitialClass: return toCSSInitialValue(this)->customCSSText(); case PrimitiveClass: return toCSSPrimitiveValue(this)->customCSSText(); case ShadowClass: return toCSSShadowValue(this)->customCSSText(); case CubicBezierTimingFunctionClass: return toCSSCubicBezierTimingFunctionValue(this)->customCSSText(); case StepsTimingFunctionClass: return toCSSStepsTimingFunctionValue(this)->customCSSText(); case UnicodeRangeClass: return toCSSUnicodeRangeValue(this)->customCSSText(); case ValueListClass: return toCSSValueList(this)->customCSSText(); case CSSTransformClass: return toCSSTransformValue(this)->customCSSText(); case LineBoxContainClass: return toCSSLineBoxContainValue(this)->customCSSText(); case CalculationClass: return toCSSCalcValue(this)->customCSSText(); case ImageSetClass: return toCSSImageSetValue(this)->customCSSText(); case CSSFilterClass: return toCSSFilterValue(this)->customCSSText(); } ASSERT_NOT_REACHED(); return String(); } void CSSValue::destroy() { if (m_isTextClone) { ASSERT(isCSSOMSafe()); delete toTextCloneCSSValue(this); return; } ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM()); switch (classType()) { case AspectRatioClass: delete toCSSAspectRatioValue(this); return; case BorderImageSliceClass: delete toCSSBorderImageSliceValue(this); return; case CanvasClass: delete toCSSCanvasValue(this); return; case CursorImageClass: delete toCSSCursorImageValue(this); return; case FontClass: delete toCSSFontValue(this); return; case FontFaceSrcClass: delete toCSSFontFaceSrcValue(this); return; case FontFeatureClass: delete toCSSFontFeatureValue(this); return; case FunctionClass: delete toCSSFunctionValue(this); return; case LinearGradientClass: delete toCSSLinearGradientValue(this); return; case RadialGradientClass: delete toCSSRadialGradientValue(this); return; case CrossfadeClass: delete toCSSCrossfadeValue(this); return; case ImageClass: delete toCSSImageValue(this); return; case InheritedClass: delete toCSSInheritedValue(this); return; case InitialClass: delete toCSSInitialValue(this); return; case PrimitiveClass: delete toCSSPrimitiveValue(this); return; case ShadowClass: delete toCSSShadowValue(this); return; case CubicBezierTimingFunctionClass: delete toCSSCubicBezierTimingFunctionValue(this); return; case StepsTimingFunctionClass: delete toCSSStepsTimingFunctionValue(this); return; case UnicodeRangeClass: delete toCSSUnicodeRangeValue(this); return; case ValueListClass: delete toCSSValueList(this); return; case CSSTransformClass: delete toCSSTransformValue(this); return; case LineBoxContainClass: delete toCSSLineBoxContainValue(this); return; case CalculationClass: delete toCSSCalcValue(this); return; case ImageSetClass: delete toCSSImageSetValue(this); return; case CSSFilterClass: delete toCSSFilterValue(this); return; } ASSERT_NOT_REACHED(); } PassRefPtr CSSValue::cloneForCSSOM() const { switch (classType()) { case PrimitiveClass: return toCSSPrimitiveValue(this)->cloneForCSSOM(); case ValueListClass: return toCSSValueList(this)->cloneForCSSOM(); case ImageClass: case CursorImageClass: return toCSSImageValue(this)->cloneForCSSOM(); case CSSFilterClass: return toCSSFilterValue(this)->cloneForCSSOM(); case CSSTransformClass: return toCSSTransformValue(this)->cloneForCSSOM(); case ImageSetClass: return toCSSImageSetValue(this)->cloneForCSSOM(); default: ASSERT(!isSubtypeExposedToCSSOM()); return TextCloneCSSValue::create(classType(), cssText()); } } }