Home | History | Annotate | Download | only in css
      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