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