Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2011 Andreas Kling (kling (at) 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 
     63 namespace WebCore {
     64 
     65 struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> {
     66     uint32_t bitfields;
     67 };
     68 
     69 COMPILE_ASSERT(sizeof(CSSValue) == sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small);
     70 
     71 class TextCloneCSSValue : public CSSValue {
     72 public:
     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 
     77 private:
     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 
     88 bool CSSValue::isImplicitInitialValue() const
     89 {
     90     return m_classType == InitialClass && static_cast<const CSSInitialValue*>(this)->isImplicit();
     91 }
     92 
     93 CSSValue::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 
    106 void 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 
    121 bool 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 
    140 template<class ChildClassType>
    141 inline 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 
    146 bool 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 
    236 String 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 
    320 String 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 
    336 void 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 
    455 PassRefPtr<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