1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@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 "core/css/resolver/StyleResolverIncludes.h"
31#include "wtf/RefPtr.h"
32#include "wtf/Vector.h"
33
34namespace WebCore {
35
36class CSSRuleList;
37class RenderRegion;
38class RuleData;
39class RuleSet;
40class ScopedStyleResolver;
41class SelectorFilter;
42class StaticCSSRuleList;
43
44typedef unsigned CascadeScope;
45typedef unsigned CascadeOrder;
46
47const CascadeScope ignoreCascadeScope = 0;
48const CascadeOrder ignoreCascadeOrder = 0;
49
50class MatchedRule {
51    WTF_MAKE_FAST_ALLOCATED;
52public:
53    explicit MatchedRule(const RuleData* ruleData, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex)
54        : m_ruleData(ruleData)
55        , m_specificity(specificity)
56        , m_cascadeScope(cascadeScope)
57        , m_styleSheetIndex(styleSheetIndex)
58    {
59        ASSERT(m_ruleData);
60        static const unsigned BitsForPositionInRuleData = 18;
61        m_position = (cascadeOrder << BitsForPositionInRuleData) + m_ruleData->position();
62    }
63
64    const RuleData* ruleData() const { return m_ruleData; }
65    uint32_t cascadeScope() const { return m_cascadeScope; }
66    uint32_t position() const { return m_position; }
67    unsigned specificity() const { return ruleData()->specificity() + m_specificity; }
68    uint32_t styleSheetIndex() const { return m_styleSheetIndex; }
69
70private:
71    const RuleData* m_ruleData;
72    unsigned m_specificity;
73    CascadeScope m_cascadeScope;
74    uint32_t m_position;
75    uint32_t m_styleSheetIndex;
76};
77
78class StyleRuleList : public RefCounted<StyleRuleList> {
79public:
80    static PassRefPtr<StyleRuleList> create() { return adoptRef(new StyleRuleList()); }
81    Vector<StyleRule*> m_list;
82};
83
84// ElementRuleCollector is designed to be used as a stack object.
85// Create one, ask what rules the ElementResolveContext matches
86// and then let it go out of scope.
87// FIXME: Currently it modifies the RenderStyle but should not!
88class ElementRuleCollector {
89    WTF_MAKE_NONCOPYABLE(ElementRuleCollector);
90public:
91    ElementRuleCollector(const ElementResolveContext&, const SelectorFilter&, RenderStyle* = 0, ShouldIncludeStyleSheetInCSSOMWrapper = IncludeStyleSheetInCSSOMWrapper);
92    ~ElementRuleCollector();
93
94    void setMode(SelectorChecker::Mode mode) { m_mode = mode; }
95    void setPseudoStyleRequest(const PseudoStyleRequest& request) { m_pseudoStyleRequest = request; }
96    void setSameOriginOnly(bool f) { m_sameOriginOnly = f; }
97    void setRegionForStyling(const RenderRegion* regionForStyling) { m_regionForStyling = regionForStyling; }
98
99    void setMatchingUARules(bool matchingUARules) { m_matchingUARules = matchingUARules; }
100    bool hasAnyMatchingRules(RuleSet*);
101
102    MatchResult& matchedResult();
103    PassRefPtr<StyleRuleList> matchedStyleRuleList();
104    PassRefPtr<CSSRuleList> matchedCSSRuleList();
105
106    void collectMatchingRules(const MatchRequest&, RuleRange&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary, CascadeScope = ignoreCascadeScope, CascadeOrder = ignoreCascadeOrder);
107    void collectMatchingRulesForRegion(const MatchRequest&, RuleRange&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary, CascadeScope = ignoreCascadeScope, CascadeOrder = ignoreCascadeOrder);
108    void sortAndTransferMatchedRules();
109    void clearMatchedRules();
110    void addElementStyleProperties(const StylePropertySet*, bool isCacheable = true);
111
112    unsigned lastMatchedRulesPosition() const { return m_matchedRules ? m_matchedRules->size() : 0; }
113    void sortMatchedRulesFrom(unsigned position);
114    void sortAndTransferMatchedRulesWithOnlySortBySpecificity();
115
116private:
117    void collectRuleIfMatches(const RuleData&, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&);
118    void collectMatchingRulesForList(const Vector<RuleData>*, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&);
119    void collectMatchingRulesForList(const RuleData*, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&);
120    bool ruleMatches(const RuleData&, const ContainerNode* scope, SelectorChecker::BehaviorAtBoundary, SelectorChecker::MatchResult*);
121
122    void appendCSSOMWrapperForRule(StyleRule*);
123
124    void sortMatchedRules();
125    void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder);
126    void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder, unsigned styleSheetIndex);
127
128    StaticCSSRuleList* ensureRuleList();
129    StyleRuleList* ensureStyleRuleList();
130
131private:
132    const ElementResolveContext& m_context;
133    const SelectorFilter& m_selectorFilter;
134    RefPtr<RenderStyle> m_style; // FIXME: This can be mutated during matching!
135
136    const RenderRegion* m_regionForStyling;
137    PseudoStyleRequest m_pseudoStyleRequest;
138    SelectorChecker::Mode m_mode;
139    bool m_canUseFastReject;
140    bool m_sameOriginOnly;
141    bool m_matchingUARules;
142    bool m_includeStyleSheet;
143
144    OwnPtr<Vector<MatchedRule, 32> > m_matchedRules;
145
146    // Output.
147    RefPtr<StaticCSSRuleList> m_cssRuleList;
148    RefPtr<StyleRuleList> m_styleRuleList;
149    MatchResult m_result;
150};
151
152} // namespace WebCore
153
154#endif // ElementRuleCollector_h
155