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