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