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