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