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