1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 22 #ifndef ElementRuleCollector_h 23 #define ElementRuleCollector_h 24 25 #include "core/css/PseudoStyleRequest.h" 26 #include "core/css/SelectorChecker.h" 27 #include "core/css/resolver/ElementResolveContext.h" 28 #include "core/css/resolver/MatchRequest.h" 29 #include "core/css/resolver/MatchResult.h" 30 #include "wtf/RefPtr.h" 31 #include "wtf/Vector.h" 32 33 namespace WebCore { 34 35 class CSSStyleSheet; 36 class CSSRuleList; 37 class RuleData; 38 class RuleSet; 39 class ScopedStyleResolver; 40 class SelectorFilter; 41 class StaticCSSRuleList; 42 43 typedef unsigned CascadeScope; 44 typedef unsigned CascadeOrder; 45 46 const CascadeScope ignoreCascadeScope = 0; 47 const CascadeOrder ignoreCascadeOrder = 0; 48 49 class MatchedRule { 50 ALLOW_ONLY_INLINE_ALLOCATION(); 51 public: 52 MatchedRule(const RuleData* ruleData, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet) 53 : m_ruleData(ruleData) 54 , m_specificity(specificity) 55 , m_cascadeScope(cascadeScope) 56 , m_parentStyleSheet(parentStyleSheet) 57 { 58 ASSERT(m_ruleData); 59 static const unsigned BitsForPositionInRuleData = 18; 60 static const unsigned BitsForStyleSheetIndex = 32; 61 m_position = ((uint64_t)cascadeOrder << (BitsForStyleSheetIndex + BitsForPositionInRuleData)) + ((uint64_t)styleSheetIndex << BitsForPositionInRuleData)+ m_ruleData->position(); 62 } 63 64 const RuleData* ruleData() const { return m_ruleData; } 65 uint32_t cascadeScope() const { return m_cascadeScope; } 66 uint64_t position() const { return m_position; } 67 unsigned specificity() const { return ruleData()->specificity() + m_specificity; } 68 const CSSStyleSheet* parentStyleSheet() const { return m_parentStyleSheet; } 69 void trace(Visitor* visitor) 70 { 71 visitor->trace(m_parentStyleSheet); 72 } 73 74 private: 75 // FIXME: Oilpan: RuleData is in the oilpan heap and this pointer 76 // really should be traced. However, RuleData objects are 77 // allocated inside larger TerminatedArray objects and we cannot 78 // trace a raw rule data pointer at this point. 79 const RuleData* m_ruleData; 80 unsigned m_specificity; 81 CascadeScope m_cascadeScope; 82 uint64_t m_position; 83 RawPtrWillBeMember<const CSSStyleSheet> m_parentStyleSheet; 84 }; 85 86 } // namespace WebCore 87 88 WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::MatchedRule); 89 90 namespace WebCore { 91 92 // FIXME: oilpan: when transition types are gone this class can be replaced with HeapVector. 93 class StyleRuleList FINAL : public RefCountedWillBeGarbageCollected<StyleRuleList> { 94 public: 95 static PassRefPtrWillBeRawPtr<StyleRuleList> create() { return adoptRefWillBeNoop(new StyleRuleList()); } 96 97 void trace(Visitor* visitor) 98 { 99 #if ENABLE(OILPAN) 100 visitor->trace(m_list); 101 #endif 102 } 103 104 WillBeHeapVector<RawPtrWillBeMember<StyleRule> > m_list; 105 }; 106 107 // ElementRuleCollector is designed to be used as a stack object. 108 // Create one, ask what rules the ElementResolveContext matches 109 // and then let it go out of scope. 110 // FIXME: Currently it modifies the RenderStyle but should not! 111 class ElementRuleCollector { 112 STACK_ALLOCATED(); 113 WTF_MAKE_NONCOPYABLE(ElementRuleCollector); 114 public: 115 ElementRuleCollector(const ElementResolveContext&, const SelectorFilter&, RenderStyle* = 0); 116 ~ElementRuleCollector(); 117 118 void setMode(SelectorChecker::Mode mode) { m_mode = mode; } 119 void setPseudoStyleRequest(const PseudoStyleRequest& request) { m_pseudoStyleRequest = request; } 120 void setSameOriginOnly(bool f) { m_sameOriginOnly = f; } 121 122 void setMatchingUARules(bool matchingUARules) { m_matchingUARules = matchingUARules; } 123 bool hasAnyMatchingRules(RuleSet*); 124 125 MatchResult& matchedResult(); 126 PassRefPtrWillBeRawPtr<StyleRuleList> matchedStyleRuleList(); 127 PassRefPtrWillBeRawPtr<CSSRuleList> matchedCSSRuleList(); 128 129 void collectMatchingRules(const MatchRequest&, RuleRange&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary, CascadeScope = ignoreCascadeScope, CascadeOrder = ignoreCascadeOrder); 130 void sortAndTransferMatchedRules(); 131 void clearMatchedRules(); 132 void addElementStyleProperties(const StylePropertySet*, bool isCacheable = true); 133 134 unsigned lastMatchedRulesPosition() const { return m_matchedRules ? m_matchedRules->size() : 0; } 135 void sortMatchedRulesFrom(unsigned position); 136 void sortAndTransferMatchedRulesWithOnlySortBySpecificity(); 137 138 private: 139 void collectRuleIfMatches(const RuleData&, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&); 140 141 template<typename RuleDataListType> 142 void collectMatchingRulesForList(const RuleDataListType* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) 143 { 144 if (!rules) 145 return; 146 147 for (typename RuleDataListType::const_iterator it = rules->begin(), end = rules->end(); it != end; ++it) 148 collectRuleIfMatches(*it, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); 149 } 150 151 bool ruleMatches(const RuleData&, const ContainerNode* scope, SelectorChecker::BehaviorAtBoundary, SelectorChecker::MatchResult*); 152 153 CSSRuleList* nestedRuleList(CSSRule*); 154 template<class CSSRuleCollection> 155 CSSRule* findStyleRule(CSSRuleCollection*, StyleRule*); 156 void appendCSSOMWrapperForRule(CSSStyleSheet*, StyleRule*); 157 158 void sortMatchedRules(); 159 void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet); 160 161 StaticCSSRuleList* ensureRuleList(); 162 StyleRuleList* ensureStyleRuleList(); 163 164 private: 165 const ElementResolveContext& m_context; 166 const SelectorFilter& m_selectorFilter; 167 RefPtr<RenderStyle> m_style; // FIXME: This can be mutated during matching! 168 169 PseudoStyleRequest m_pseudoStyleRequest; 170 SelectorChecker::Mode m_mode; 171 bool m_canUseFastReject; 172 bool m_sameOriginOnly; 173 bool m_matchingUARules; 174 175 OwnPtrWillBeMember<WillBeHeapVector<MatchedRule, 32> > m_matchedRules; 176 177 // Output. 178 RefPtrWillBeMember<StaticCSSRuleList> m_cssRuleList; 179 RefPtrWillBeMember<StyleRuleList> m_styleRuleList; 180 MatchResult m_result; 181 }; 182 183 } // namespace WebCore 184 185 #endif // ElementRuleCollector_h 186