1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) 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: 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 117 RenderStyle* style() const { return m_style.get(); } 118 RenderStyle* parentStyle() const { return m_parentStyle; } 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: 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 169 CSSFontSelector* fontSelector() const { return m_fontSelector.get(); } 170 171 void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result); 172 173 bool affectedByViewportChange() const; 174 175 void allVisitedStateChanged() { m_checker.allVisitedStateChanged(); } 176 void visitedStateChanged(LinkHash visitedHash) { m_checker.visitedStateChanged(visitedHash); } 177 178 void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule); 179 void addPageStyle(PassRefPtr<CSSPageRule>); 180 181 bool usesSiblingRules() const { return m_features.siblingRules; } 182 bool usesFirstLineRules() const { return m_features.usesFirstLineRules; } 183 bool usesBeforeAfterRules() const { return m_features.usesBeforeAfterRules; } 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 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; 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 { 234 ParentStackFrame() {} 235 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: 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