2011-02-06 Maciej Stachowiak <mjs@apple.com>
[WebKit.git] / Source / WebCore / css / CSSStyleSelector.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 CSSStyleSelector_h
23 #define CSSStyleSelector_h
24
25 #include "CSSFontSelector.h"
26 #include "CSSRule.h"
27 #include "LinkHash.h"
28 #include "MediaQueryExp.h"
29 #include "RenderStyle.h"
30 #include <wtf/HashCountedSet.h>
31 #include <wtf/HashMap.h>
32 #include <wtf/HashSet.h>
33 #include <wtf/RefPtr.h>
34 #include <wtf/Vector.h>
35 #include <wtf/text/StringHash.h>
36
37 namespace WebCore {
38
39 class CSSMutableStyleDeclaration;
40 class CSSPageRule;
41 class CSSPrimitiveValue;
42 class CSSProperty;
43 class CSSFontFace;
44 class CSSFontFaceRule;
45 class CSSImageValue;
46 class CSSRuleList;
47 class CSSSelector;
48 class CSSStyleRule;
49 class CSSStyleSheet;
50 class CSSValue;
51 class ContainerNode;
52 class DataGridColumn;
53 class Document;
54 class Element;
55 class Frame;
56 class FrameView;
57 class KURL;
58 class KeyframeList;
59 class KeyframeValue;
60 class MediaQueryEvaluator;
61 class Node;
62 class RuleData;
63 class RuleSet;
64 class Settings;
65 class StyleImage;
66 class StyleSheet;
67 class StyleSheetList;
68 class StyledElement;
69 class WebKitCSSKeyframeRule;
70 class WebKitCSSKeyframesRule;
71
72 class MediaQueryResult {
73     WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED;
74 public:
75     MediaQueryResult(const MediaQueryExp& expr, bool result)
76         : m_expression(expr)
77         , m_result(result)
78     {
79     }
80
81     MediaQueryExp m_expression;
82     bool m_result;
83 };
84
85     // This class selects a RenderStyle for a given element based on a collection of stylesheets.
86     class CSSStyleSelector {
87         WTF_MAKE_NONCOPYABLE(CSSStyleSelector); WTF_MAKE_FAST_ALLOCATED;
88     public:
89         CSSStyleSelector(Document*, StyleSheetList* authorSheets, CSSStyleSheet* mappedElementSheet,
90                          CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
91                          bool strictParsing, bool matchAuthorAndUserStyles);
92         ~CSSStyleSelector();
93         
94         // Using these during tree walk will allow style selector to optimize child and descendant selector lookups.
95         void pushParent(Element* parent);
96         void popParent(Element* parent);
97
98         PassRefPtr<RenderStyle> styleForElement(Element* e, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, bool matchVisitedPseudoClass = false);
99         
100         void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList& list);
101
102         PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle = 0, bool matchVisitedPseudoClass = false);
103
104         PassRefPtr<RenderStyle> styleForPage(int pageIndex);
105
106         static PassRefPtr<RenderStyle> styleForDocument(Document*);
107
108 #if ENABLE(DATAGRID)
109         // Datagrid style computation (uses unique pseudo elements and structures)
110         PassRefPtr<RenderStyle> pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle* parentStyle);
111         PassRefPtr<RenderStyle> pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle* parentStyle);
112 #endif
113
114     private:
115         void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO);
116         void initElement(Element*);
117         RenderStyle* locateSharedStyle();
118         bool matchesSiblingRules();
119         Node* locateCousinList(Element* parent, unsigned depth = 1) const;
120         Node* findSiblingForStyleSharing(Node*, unsigned& count) const;
121         bool canShareStyleWithElement(Node*) const;
122
123         RenderStyle* style() const { return m_style.get(); }
124
125         PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
126
127     public:
128         // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
129         PassRefPtr<CSSRuleList> styleRulesForElement(Element*, bool authorOnly, bool includeEmptyRules = false, CSSRuleFilter filter = AllCSSRules);
130         PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, bool authorOnly, bool includeEmptyRules = false, CSSRuleFilter filter = AllCSSRules);
131
132         // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
133         // the correct font size scaled relative to the user's default (medium).
134         static float fontSizeForKeyword(Document*, int keyword, bool shouldUseFixedDefaultSize);
135
136         // Given a font size in pixel, this function will return legacy font size between 1 and 7.
137         static int legacyFontSize(Document*, int pixelFontSize, bool shouldUseFixedDefaultSize);
138
139     private:
140
141         // When the CSS keyword "larger" is used, this function will attempt to match within the keyword
142         // table, and failing that, will simply multiply by 1.2.
143         float largerFontSize(float size, bool quirksMode) const;
144
145         // Like the previous function, but for the keyword "smaller".
146         float smallerFontSize(float size, bool quirksMode) const;
147
148     public:
149         void setStyle(PassRefPtr<RenderStyle> s) { m_style = s; } // Used by the document when setting up its root style.
150
151         void applyPropertyToStyle(int id, CSSValue*, RenderStyle*);
152
153     private:
154         void setFontSize(FontDescription&, float size);
155         static float getComputedSizeFromSpecifiedSize(Document*, RenderStyle*, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules);
156
157     public:
158         Color getColorFromPrimitiveValue(CSSPrimitiveValue*) const;
159
160         bool hasSelectorForAttribute(const AtomicString&) const;
161  
162         CSSFontSelector* fontSelector() const { return m_fontSelector.get(); }
163
164         // Checks if a compound selector (which can consist of multiple simple selectors) matches the current element.
165         bool checkSelector(CSSSelector*);
166
167         void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result);
168
169         bool affectedByViewportChange() const;
170
171         void allVisitedStateChanged() { m_checker.allVisitedStateChanged(); }
172         void visitedStateChanged(LinkHash visitedHash) { m_checker.visitedStateChanged(visitedHash); }
173
174         void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule);
175         void addPageStyle(PassRefPtr<CSSPageRule>);
176
177         static bool createTransformOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, TransformOperations& outOperations);
178
179     private:
180         enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsCompletely };
181
182         // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
183         void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
184         void checkForZoomChange(RenderStyle*, RenderStyle* parentStyle);
185         void checkForTextSizeAdjust();
186
187         void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
188
189         void addMatchedRule(const RuleData* rule) { m_matchedRules.append(rule); }
190         void addMatchedDeclaration(CSSMutableStyleDeclaration* decl);
191
192         void matchRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
193         void matchRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
194         bool fastRejectSelector(const RuleData&) const;
195         void sortMatchedRules(unsigned start, unsigned end);
196
197         template <bool firstPass>
198         void applyDeclarations(bool important, int startIndex, int endIndex);
199
200         void matchPageRules(RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
201         void matchPageRulesForList(const Vector<RuleData>*, bool isLeftPage, bool isFirstPage, const String& pageName);
202         bool isLeftPage(int pageIndex) const;
203         bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
204         bool isFirstPage(int pageIndex) const;
205         String pageName(int pageIndex) const;
206         
207         OwnPtr<RuleSet> m_authorStyle;
208         OwnPtr<RuleSet> m_userStyle;
209         
210         OwnPtr<RuleSet> m_siblingRules;
211         HashSet<AtomicStringImpl*> m_idsInRules;
212         
213         struct ParentStackFrame {
214             ParentStackFrame(Element* element) : element(element) {}
215             Element* element;
216             Vector<unsigned, 4> identifierHashes;
217         };
218         Vector<ParentStackFrame> m_parentStack;
219         // FIXME: Replace this with a bloom filter.
220         HashCountedSet<unsigned, AlreadyHashed> m_ancestorIdentifierFilter;
221
222         bool m_hasUAAppearance;
223         BorderData m_borderData;
224         FillLayer m_backgroundData;
225         Color m_backgroundColor;
226
227         typedef HashMap<AtomicStringImpl*, RefPtr<WebKitCSSKeyframesRule> > KeyframesRuleMap;
228         KeyframesRuleMap m_keyframesRuleMap;
229
230     public:
231         static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; }
232
233         class SelectorChecker {
234             WTF_MAKE_NONCOPYABLE(SelectorChecker);
235         public:
236             SelectorChecker(Document*, bool strictParsing);
237
238             bool checkSelector(CSSSelector*, Element*) const;
239             SelectorMatch checkSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
240             bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle*, RenderStyle* elementParentStyle) const;
241             bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
242
243             EInsideLink determineLinkState(Element* element) const;
244             EInsideLink determineLinkStateSlowCase(Element* element) const;
245             void allVisitedStateChanged();
246             void visitedStateChanged(LinkHash visitedHash);
247
248             Document* m_document;
249             bool m_strictParsing;
250             bool m_collectRulesOnly;
251             bool m_sameOriginOnly;
252             PseudoId m_pseudoStyle;
253             bool m_documentIsHTML;
254             mutable bool m_matchVisitedPseudoClass;
255             mutable HashSet<LinkHash, LinkHashHash> m_linksCheckedForVisitedState;
256         };
257
258     private:
259         static RenderStyle* s_styleNotYetAvailable;
260
261         void matchUARules(int& firstUARule, int& lastUARule);
262         void updateFont();
263         void cacheBorderAndBackground();
264
265         void mapFillAttachment(CSSPropertyID, FillLayer*, CSSValue*);
266         void mapFillClip(CSSPropertyID, FillLayer*, CSSValue*);
267         void mapFillComposite(CSSPropertyID, FillLayer*, CSSValue*);
268         void mapFillOrigin(CSSPropertyID, FillLayer*, CSSValue*);
269         void mapFillImage(CSSPropertyID, FillLayer*, CSSValue*);
270         void mapFillRepeatX(CSSPropertyID, FillLayer*, CSSValue*);
271         void mapFillRepeatY(CSSPropertyID, FillLayer*, CSSValue*);
272         void mapFillSize(CSSPropertyID, FillLayer*, CSSValue*);
273         void mapFillXPosition(CSSPropertyID, FillLayer*, CSSValue*);
274         void mapFillYPosition(CSSPropertyID, FillLayer*, CSSValue*);
275
276         void mapAnimationDelay(Animation*, CSSValue*);
277         void mapAnimationDirection(Animation*, CSSValue*);
278         void mapAnimationDuration(Animation*, CSSValue*);
279         void mapAnimationFillMode(Animation*, CSSValue*);
280         void mapAnimationIterationCount(Animation*, CSSValue*);
281         void mapAnimationName(Animation*, CSSValue*);
282         void mapAnimationPlayState(Animation*, CSSValue*);
283         void mapAnimationProperty(Animation*, CSSValue*);
284         void mapAnimationTimingFunction(Animation*, CSSValue*);
285
286         void mapNinePieceImage(CSSPropertyID, CSSValue*, NinePieceImage&);
287
288         void applyProperty(int id, CSSValue*);
289         void applyPageSizeProperty(CSSValue*);
290         bool pageSizeFromName(CSSPrimitiveValue*, CSSPrimitiveValue*, Length& width, Length& height);
291         Length mmLength(double mm) const;
292         Length inchLength(double inch) const;
293 #if ENABLE(SVG)
294         void applySVGProperty(int id, CSSValue*);
295 #endif
296
297         void loadPendingImages();
298         
299         StyleImage* styleImage(CSSPropertyID, CSSValue* value);
300         StyleImage* cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value);
301
302         // We collect the set of decls that match in |m_matchedDecls|.  We then walk the
303         // set of matched decls four times, once for those properties that others depend on (like font-size),
304         // and then a second time for all the remaining properties.  We then do the same two passes
305         // for any !important rules.
306         Vector<CSSMutableStyleDeclaration*, 64> m_matchedDecls;
307
308         // A buffer used to hold the set of matched rules for an element, and a temporary buffer used for
309         // merge sorting.
310         Vector<const RuleData*, 32> m_matchedRules;
311
312         RefPtr<CSSRuleList> m_ruleList;
313         
314         HashSet<int> m_pendingImageProperties; // Hash of CSSPropertyIDs
315
316         OwnPtr<MediaQueryEvaluator> m_medium;
317         RefPtr<RenderStyle> m_rootDefaultStyle;
318
319         PseudoId m_dynamicPseudo;
320
321         SelectorChecker m_checker;
322
323         RefPtr<RenderStyle> m_style;
324         RenderStyle* m_parentStyle;
325         RenderStyle* m_rootElementStyle;
326         Element* m_element;
327         StyledElement* m_styledElement;
328         EInsideLink m_elementLinkState;
329         ContainerNode* m_parentNode;
330         CSSValue* m_lineHeightValue;
331         bool m_fontDirty;
332         bool m_matchAuthorAndUserStyles;
333         
334         RefPtr<CSSFontSelector> m_fontSelector;
335         HashSet<AtomicStringImpl*> m_selectorAttrs;
336         Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls;
337         Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults;
338     };
339
340 } // namespace WebCore
341
342 #endif // CSSStyleSelector_h