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 "core/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 RefCountedWillBeRefCountedGarbageCollected<StylePropertySet> {
     45     friend class PropertyReference;
     46 public:
     47 
     48 #if ENABLE(OILPAN)
     49     // When oilpan is enabled override the finalize method to dispatch to the subclasses'
     50     // destructor. This can be removed once the MutableStylePropertySet's OwnPtr is moved
     51     // to the heap.
     52     void finalizeGarbageCollectedObject();
     53 #else
     54     // Override RefCounted's deref() to ensure operator delete is called on
     55     // the appropriate subclass type.
     56     void deref();
     57 #endif
     58 
     59     class PropertyReference {
     60     public:
     61         PropertyReference(const StylePropertySet& propertySet, unsigned index)
     62             : m_propertySet(propertySet)
     63             , m_index(index)
     64         {
     65         }
     66 
     67         CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
     68         CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
     69 
     70         bool isImportant() const { return propertyMetadata().m_important; }
     71         bool isInherited() const { return propertyMetadata().m_inherited; }
     72         bool isImplicit() const { return propertyMetadata().m_implicit; }
     73 
     74         String cssName() const;
     75         String cssText() const;
     76 
     77         const CSSValue* value() const { return propertyValue(); }
     78         // FIXME: We should try to remove this mutable overload.
     79         CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
     80 
     81         // FIXME: Remove this.
     82         CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); }
     83 
     84         const StylePropertyMetadata& propertyMetadata() const;
     85 
     86     private:
     87         const CSSValue* propertyValue() const;
     88 
     89         const StylePropertySet& m_propertySet;
     90         unsigned m_index;
     91     };
     92 
     93     unsigned propertyCount() const;
     94     bool isEmpty() const;
     95     PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); }
     96     int findPropertyIndex(CSSPropertyID) const;
     97 
     98     PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
     99     String getPropertyValue(CSSPropertyID) const;
    100 
    101     bool propertyIsImportant(CSSPropertyID) const;
    102     CSSPropertyID getPropertyShorthand(CSSPropertyID) const;
    103     bool isPropertyImplicit(CSSPropertyID) const;
    104 
    105     PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyBlockProperties() const;
    106 
    107     CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
    108 
    109     PassRefPtrWillBeRawPtr<MutableStylePropertySet> mutableCopy() const;
    110     PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const;
    111 
    112     PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const;
    113 
    114     String asText() const;
    115 
    116     bool isMutable() const { return m_isMutable; }
    117 
    118     bool hasFailedOrCanceledSubresources() const;
    119 
    120     static unsigned averageSizeInBytes();
    121 
    122 #ifndef NDEBUG
    123     void showStyle();
    124 #endif
    125 
    126     bool propertyMatches(CSSPropertyID, const CSSValue*) const;
    127 
    128     void trace(Visitor*);
    129     void traceAfterDispatch(Visitor*) { }
    130 
    131 protected:
    132 
    133     enum { MaxArraySize = (1 << 28) - 1 };
    134 
    135     StylePropertySet(CSSParserMode cssParserMode)
    136         : m_cssParserMode(cssParserMode)
    137         , m_isMutable(true)
    138         , m_arraySize(0)
    139     { }
    140 
    141     StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize)
    142         : m_cssParserMode(cssParserMode)
    143         , m_isMutable(false)
    144         , m_arraySize(std::min(immutableArraySize, unsigned(MaxArraySize)))
    145     { }
    146 
    147     unsigned m_cssParserMode : 3;
    148     mutable unsigned m_isMutable : 1;
    149     unsigned m_arraySize : 28;
    150 
    151     friend class PropertySetCSSStyleDeclaration;
    152 };
    153 
    154 class ImmutableStylePropertySet : public StylePropertySet {
    155 public:
    156     ~ImmutableStylePropertySet();
    157     static PassRefPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode);
    158 
    159     unsigned propertyCount() const { return m_arraySize; }
    160 
    161     const RawPtrWillBeMember<CSSValue>* valueArray() const;
    162     const StylePropertyMetadata* metadataArray() const;
    163     int findPropertyIndex(CSSPropertyID) const;
    164 
    165     void traceAfterDispatch(Visitor*);
    166 
    167     void* operator new(std::size_t, void* location)
    168     {
    169         return location;
    170     }
    171 
    172     void* m_storage;
    173 
    174 private:
    175     ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode);
    176 };
    177 
    178 inline const RawPtrWillBeMember<CSSValue>* ImmutableStylePropertySet::valueArray() const
    179 {
    180     return reinterpret_cast<const RawPtrWillBeMember<CSSValue>*>(const_cast<const void**>(&(this->m_storage)));
    181 }
    182 
    183 inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const
    184 {
    185     return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(RawPtrWillBeMember<CSSValue>)]);
    186 }
    187 
    188 DEFINE_TYPE_CASTS(ImmutableStylePropertySet, StylePropertySet, set, !set->isMutable(), !set.isMutable());
    189 
    190 inline ImmutableStylePropertySet* toImmutableStylePropertySet(const RefPtr<StylePropertySet>& set)
    191 {
    192     return toImmutableStylePropertySet(set.get());
    193 }
    194 
    195 class MutableStylePropertySet : public StylePropertySet {
    196 public:
    197     ~MutableStylePropertySet() { }
    198     static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode);
    199     static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count);
    200 
    201     unsigned propertyCount() const { return m_propertyVector.size(); }
    202 
    203     void addParsedProperties(const WillBeHeapVector<CSSProperty, 256>&);
    204     void addParsedProperty(const CSSProperty&);
    205 
    206     // These expand shorthand properties into multiple properties.
    207     bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
    208     void setProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important = false);
    209 
    210     // These do not. FIXME: This is too messy, we can do better.
    211     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
    212     bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
    213     void appendPrefixingVariantProperty(const CSSProperty&);
    214     void setPrefixingVariantProperty(const CSSProperty&);
    215     void setProperty(const CSSProperty&, CSSProperty* slot = 0);
    216 
    217     bool removeProperty(CSSPropertyID, String* returnText = 0);
    218     void removePrefixedOrUnprefixedProperty(CSSPropertyID);
    219     void removeBlockProperties();
    220     bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
    221     void removeEquivalentProperties(const StylePropertySet*);
    222     void removeEquivalentProperties(const CSSStyleDeclaration*);
    223 
    224     void mergeAndOverrideOnConflict(const StylePropertySet*);
    225 
    226     void clear();
    227     void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet);
    228 
    229     CSSStyleDeclaration* ensureCSSStyleDeclaration();
    230     int findPropertyIndex(CSSPropertyID) const;
    231 
    232     void traceAfterDispatch(Visitor*);
    233 
    234 private:
    235     explicit MutableStylePropertySet(CSSParserMode);
    236     explicit MutableStylePropertySet(const StylePropertySet&);
    237     MutableStylePropertySet(const CSSProperty* properties, unsigned count);
    238 
    239     bool removeShorthandProperty(CSSPropertyID);
    240     CSSProperty* findCSSPropertyWithID(CSSPropertyID);
    241     OwnPtrWillBeMember<PropertySetCSSStyleDeclaration> m_cssomWrapper;
    242 
    243     friend class StylePropertySet;
    244 
    245     WillBeHeapVector<CSSProperty, 4> m_propertyVector;
    246 };
    247 
    248 DEFINE_TYPE_CASTS(MutableStylePropertySet, StylePropertySet, set, set->isMutable(), set.isMutable());
    249 
    250 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtr<StylePropertySet>& set)
    251 {
    252     return toMutableStylePropertySet(set.get());
    253 }
    254 
    255 inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const
    256 {
    257     if (m_propertySet.isMutable())
    258         return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).metadata();
    259     return toImmutableStylePropertySet(m_propertySet).metadataArray()[m_index];
    260 }
    261 
    262 inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const
    263 {
    264     if (m_propertySet.isMutable())
    265         return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).value();
    266     return toImmutableStylePropertySet(m_propertySet).valueArray()[m_index];
    267 }
    268 
    269 inline unsigned StylePropertySet::propertyCount() const
    270 {
    271     if (m_isMutable)
    272         return toMutableStylePropertySet(this)->m_propertyVector.size();
    273     return m_arraySize;
    274 }
    275 
    276 inline bool StylePropertySet::isEmpty() const
    277 {
    278     return !propertyCount();
    279 }
    280 
    281 #if !ENABLE(OILPAN)
    282 inline void StylePropertySet::deref()
    283 {
    284     if (!derefBase())
    285         return;
    286 
    287     if (m_isMutable)
    288         delete toMutableStylePropertySet(this);
    289     else
    290         delete toImmutableStylePropertySet(this);
    291 }
    292 #endif // !ENABLE(OILPAN)
    293 
    294 inline int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const
    295 {
    296     if (m_isMutable)
    297         return toMutableStylePropertySet(this)->findPropertyIndex(propertyID);
    298     return toImmutableStylePropertySet(this)->findPropertyIndex(propertyID);
    299 }
    300 
    301 } // namespace WebCore
    302 
    303 #endif // StylePropertySet_h
    304