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