1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@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 StyleResolver_h
23#define StyleResolver_h
24
25#include "CSSToStyleMap.h"
26#include "CSSValueList.h"
27#include "DocumentRuleSets.h"
28#include "InspectorCSSOMWrappers.h"
29#include "LinkHash.h"
30#include "MediaQueryExp.h"
31#include "RenderStyle.h"
32#include "RuleFeature.h"
33#include "RuleSet.h"
34#include "RuntimeEnabledFeatures.h"
35#include "ScrollTypes.h"
36#include "SelectorChecker.h"
37#include "SelectorFilter.h"
38#include "StyleInheritedData.h"
39#include "StyleScopeResolver.h"
40#include "ViewportStyleResolver.h"
41#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
42#include "WebKitCSSSVGDocumentValue.h"
43#endif
44#if ENABLE(CSS_SHADERS)
45#include "CustomFilterConstants.h"
46#endif
47#include <wtf/HashMap.h>
48#include <wtf/HashSet.h>
49#include <wtf/RefPtr.h>
50#include <wtf/Vector.h>
51#include <wtf/text/AtomicStringHash.h>
52#include <wtf/text/StringHash.h>
53
54namespace WebCore {
55
56enum ESmartMinimumForFontSize { DoNotUseSmartMinimumForFontSize, UseSmartMinimumForFontFize };
57
58class CSSCursorImageValue;
59class CSSFontSelector;
60class CSSFontFace;
61class CSSFontFaceRule;
62class CSSImageGeneratorValue;
63class CSSImageSetValue;
64class CSSImageValue;
65class CSSPageRule;
66class CSSPrimitiveValue;
67class CSSProperty;
68class CSSSelector;
69class CSSStyleSheet;
70class CSSValue;
71class ContainerNode;
72class CustomFilterOperation;
73class CustomFilterParameter;
74class CustomFilterParameterList;
75class CustomFilterProgram;
76struct CustomFilterProgramMixSettings;
77class Document;
78class DeprecatedStyleBuilder;
79class Element;
80class Frame;
81class FrameView;
82class KURL;
83class KeyframeList;
84class KeyframeValue;
85class MediaQueryEvaluator;
86class Node;
87class RenderRegion;
88class RenderScrollbar;
89class RuleData;
90class RuleSet;
91class Settings;
92class StyleCustomFilterProgramCache;
93class StyleScopeResolver;
94class StyleImage;
95class StyleKeyframe;
96class StylePendingImage;
97class StylePropertySet;
98class StyleRule;
99#if ENABLE(SHADOW_DOM)
100class StyleRuleHost;
101#endif
102class StyleRuleKeyframes;
103class StyleRulePage;
104class StyleRuleRegion;
105class StyleShader;
106class StyleSheet;
107class StyleSheetList;
108class StyledElement;
109class ViewportStyleResolver;
110class WebKitCSSFilterValue;
111class WebKitCSSShaderValue;
112class WebKitCSSSVGDocumentValue;
113
114class MediaQueryResult {
115    WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED;
116public:
117    MediaQueryResult(const MediaQueryExp& expr, bool result)
118        : m_expression(expr)
119        , m_result(result)
120    {
121    }
122
123    MediaQueryExp m_expression;
124    bool m_result;
125};
126
127enum StyleSharingBehavior {
128    AllowStyleSharing,
129    DisallowStyleSharing,
130};
131
132// MatchOnlyUserAgentRules is used in media queries, where relative units
133// are interpreted according to the document root element style, and styled only
134// from the User Agent Stylesheet rules.
135
136enum RuleMatchingBehavior {
137    MatchAllRules,
138    MatchAllRulesExcludingSMIL,
139    MatchOnlyUserAgentRules,
140};
141
142class PseudoStyleRequest {
143public:
144    PseudoStyleRequest(PseudoId pseudoId, RenderScrollbar* scrollbar = 0, ScrollbarPart scrollbarPart = NoPart)
145        : pseudoId(pseudoId)
146        , scrollbarPart(scrollbarPart)
147        , scrollbar(scrollbar)
148    {
149    }
150
151    PseudoId pseudoId;
152    ScrollbarPart scrollbarPart;
153    RenderScrollbar* scrollbar;
154};
155
156class MatchRequest {
157public:
158    MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0)
159        : ruleSet(ruleSet)
160        , includeEmptyRules(includeEmptyRules)
161        , scope(scope) { }
162    const RuleSet* ruleSet;
163    const bool includeEmptyRules;
164    const ContainerNode* scope;
165};
166
167// This class selects a RenderStyle for a given element based on a collection of stylesheets.
168class StyleResolver {
169    WTF_MAKE_NONCOPYABLE(StyleResolver); WTF_MAKE_FAST_ALLOCATED;
170public:
171    StyleResolver(Document*, bool matchAuthorAndUserStyles);
172    ~StyleResolver();
173
174    // Using these during tree walk will allow style selector to optimize child and descendant selector lookups.
175    void pushParentElement(Element*);
176    void popParentElement(Element*);
177    void pushParentShadowRoot(const ShadowRoot*);
178    void popParentShadowRoot(const ShadowRoot*);
179#if ENABLE(SHADOW_DOM)
180    void addHostRule(StyleRuleHost* rule, bool hasDocumentSecurityOrigin, const ContainerNode* scope) { ensureScopeResolver()->addHostRule(rule, hasDocumentSecurityOrigin, scope); }
181#endif
182
183    PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing,
184        RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = 0);
185
186    void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList&);
187
188    PassRefPtr<RenderStyle> pseudoStyleForElement(Element*, const PseudoStyleRequest&, RenderStyle* parentStyle);
189
190    PassRefPtr<RenderStyle> styleForPage(int pageIndex);
191    PassRefPtr<RenderStyle> defaultStyleForElement();
192    PassRefPtr<RenderStyle> styleForText(Text*);
193
194    static PassRefPtr<RenderStyle> styleForDocument(Document*, CSSFontSelector* = 0);
195
196    RenderStyle* style() const { return m_state.style(); }
197    RenderStyle* parentStyle() const { return m_state.parentStyle(); }
198    RenderStyle* rootElementStyle() const { return m_state.rootElementStyle(); }
199    Element* element() { return m_state.element(); }
200    Document* document() { return m_document; }
201    StyleScopeResolver* scopeResolver() const { return m_scopeResolver.get(); }
202    bool hasParentNode() const { return m_state.parentNode(); }
203
204    // FIXME: It could be better to call m_ruleSets.appendAuthorStyleSheets() directly after we factor StyleRsolver further.
205    // https://bugs.webkit.org/show_bug.cgi?id=108890
206    void appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >&);
207
208    DocumentRuleSets& ruleSets() { return m_ruleSets; }
209    const DocumentRuleSets& ruleSets() const { return m_ruleSets; }
210    SelectorFilter& selectorFilter() { return m_selectorFilter; }
211
212#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
213    StyleScopeResolver* ensureScopeResolver()
214    {
215#if ENABLE(STYLE_SCOPED)
216#if ENABLE(SHADOW_DOM)
217        ASSERT(RuntimeEnabledFeatures::shadowDOMEnabled() || RuntimeEnabledFeatures::styleScopedEnabled());
218#else
219        ASSERT(RuntimeEnabledFeatures::styleScopedEnabled());
220#endif
221#else
222        ASSERT(RuntimeEnabledFeatures::shadowDOMEnabled());
223#endif
224        if (!m_scopeResolver)
225            m_scopeResolver = adoptPtr(new StyleScopeResolver());
226        return m_scopeResolver.get();
227    }
228#endif
229
230private:
231    void initElement(Element*);
232    RenderStyle* locateSharedStyle();
233    bool styleSharingCandidateMatchesRuleSet(RuleSet*);
234    bool styleSharingCandidateMatchesHostRules();
235    Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const;
236    StyledElement* findSiblingForStyleSharing(Node*, unsigned& count) const;
237    bool canShareStyleWithElement(StyledElement*) const;
238
239    PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const StyleKeyframe*, KeyframeValue&);
240
241public:
242    // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
243    enum CSSRuleFilter {
244        UAAndUserCSSRules   = 1 << 1,
245        AuthorCSSRules      = 1 << 2,
246        EmptyCSSRules       = 1 << 3,
247        CrossOriginCSSRules = 1 << 4,
248        AllButEmptyCSSRules = UAAndUserCSSRules | AuthorCSSRules | CrossOriginCSSRules,
249        AllCSSRules         = AllButEmptyCSSRules | EmptyCSSRules,
250    };
251    Vector<RefPtr<StyleRuleBase> > styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules);
252    Vector<RefPtr<StyleRuleBase> > pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
253
254    // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
255    // the correct font size scaled relative to the user's default (medium).
256    static float fontSizeForKeyword(Document*, int keyword, bool shouldUseFixedDefaultSize);
257
258    // Given a font size in pixel, this function will return legacy font size between 1 and 7.
259    static int legacyFontSize(Document*, int pixelFontSize, bool shouldUseFixedDefaultSize);
260
261public:
262    void applyPropertyToStyle(CSSPropertyID, CSSValue*, RenderStyle*);
263
264    void applyPropertyToCurrentStyle(CSSPropertyID, CSSValue*);
265
266    void updateFont();
267    void initializeFontStyle(Settings*);
268
269    static float getComputedSizeFromSpecifiedSize(Document*, float zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize = UseSmartMinimumForFontFize);
270
271    void setFontSize(FontDescription&, float size);
272
273private:
274    static float getComputedSizeFromSpecifiedSize(Document*, RenderStyle*, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules);
275
276public:
277    bool useSVGZoomRules();
278
279    static bool colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue*);
280    Color colorFromPrimitiveValue(CSSPrimitiveValue*, bool forVisitedLink = false) const;
281
282    bool hasSelectorForId(const AtomicString&) const;
283    bool hasSelectorForClass(const AtomicString&) const;
284    bool hasSelectorForAttribute(const AtomicString&) const;
285
286    CSSFontSelector* fontSelector() const { return m_fontSelector.get(); }
287#if ENABLE(CSS_DEVICE_ADAPTATION)
288    ViewportStyleResolver* viewportStyleResolver() { return m_viewportStyleResolver.get(); }
289#endif
290
291    void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result);
292    bool hasViewportDependentMediaQueries() const { return !m_viewportDependentMediaQueryResults.isEmpty(); }
293    bool affectedByViewportChange() const;
294
295    void addKeyframeStyle(PassRefPtr<StyleRuleKeyframes>);
296
297    bool checkRegionStyle(Element* regionElement);
298
299    bool usesSiblingRules() const { return !m_ruleSets.features().siblingRules.isEmpty(); }
300    bool usesFirstLineRules() const { return m_ruleSets.features().usesFirstLineRules; }
301    bool usesBeforeAfterRules() const { return m_ruleSets.features().usesBeforeAfterRules; }
302
303    void invalidateMatchedPropertiesCache();
304
305#if ENABLE(CSS_FILTERS)
306    bool createFilterOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, FilterOperations& outOperations);
307#if ENABLE(CSS_SHADERS)
308    StyleShader* styleShader(CSSValue*);
309    StyleShader* cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue*);
310    bool parseCustomFilterParameterList(CSSValue*, CustomFilterParameterList&);
311    PassRefPtr<CustomFilterParameter> parseCustomFilterParameter(const String& name, CSSValue*);
312    PassRefPtr<CustomFilterParameter> parseCustomFilterColorParameter(const String& name, CSSValueList*);
313    PassRefPtr<CustomFilterParameter> parseCustomFilterArrayParameter(const String& name, CSSValueList*, bool);
314    PassRefPtr<CustomFilterParameter> parseCustomFilterNumberParameter(const String& name, CSSValueList*);
315    PassRefPtr<CustomFilterParameter> parseCustomFilterTransformParameter(const String& name, CSSValueList*);
316    PassRefPtr<CustomFilterOperation> createCustomFilterOperationWithAtRuleReferenceSyntax(WebKitCSSFilterValue*);
317    PassRefPtr<CustomFilterOperation> createCustomFilterOperationWithInlineSyntax(WebKitCSSFilterValue*);
318    PassRefPtr<CustomFilterOperation> createCustomFilterOperation(WebKitCSSFilterValue*);
319    void loadPendingShaders();
320    PassRefPtr<CustomFilterProgram> lookupCustomFilterProgram(WebKitCSSShaderValue* vertexShader, WebKitCSSShaderValue* fragmentShader,
321        CustomFilterProgramType, const CustomFilterProgramMixSettings&, CustomFilterMeshType);
322#endif
323#if ENABLE(SVG)
324    void loadPendingSVGDocuments();
325#endif
326#endif // ENABLE(CSS_FILTERS)
327
328    void loadPendingResources();
329
330    struct RuleRange {
331        RuleRange(int& firstRuleIndex, int& lastRuleIndex): firstRuleIndex(firstRuleIndex), lastRuleIndex(lastRuleIndex) { }
332        int& firstRuleIndex;
333        int& lastRuleIndex;
334    };
335
336    struct MatchRanges {
337        MatchRanges() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1) { }
338        int firstUARule;
339        int lastUARule;
340        int firstAuthorRule;
341        int lastAuthorRule;
342        int firstUserRule;
343        int lastUserRule;
344        RuleRange UARuleRange() { return RuleRange(firstUARule, lastUARule); }
345        RuleRange authorRuleRange() { return RuleRange(firstAuthorRule, lastAuthorRule); }
346        RuleRange userRuleRange() { return RuleRange(firstUserRule, lastUserRule); }
347    };
348
349    struct MatchedProperties {
350        MatchedProperties();
351        ~MatchedProperties();
352
353        RefPtr<StylePropertySet> properties;
354        union {
355            struct {
356                unsigned linkMatchType : 2;
357                unsigned whitelistType : 2;
358            };
359            // Used to make sure all memory is zero-initialized since we compute the hash over the bytes of this object.
360            void* possiblyPaddedMember;
361        };
362    };
363
364    struct MatchResult {
365        MatchResult() : isCacheable(true) { }
366        Vector<MatchedProperties, 64> matchedProperties;
367        Vector<StyleRule*, 64> matchedRules;
368        MatchRanges ranges;
369        bool isCacheable;
370
371        void addMatchedProperties(const StylePropertySet* properties, StyleRule* = 0, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone);
372    };
373
374private:
375    // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
376    void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
377    void checkForZoomChange(RenderStyle*, RenderStyle* parentStyle);
378
379    void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
380
381    bool fastRejectSelector(const RuleData&) const;
382
383    void applyMatchedProperties(const MatchResult&, const Element*);
384
385    enum StyleApplicationPass {
386#if ENABLE(CSS_VARIABLES)
387        VariableDefinitions,
388#endif
389        HighPriorityProperties,
390        LowPriorityProperties
391    };
392    template <StyleApplicationPass pass>
393    void applyMatchedProperties(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
394    template <StyleApplicationPass pass>
395    void applyProperties(const StylePropertySet* properties, StyleRule*, bool isImportant, bool inheritedOnly, PropertyWhitelistType = PropertyWhitelistNone);
396#if ENABLE(CSS_VARIABLES)
397    void resolveVariables(CSSPropertyID, CSSValue*, Vector<std::pair<CSSPropertyID, String> >& knownExpressions);
398#endif
399    static bool isValidRegionStyleProperty(CSSPropertyID);
400#if ENABLE(VIDEO_TRACK)
401    static bool isValidCueStyleProperty(CSSPropertyID);
402#endif
403    void matchPageRules(MatchResult&, RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
404    void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>&, bool isLeftPage, bool isFirstPage, const String& pageName);
405    Settings* documentSettings() { return m_document->settings(); }
406
407    bool isLeftPage(int pageIndex) const;
408    bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
409    bool isFirstPage(int pageIndex) const;
410    String pageName(int pageIndex) const;
411
412    DocumentRuleSets m_ruleSets;
413
414    typedef HashMap<AtomicStringImpl*, RefPtr<StyleRuleKeyframes> > KeyframesRuleMap;
415    KeyframesRuleMap m_keyframesRuleMap;
416
417public:
418    typedef HashMap<CSSPropertyID, RefPtr<CSSValue> > PendingImagePropertyMap;
419#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
420    typedef HashMap<FilterOperation*, RefPtr<WebKitCSSSVGDocumentValue> > PendingSVGDocumentMap;
421#endif
422
423    class State {
424        WTF_MAKE_NONCOPYABLE(State);
425    public:
426        State()
427        : m_element(0)
428        , m_styledElement(0)
429        , m_parentNode(0)
430        , m_parentStyle(0)
431        , m_rootElementStyle(0)
432        , m_regionForStyling(0)
433        , m_elementLinkState(NotInsideLink)
434        , m_distributedToInsertionPoint(false)
435        , m_elementAffectedByClassRules(false)
436        , m_applyPropertyToRegularStyle(true)
437        , m_applyPropertyToVisitedLinkStyle(false)
438#if ENABLE(CSS_SHADERS)
439        , m_hasPendingShaders(false)
440#endif
441        , m_lineHeightValue(0)
442        , m_fontDirty(false)
443        , m_hasUAAppearance(false)
444        , m_backgroundData(BackgroundFillLayer) { }
445
446    public:
447        void initElement(Element*);
448        void initForStyleResolve(Document*, Element*, RenderStyle* parentStyle = 0, RenderRegion* regionForStyling = 0);
449        void clear();
450
451        Document* document() const { return m_element->document(); }
452        Element* element() const { return m_element; }
453        StyledElement* styledElement() const { return m_styledElement; }
454        void setStyle(PassRefPtr<RenderStyle> style) { m_style = style; }
455        RenderStyle* style() const { return m_style.get(); }
456        PassRefPtr<RenderStyle> takeStyle() { return m_style.release(); }
457
458        const ContainerNode* parentNode() const { return m_parentNode; }
459        void setParentStyle(PassRefPtr<RenderStyle> parentStyle) { m_parentStyle = parentStyle; }
460        RenderStyle* parentStyle() const { return m_parentStyle.get(); }
461        RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
462
463        const RenderRegion* regionForStyling() const { return m_regionForStyling; }
464        EInsideLink elementLinkState() const { return m_elementLinkState; }
465        bool distributedToInsertionPoint() const { return m_distributedToInsertionPoint; }
466        void setElementAffectedByClassRules(bool isAffected) { m_elementAffectedByClassRules = isAffected; }
467        bool elementAffectedByClassRules() const { return m_elementAffectedByClassRules; }
468
469        void setApplyPropertyToRegularStyle(bool isApply) { m_applyPropertyToRegularStyle = isApply; }
470        void setApplyPropertyToVisitedLinkStyle(bool isApply) { m_applyPropertyToVisitedLinkStyle = isApply; }
471        bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
472        bool applyPropertyToVisitedLinkStyle() const { return m_applyPropertyToVisitedLinkStyle; }
473        PendingImagePropertyMap& pendingImageProperties() { return m_pendingImageProperties; }
474#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
475        PendingSVGDocumentMap& pendingSVGDocuments() { return m_pendingSVGDocuments; }
476#endif
477#if ENABLE(CSS_SHADERS)
478        void setHasPendingShaders(bool hasPendingShaders) { m_hasPendingShaders = hasPendingShaders; }
479        bool hasPendingShaders() const { return m_hasPendingShaders; }
480#endif
481
482        void setLineHeightValue(CSSValue* value) { m_lineHeightValue = value; }
483        CSSValue* lineHeightValue() { return m_lineHeightValue; }
484        void setFontDirty(bool isDirty) { m_fontDirty = isDirty; }
485        bool fontDirty() const { return m_fontDirty; }
486
487        void cacheBorderAndBackground();
488        bool hasUAAppearance() const { return m_hasUAAppearance; }
489        BorderData borderData() const { return m_borderData; }
490        FillLayer backgroundData() const { return m_backgroundData; }
491        Color backgroundColor() const { return m_backgroundColor; }
492
493        const FontDescription& fontDescription() { return m_style->fontDescription(); }
494        const FontDescription& parentFontDescription() { return m_parentStyle->fontDescription(); }
495        void setFontDescription(const FontDescription& fontDescription) { m_fontDirty |= m_style->setFontDescription(fontDescription); }
496        void setZoom(float f) { m_fontDirty |= m_style->setZoom(f); }
497        void setEffectiveZoom(float f) { m_fontDirty |= m_style->setEffectiveZoom(f); }
498        void setWritingMode(WritingMode writingMode) { m_fontDirty |= m_style->setWritingMode(writingMode); }
499        void setTextOrientation(TextOrientation textOrientation) { m_fontDirty |= m_style->setTextOrientation(textOrientation); }
500
501        bool useSVGZoomRules() const { return m_element && m_element->isSVGElement(); }
502
503    private:
504        // FIXME(bug 108563): to make it easier to review, these member
505        // variables are public. However we should add methods to access
506        // these variables.
507        Element* m_element;
508        RefPtr<RenderStyle> m_style;
509        StyledElement* m_styledElement;
510        ContainerNode* m_parentNode;
511        RefPtr<RenderStyle> m_parentStyle;
512        RenderStyle* m_rootElementStyle;
513
514        // Required to ASSERT in applyProperties.
515        RenderRegion* m_regionForStyling;
516
517        EInsideLink m_elementLinkState;
518
519        bool m_distributedToInsertionPoint;
520
521        bool m_elementAffectedByClassRules;
522
523        bool m_applyPropertyToRegularStyle;
524        bool m_applyPropertyToVisitedLinkStyle;
525
526        PendingImagePropertyMap m_pendingImageProperties;
527#if ENABLE(CSS_SHADERS)
528        bool m_hasPendingShaders;
529#endif
530#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
531        PendingSVGDocumentMap m_pendingSVGDocuments;
532#endif
533        CSSValue* m_lineHeightValue;
534        bool m_fontDirty;
535
536        bool m_hasUAAppearance;
537        BorderData m_borderData;
538        FillLayer m_backgroundData;
539        Color m_backgroundColor;
540    };
541
542    static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; }
543
544    PassRefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue*);
545    PassRefPtr<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue*);
546    PassRefPtr<StyleImage> generatedOrPendingFromValue(CSSPropertyID, CSSImageGeneratorValue*);
547#if ENABLE(CSS_IMAGE_SET)
548    PassRefPtr<StyleImage> setOrPendingFromValue(CSSPropertyID, CSSImageSetValue*);
549#endif
550    PassRefPtr<StyleImage> cursorOrPendingFromValue(CSSPropertyID, CSSCursorImageValue*);
551
552    bool applyPropertyToRegularStyle() const { return m_state.applyPropertyToRegularStyle(); }
553    bool applyPropertyToVisitedLinkStyle() const { return m_state.applyPropertyToVisitedLinkStyle(); }
554
555    static Length convertToIntLength(const CSSPrimitiveValue*, const RenderStyle*, const RenderStyle* rootStyle, double multiplier = 1);
556    static Length convertToFloatLength(const CSSPrimitiveValue*, const RenderStyle*, const RenderStyle* rootStyle, double multiplier = 1);
557
558    CSSToStyleMap* styleMap() { return &m_styleMap; }
559    InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; }
560    const FontDescription& fontDescription() { return m_state.fontDescription(); }
561    const FontDescription& parentFontDescription() { return m_state.parentFontDescription(); }
562    void setFontDescription(const FontDescription& fontDescription) { m_state.setFontDescription(fontDescription); }
563    void setZoom(float f) { m_state.setZoom(f); }
564    void setEffectiveZoom(float f) { m_state.setEffectiveZoom(f); }
565    void setWritingMode(WritingMode writingMode) { m_state.setWritingMode(writingMode); }
566    void setTextOrientation(TextOrientation textOrientation) { m_state.setTextOrientation(textOrientation); }
567
568private:
569    static RenderStyle* s_styleNotYetAvailable;
570
571    void cacheBorderAndBackground();
572
573private:
574    bool canShareStyleWithControl(StyledElement*) const;
575
576    void applyProperty(CSSPropertyID, CSSValue*);
577
578#if ENABLE(SVG)
579    void applySVGProperty(CSSPropertyID, CSSValue*);
580#endif
581
582    PassRefPtr<StyleImage> loadPendingImage(StylePendingImage*);
583    void loadPendingImages();
584
585    static unsigned computeMatchedPropertiesHash(const MatchedProperties*, unsigned size);
586    struct MatchedPropertiesCacheItem {
587        Vector<MatchedProperties> matchedProperties;
588        MatchRanges ranges;
589        RefPtr<RenderStyle> renderStyle;
590        RefPtr<RenderStyle> parentRenderStyle;
591    };
592    const MatchedPropertiesCacheItem* findFromMatchedPropertiesCache(unsigned hash, const MatchResult&);
593    void addToMatchedPropertiesCache(const RenderStyle*, const RenderStyle* parentStyle, unsigned hash, const MatchResult&);
594
595    // Every N additions to the matched declaration cache trigger a sweep where entries holding
596    // the last reference to a style declaration are garbage collected.
597    void sweepMatchedPropertiesCache(Timer<StyleResolver>*);
598
599    bool classNamesAffectedByRules(const SpaceSplitString&) const;
600    bool sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement*) const;
601
602    unsigned m_matchedPropertiesCacheAdditionsSinceLastSweep;
603
604    typedef HashMap<unsigned, MatchedPropertiesCacheItem> MatchedPropertiesCache;
605    MatchedPropertiesCache m_matchedPropertiesCache;
606
607    Timer<StyleResolver> m_matchedPropertiesCacheSweepTimer;
608
609    OwnPtr<MediaQueryEvaluator> m_medium;
610    RefPtr<RenderStyle> m_rootDefaultStyle;
611
612    Document* m_document;
613    SelectorFilter m_selectorFilter;
614
615    bool m_matchAuthorAndUserStyles;
616
617    RefPtr<CSSFontSelector> m_fontSelector;
618    Vector<OwnPtr<MediaQueryResult> > m_viewportDependentMediaQueryResults;
619
620#if ENABLE(CSS_DEVICE_ADAPTATION)
621    RefPtr<ViewportStyleResolver> m_viewportStyleResolver;
622#endif
623
624    const DeprecatedStyleBuilder& m_deprecatedStyleBuilder;
625
626    OwnPtr<StyleScopeResolver> m_scopeResolver;
627    CSSToStyleMap m_styleMap;
628    InspectorCSSOMWrappers m_inspectorCSSOMWrappers;
629
630    State m_state;
631
632#if ENABLE(CSS_SHADERS)
633    OwnPtr<StyleCustomFilterProgramCache> m_customFilterProgramCache;
634#endif
635
636    friend class DeprecatedStyleBuilder;
637    friend bool operator==(const MatchedProperties&, const MatchedProperties&);
638    friend bool operator!=(const MatchedProperties&, const MatchedProperties&);
639    friend bool operator==(const MatchRanges&, const MatchRanges&);
640    friend bool operator!=(const MatchRanges&, const MatchRanges&);
641};
642
643inline bool StyleResolver::hasSelectorForAttribute(const AtomicString &attributeName) const
644{
645    ASSERT(!attributeName.isEmpty());
646    return m_ruleSets.features().attrsInRules.contains(attributeName.impl());
647}
648
649inline bool StyleResolver::hasSelectorForClass(const AtomicString& classValue) const
650{
651    ASSERT(!classValue.isEmpty());
652    return m_ruleSets.features().classesInRules.contains(classValue.impl());
653}
654
655inline bool StyleResolver::hasSelectorForId(const AtomicString& idValue) const
656{
657    ASSERT(!idValue.isEmpty());
658    return m_ruleSets.features().idsInRules.contains(idValue.impl());
659}
660
661inline bool checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement)
662{
663    if (!regionSelector || !regionElement)
664        return false;
665
666    SelectorChecker selectorChecker(regionElement->document(), SelectorChecker::QueryingRules);
667    for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
668        SelectorChecker::SelectorCheckingContext selectorCheckingContext(s, regionElement, SelectorChecker::VisitedMatchDisabled);
669        PseudoId ignoreDynamicPseudo = NOPSEUDO;
670        if (selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo) == SelectorChecker::SelectorMatches)
671            return true;
672    }
673    return false;
674}
675
676} // namespace WebCore
677
678#endif // StyleResolver_h
679