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 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:
     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 
    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:
    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 
    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 
    150         void allVisitedStateChanged() { m_checker.allVisitedStateChanged(); }
    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 
    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:
    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)
    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 
    303         ~CSSRuleData()
    304         {
    305         }
    306 
    307         unsigned position() { return m_position; }
    308         CSSStyleRule* rule() { return m_rule; }
    309         CSSSelector* selector() { return m_selector; }
    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:
    321         CSSRuleDataList(unsigned pos, CSSStyleRule* rule, CSSSelector* sel)
    322             : m_first(new CSSRuleData(pos, rule, sel))
    323             , m_last(m_first)
    324         {
    325         }
    326 
    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 
    339         CSSRuleData* first() { return m_first; }
    340         CSSRuleData* last() { return m_last; }
    341 
    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