Home | History | Annotate | Download | only in css
      1 /*
      2  * (C) 1999-2003 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2004, 2005, 2006, 2008, 2012 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 StylePropertySet_h
     22 #define StylePropertySet_h
     23 
     24 #include "CSSPropertyNames.h"
     25 #include "core/css/CSSParserMode.h"
     26 #include "core/css/CSSPrimitiveValue.h"
     27 #include "core/css/CSSProperty.h"
     28 #include "core/css/PropertySetCSSStyleDeclaration.h"
     29 #include "wtf/ListHashSet.h"
     30 #include "wtf/Vector.h"
     31 #include "wtf/text/WTFString.h"
     32 
     33 namespace WebCore {
     34 
     35 class CSSRule;
     36 class CSSStyleDeclaration;
     37 class Element;
     38 class ImmutableStylePropertySet;
     39 class KURL;
     40 class MutableStylePropertySet;
     41 class StylePropertyShorthand;
     42 class StyleSheetContents;
     43 
     44 class StylePropertySet : public RefCounted<StylePropertySet> {
     45     friend class PropertyReference;
     46 public:
     47     // Override RefCounted's deref() to ensure operator delete is called on
     48     // the appropriate subclass type.
     49     void deref();
     50 
     51     class PropertyReference {
     52     public:
     53         PropertyReference(const StylePropertySet& propertySet, unsigned index)
     54             : m_propertySet(propertySet)
     55             , m_index(index)
     56         {
     57         }
     58 
     59         CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
     60         CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
     61 
     62         bool isImportant() const { return propertyMetadata().m_important; }
     63         bool isInherited() const { return propertyMetadata().m_inherited; }
     64         bool isImplicit() const { return propertyMetadata().m_implicit; }
     65 
     66         String cssName() const;
     67         String cssText() const;
     68 
     69         const CSSValue* value() const { return propertyValue(); }
     70         // FIXME: We should try to remove this mutable overload.
     71         CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
     72 
     73         // FIXME: Remove this.
     74         CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); }
     75 
     76         const StylePropertyMetadata& propertyMetadata() const;
     77 
     78     private:
     79         const CSSValue* propertyValue() const;
     80 
     81         const StylePropertySet& m_propertySet;
     82         unsigned m_index;
     83     };
     84 
     85     unsigned propertyCount() const;
     86     bool isEmpty() const;
     87     PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); }
     88     int findPropertyIndex(CSSPropertyID) const;
     89     size_t findVariableIndex(const AtomicString& name) const;
     90 
     91     PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
     92     String getPropertyValue(CSSPropertyID) const;
     93     unsigned variableCount() const;
     94     String variableValue(const AtomicString& name) const;
     95 
     96     bool propertyIsImportant(CSSPropertyID) const;
     97     CSSPropertyID getPropertyShorthand(CSSPropertyID) const;
     98     bool isPropertyImplicit(CSSPropertyID) const;
     99 
    100     PassRefPtr<MutableStylePropertySet> copyBlockProperties() const;
    101 
    102     CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
    103 
    104     void addSubresourceStyleURLs(ListHashSet<KURL>&, StyleSheetContents* contextStyleSheet) const;
    105 
    106     PassRefPtr<MutableStylePropertySet> mutableCopy() const;
    107     PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const;
    108 
    109     PassRefPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const;
    110 
    111     String asText() const;
    112 
    113     bool isMutable() const { return m_isMutable; }
    114     bool hasCSSOMWrapper() const;
    115 
    116     bool hasFailedOrCanceledSubresources() const;
    117 
    118     static unsigned averageSizeInBytes();
    119 
    120 #ifndef NDEBUG
    121     void showStyle();
    122 #endif
    123 
    124     bool propertyMatches(CSSPropertyID, const CSSValue*) const;
    125 
    126 protected:
    127     StylePropertySet(CSSParserMode cssParserMode)
    128         : m_cssParserMode(cssParserMode)
    129         , m_isMutable(true)
    130         , m_arraySize(0)
    131     { }
    132 
    133     StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize)
    134         : m_cssParserMode(cssParserMode)
    135         , m_isMutable(false)
    136         , m_arraySize(immutableArraySize)
    137     { }
    138 
    139     unsigned m_cssParserMode : 2;
    140     mutable unsigned m_isMutable : 1;
    141     unsigned m_arraySize : 29;
    142 
    143     friend class PropertySetCSSStyleDeclaration;
    144 };
    145 
    146 class ImmutableStylePropertySet : public StylePropertySet {
    147 public:
    148     ~ImmutableStylePropertySet();
    149     static PassRefPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode);
    150 
    151     unsigned propertyCount() const { return m_arraySize; }
    152 
    153     const CSSValue** valueArray() const;
    154     const StylePropertyMetadata* metadataArray() const;
    155 
    156     void* m_storage;
    157 
    158 private:
    159     ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode);
    160 };
    161 
    162 inline const CSSValue** ImmutableStylePropertySet::valueArray() const
    163 {
    164     return reinterpret_cast<const CSSValue**>(const_cast<const void**>(&(this->m_storage)));
    165 }
    166 
    167 inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const
    168 {
    169     return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]);
    170 }
    171 
    172 class MutableStylePropertySet : public StylePropertySet {
    173 public:
    174     static PassRefPtr<MutableStylePropertySet> create(CSSParserMode = CSSQuirksMode);
    175     static PassRefPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count);
    176 
    177     unsigned propertyCount() const { return m_propertyVector.size(); }
    178     PropertySetCSSStyleDeclaration* cssStyleDeclaration();
    179 
    180     void addParsedProperties(const Vector<CSSProperty>&);
    181     void addParsedProperty(const CSSProperty&);
    182 
    183     // These expand shorthand properties into multiple properties.
    184     bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
    185     void setProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important = false);
    186 
    187     // These do not. FIXME: This is too messy, we can do better.
    188     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
    189     bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
    190     void appendPrefixingVariantProperty(const CSSProperty&);
    191     void setPrefixingVariantProperty(const CSSProperty&);
    192     void setProperty(const CSSProperty&, CSSProperty* slot = 0);
    193     bool setVariableValue(const AtomicString& name, const String& value, bool important = false);
    194 
    195     bool removeProperty(CSSPropertyID, String* returnText = 0);
    196     void removePrefixedOrUnprefixedProperty(CSSPropertyID);
    197     void removeBlockProperties();
    198     bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
    199     void removeEquivalentProperties(const StylePropertySet*);
    200     void removeEquivalentProperties(const CSSStyleDeclaration*);
    201     bool removeVariable(const AtomicString& name);
    202     bool clearVariables();
    203 
    204     void mergeAndOverrideOnConflict(const StylePropertySet*);
    205 
    206     void clear();
    207     void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet);
    208 
    209     CSSStyleDeclaration* ensureCSSStyleDeclaration();
    210     CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(Element* parentElement);
    211 
    212     Vector<CSSProperty, 4> m_propertyVector;
    213 
    214 private:
    215     explicit MutableStylePropertySet(CSSParserMode);
    216     explicit MutableStylePropertySet(const StylePropertySet&);
    217     MutableStylePropertySet(const CSSProperty* properties, unsigned count);
    218 
    219     bool removeShorthandProperty(CSSPropertyID);
    220     CSSProperty* findCSSPropertyWithID(CSSPropertyID);
    221     OwnPtr<PropertySetCSSStyleDeclaration> m_cssomWrapper;
    222 
    223     friend class StylePropertySet;
    224 };
    225 
    226 inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const
    227 {
    228     if (m_propertySet.isMutable())
    229         return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).metadata();
    230     return static_cast<const ImmutableStylePropertySet&>(m_propertySet).metadataArray()[m_index];
    231 }
    232 
    233 inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const
    234 {
    235     if (m_propertySet.isMutable())
    236         return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).value();
    237     return static_cast<const ImmutableStylePropertySet&>(m_propertySet).valueArray()[m_index];
    238 }
    239 
    240 inline unsigned StylePropertySet::propertyCount() const
    241 {
    242     if (m_isMutable)
    243         return static_cast<const MutableStylePropertySet*>(this)->m_propertyVector.size();
    244     return m_arraySize;
    245 }
    246 
    247 inline bool StylePropertySet::isEmpty() const
    248 {
    249     return !propertyCount();
    250 }
    251 
    252 inline void StylePropertySet::deref()
    253 {
    254     if (!derefBase())
    255         return;
    256 
    257     if (m_isMutable)
    258         delete static_cast<MutableStylePropertySet*>(this);
    259     else
    260         delete static_cast<ImmutableStylePropertySet*>(this);
    261 }
    262 
    263 } // namespace WebCore
    264 
    265 #endif // StylePropertySet_h
    266