c5bf8dcf880d783260110abb44a6f63c364acf9e
[WebKit-https.git] / Source / WebCore / css / StyleResolver.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11  * Copyright (C) 2012 Google Inc. All rights reserved.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public License
24  * along with this library; see the file COPYING.LIB.  If not, write to
25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 #include "config.h"
30 #include "StyleResolver.h"
31
32 #include "Attribute.h"
33 #include "CSSBorderImage.h"
34 #include "CSSCalculationValue.h"
35 #include "CSSCursorImageValue.h"
36 #include "CSSDefaultStyleSheets.h"
37 #include "CSSFilterImageValue.h"
38 #include "CSSFontFaceRule.h"
39 #include "CSSFontFeatureValue.h"
40 #include "CSSFontSelector.h"
41 #include "CSSFontValue.h"
42 #include "CSSGridTemplateValue.h"
43 #include "CSSLineBoxContainValue.h"
44 #include "CSSPageRule.h"
45 #include "CSSParser.h"
46 #include "CSSPrimitiveValueMappings.h"
47 #include "CSSPropertyNames.h"
48 #include "CSSReflectValue.h"
49 #include "CSSSelector.h"
50 #include "CSSSelectorList.h"
51 #include "CSSShadowValue.h"
52 #include "CSSStyleRule.h"
53 #include "CSSSupportsRule.h"
54 #include "CSSTimingFunctionValue.h"
55 #include "CSSValueList.h"
56 #include "CachedImage.h"
57 #include "CalculationValue.h"
58 #include "ContentData.h"
59 #include "Counter.h"
60 #include "CounterContent.h"
61 #include "CursorList.h"
62 #include "DeprecatedStyleBuilder.h"
63 #include "DocumentStyleSheetCollection.h"
64 #include "ElementRuleCollector.h"
65 #include "Frame.h"
66 #include "FrameSelection.h"
67 #include "FrameView.h"
68 #include "HTMLDocument.h"
69 #include "HTMLIFrameElement.h"
70 #include "HTMLInputElement.h"
71 #include "HTMLNames.h"
72 #include "HTMLOptGroupElement.h"
73 #include "HTMLOptionElement.h"
74 #include "HTMLProgressElement.h"
75 #include "HTMLStyleElement.h"
76 #include "HTMLTableElement.h"
77 #include "HTMLTextAreaElement.h"
78 #include "InsertionPoint.h"
79 #include "InspectorInstrumentation.h"
80 #include "KeyframeList.h"
81 #include "LinkHash.h"
82 #include "LocaleToScriptMapping.h"
83 #include "MathMLNames.h"
84 #include "MediaList.h"
85 #include "MediaQueryEvaluator.h"
86 #include "NodeRenderStyle.h"
87 #include "NodeRenderingTraversal.h"
88 #include "Page.h"
89 #include "PageRuleCollector.h"
90 #include "Pair.h"
91 #include "QuotesData.h"
92 #include "Rect.h"
93 #include "RenderRegion.h"
94 #include "RenderScrollbar.h"
95 #include "RenderScrollbarTheme.h"
96 #include "RenderStyleConstants.h"
97 #include "RenderTheme.h"
98 #include "RenderView.h"
99 #include "RuleSet.h"
100 #include "SVGDocumentExtensions.h"
101 #include "SVGFontFaceElement.h"
102 #include "SecurityOrigin.h"
103 #include "SelectorCheckerFastPath.h"
104 #include "Settings.h"
105 #include "ShadowData.h"
106 #include "ShadowRoot.h"
107 #include "StyleCachedImage.h"
108 #include "StyleFontSizeFunctions.h"
109 #include "StyleGeneratedImage.h"
110 #include "StylePendingImage.h"
111 #include "StyleProperties.h"
112 #include "StylePropertyShorthand.h"
113 #include "StyleRule.h"
114 #include "StyleRuleImport.h"
115 #include "StyleSheetContents.h"
116 #include "StyleSheetList.h"
117 #include "Text.h"
118 #include "TransformFunctions.h"
119 #include "TransformOperations.h"
120 #include "UserAgentStyleSheets.h"
121 #include "ViewportStyleResolver.h"
122 #include "VisitedLinkState.h"
123 #include "WebKitCSSKeyframeRule.h"
124 #include "WebKitCSSKeyframesRule.h"
125 #include "WebKitCSSRegionRule.h"
126 #include "WebKitCSSTransformValue.h"
127 #include "WebKitFontFamilyNames.h"
128 #include "XMLNames.h"
129 #include <wtf/StdLibExtras.h>
130 #include <wtf/Vector.h>
131
132 #if ENABLE(CSS_FILTERS)
133 #include "FilterOperation.h"
134 #include "WebKitCSSFilterValue.h"
135 #endif
136
137 #if ENABLE(CSS_IMAGE_SET)
138 #include "CSSImageSetValue.h"
139 #include "StyleCachedImageSet.h"
140 #endif
141
142 #if ENABLE(CSS_SHADERS)
143 #include "CustomFilterArrayParameter.h"
144 #include "CustomFilterColorParameter.h"
145 #include "CustomFilterConstants.h"
146 #include "CustomFilterNumberParameter.h"
147 #include "CustomFilterOperation.h"
148 #include "CustomFilterParameter.h"
149 #include "CustomFilterProgramInfo.h"
150 #include "CustomFilterTransformParameter.h"
151 #include "StyleCachedShader.h"
152 #include "StyleCustomFilterProgram.h"
153 #include "StyleCustomFilterProgramCache.h"
154 #include "StylePendingShader.h"
155 #include "StyleShader.h"
156 #include "WebKitCSSMixFunctionValue.h"
157 #include "WebKitCSSShaderValue.h"
158 #endif
159
160 #if ENABLE(CSS_SHAPES)
161 #include "CachedResourceLoader.h"
162 #endif
163
164 #if ENABLE(DASHBOARD_SUPPORT)
165 #include "DashboardRegion.h"
166 #endif
167
168 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
169 #include "HTMLAudioElement.h"
170 #endif
171
172 #if ENABLE(SVG)
173 #include "CachedSVGDocument.h"
174 #include "CachedSVGDocumentReference.h"
175 #include "SVGDocument.h"
176 #include "SVGElement.h"
177 #include "SVGNames.h"
178 #include "SVGURIReference.h"
179 #include "WebKitCSSSVGDocumentValue.h"
180 #endif
181
182 #if ENABLE(VIDEO_TRACK)
183 #include "WebVTTElement.h"
184 #endif
185
186 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
187 #include "HTMLMediaElement.h"
188 #endif
189
190 namespace WebCore {
191
192 using namespace HTMLNames;
193
194 #define HANDLE_INHERIT(prop, Prop) \
195 if (isInherit) { \
196     m_state.style()->set##Prop(m_state.parentStyle()->prop()); \
197     return; \
198 }
199
200 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
201 HANDLE_INHERIT(prop, Prop) \
202 if (isInitial) { \
203     m_state.style()->set##Prop(RenderStyle::initial##Prop()); \
204     return; \
205 }
206
207 RenderStyle* StyleResolver::s_styleNotYetAvailable;
208
209 inline void StyleResolver::State::cacheBorderAndBackground()
210 {
211     m_hasUAAppearance = m_style->hasAppearance();
212     if (m_hasUAAppearance) {
213         m_borderData = m_style->border();
214         m_backgroundData = *m_style->backgroundLayers();
215         m_backgroundColor = m_style->backgroundColor();
216     }
217 }
218
219 inline void StyleResolver::State::clear()
220 {
221     m_element = 0;
222     m_styledElement = 0;
223     m_parentStyle = 0;
224     m_parentNode = 0;
225     m_regionForStyling = 0;
226     m_pendingImageProperties.clear();
227 #if ENABLE(CSS_SHADERS)
228     m_hasPendingShaders = false;
229 #endif
230 #if ENABLE(CSS_FILTERS) && ENABLE(SVG)
231     m_pendingSVGDocuments.clear();
232 #endif
233 }
234
235 void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
236 {
237     matchedProperties.grow(matchedProperties.size() + 1);
238     StyleResolver::MatchedProperties& newProperties = matchedProperties.last();
239     newProperties.properties = const_cast<StyleProperties*>(&properties);
240     newProperties.linkMatchType = linkMatchType;
241     newProperties.whitelistType = propertyWhitelistType;
242     matchedRules.append(rule);
243 }
244
245 StyleResolver::StyleResolver(Document& document, bool matchAuthorAndUserStyles)
246     : m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
247     , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
248     , m_document(document)
249     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
250     , m_fontSelector(CSSFontSelector::create(&m_document))
251 #if ENABLE(CSS_DEVICE_ADAPTATION)
252     , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
253 #endif
254     , m_deprecatedStyleBuilder(DeprecatedStyleBuilder::sharedStyleBuilder())
255     , m_styleMap(this)
256 {
257     Element* root = m_document.documentElement();
258
259     CSSDefaultStyleSheets::initDefaultStyle(root);
260
261     // construct document root element default style. this is needed
262     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
263     // This is here instead of constructor, because when constructor is run,
264     // document doesn't have documentElement
265     // NOTE: this assumes that element that gets passed to styleForElement -call
266     // is always from the document that owns the style selector
267     FrameView* view = m_document.view();
268     if (view)
269         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
270     else
271         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
272
273     if (root)
274         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
275
276     if (m_rootDefaultStyle && view)
277         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame(), m_rootDefaultStyle.get()));
278
279     m_ruleSets.resetAuthorStyle();
280
281     DocumentStyleSheetCollection& styleSheetCollection = m_document.styleSheetCollection();
282     m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this);
283
284 #if ENABLE(SVG_FONTS)
285     if (m_document.svgExtensions()) {
286         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements();
287         HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
288         for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
289             fontSelector()->addFontFaceRule((*it)->fontFaceRule());
290     }
291 #endif
292
293     appendAuthorStyleSheets(0, styleSheetCollection.activeAuthorStyleSheets());
294 }
295
296 void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet>>& styleSheets)
297 {
298     m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, document().isViewSource(), this);
299     if (auto renderView = document().renderView())
300         renderView->style().font().update(fontSelector());
301
302 #if ENABLE(CSS_DEVICE_ADAPTATION)
303     viewportStyleResolver()->resolve();
304 #endif
305 }
306
307 void StyleResolver::pushParentElement(Element* parent)
308 {
309     const ContainerNode* parentsParent = parent->parentOrShadowHostElement();
310
311     // We are not always invoked consistently. For example, script execution can cause us to enter
312     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
313     // Reset the stack in this case, or if we see a new root element.
314     // Otherwise just push the new parent.
315     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
316         m_selectorFilter.setupParentStack(parent);
317     else
318         m_selectorFilter.pushParent(parent);
319
320     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
321     if (m_scopeResolver)
322         m_scopeResolver->push(parent, parent->parentOrShadowHostNode());
323 }
324
325 void StyleResolver::popParentElement(Element* parent)
326 {
327     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
328     // Pause maintaining the stack in this case.
329     if (m_selectorFilter.parentStackIsConsistent(parent))
330         m_selectorFilter.popParent();
331     if (m_scopeResolver)
332         m_scopeResolver->pop(parent);
333 }
334
335 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
336 {
337     ASSERT(shadowRoot->hostElement());
338     if (m_scopeResolver)
339         m_scopeResolver->push(shadowRoot, shadowRoot->hostElement());
340 }
341
342 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
343 {
344     ASSERT(shadowRoot->hostElement());
345     if (m_scopeResolver)
346         m_scopeResolver->pop(shadowRoot);
347 }
348
349 // This is a simplified style setting function for keyframe styles
350 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
351 {
352     AtomicString s(rule->name());
353     m_keyframesRuleMap.set(s.impl(), rule);
354 }
355
356 StyleResolver::~StyleResolver()
357 {
358     m_fontSelector->clearDocument();
359
360 #if ENABLE(CSS_DEVICE_ADAPTATION)
361     m_viewportStyleResolver->clearDocument();
362 #endif
363 }
364
365 void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
366 {
367     // Look for cache entries containing a style declaration with a single ref and remove them.
368     // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
369     // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
370     Vector<unsigned, 16> toRemove;
371     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
372     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
373     for (; it != end; ++it) {
374         Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
375         for (size_t i = 0; i < matchedProperties.size(); ++i) {
376             if (matchedProperties[i].properties->hasOneRef()) {
377                 toRemove.append(it->key);
378                 break;
379             }
380         }
381     }
382     for (size_t i = 0; i < toRemove.size(); ++i)
383         m_matchedPropertiesCache.remove(toRemove[i]);
384
385     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
386 }
387
388 inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
389 {
390 #if ENABLE(SHADOW_DOM)
391     return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_state.element());
392 #else
393     return false;
394 #endif
395 }
396
397 bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
398 {
399     for (unsigned i = 0; i < classNames.size(); ++i) {
400         if (m_ruleSets.features().classesInRules.contains(classNames[i].impl()))
401             return true;
402     }
403     return false;
404 }
405
406 inline void StyleResolver::State::initElement(Element* e)
407 {
408     m_element = e;
409     m_styledElement = e && e->isStyledElement() ? toStyledElement(e) : nullptr;
410     m_elementLinkState = e ? e->document().visitedLinkState().determineLinkState(e) : NotInsideLink;
411 }
412
413 inline void StyleResolver::initElement(Element* e)
414 {
415     if (m_state.element() != e) {
416         m_state.initElement(e);
417         if (e && e == e->document().documentElement()) {
418             e->document().setDirectionSetOnDocumentElement(false);
419             e->document().setWritingModeSetOnDocumentElement(false);
420         }
421     }
422 }
423
424 inline void StyleResolver::State::initForStyleResolve(Document& document, Element* e, RenderStyle* parentStyle, RenderRegion* regionForStyling)
425 {
426     m_regionForStyling = regionForStyling;
427
428     if (e) {
429         m_parentNode = NodeRenderingTraversal::parent(e);
430         bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance();
431         m_parentStyle = resetStyleInheritance ? 0 :
432             parentStyle ? parentStyle :
433             m_parentNode ? m_parentNode->renderStyle() : 0;
434     } else {
435         m_parentNode = 0;
436         m_parentStyle = parentStyle;
437     }
438
439     Node* docElement = e ? e->document().documentElement() : 0;
440     RenderStyle* docStyle = document.renderStyle();
441     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
442
443     m_style = 0;
444     m_pendingImageProperties.clear();
445     m_fontDirty = false;
446 }
447
448 static const unsigned cStyleSearchThreshold = 10;
449 static const unsigned cStyleSearchLevelThreshold = 10;
450
451 static inline bool parentElementPreventsSharing(const Element* parentElement)
452 {
453     if (!parentElement)
454         return false;
455     return parentElement->hasFlagsSetDuringStylingOfChildren();
456 }
457
458 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
459 {
460     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
461         return 0;
462     if (!parent || !parent->isStyledElement())
463         return 0;
464     StyledElement* p = toStyledElement(parent);
465     if (p->inlineStyle())
466         return 0;
467 #if ENABLE(SVG)
468     if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties())
469         return 0;
470 #endif
471     if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleResolution().impl()))
472         return 0;
473
474     RenderStyle* parentStyle = p->renderStyle();
475     unsigned subcount = 0;
476     Node* thisCousin = p;
477     Node* currentNode = p->previousSibling();
478
479     // Reserve the tries for this level. This effectively makes sure that the algorithm
480     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
481     visitedNodeCount += cStyleSearchThreshold;
482     while (thisCousin) {
483         while (currentNode) {
484             ++subcount;
485             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()
486                 && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode))
487 #if ENABLE(SHADOW_DOM)
488                 && !toElement(currentNode)->authorShadowRoot()
489 #endif
490                 ) {
491                 // Adjust for unused reserved tries.
492                 visitedNodeCount -= cStyleSearchThreshold - subcount;
493                 return currentNode->lastChild();
494             }
495             if (subcount >= cStyleSearchThreshold)
496                 return 0;
497             currentNode = currentNode->previousSibling();
498         }
499         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
500         thisCousin = currentNode;
501     }
502
503     return 0;
504 }
505
506 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
507 {
508     if (!ruleSet)
509         return false;
510
511     ElementRuleCollector collector(this, m_state);
512     return collector.hasAnyMatchingRules(ruleSet);
513 }
514
515 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
516 {
517     const State& state = m_state;
518     HTMLInputElement* thisInputElement = element->toInputElement();
519     HTMLInputElement* otherInputElement = state.element()->toInputElement();
520
521     if (!thisInputElement || !otherInputElement)
522         return false;
523
524     if (thisInputElement->elementData() != otherInputElement->elementData()) {
525         if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
526             return false;
527         if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
528             return false;
529     }
530
531     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
532         return false;
533     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
534         return false;
535     if (thisInputElement->shouldAppearIndeterminate() != otherInputElement->shouldAppearIndeterminate())
536         return false;
537     if (thisInputElement->isRequired() != otherInputElement->isRequired())
538         return false;
539
540     if (element->isDisabledFormControl() != state.element()->isDisabledFormControl())
541         return false;
542
543     if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonForForm())
544         return false;
545
546     if (state.document().containsValidityStyleRules()) {
547         bool willValidate = element->willValidate();
548
549         if (willValidate != state.element()->willValidate())
550             return false;
551
552         if (willValidate && (element->isValidFormControlElement() != state.element()->isValidFormControlElement()))
553             return false;
554
555         if (element->isInRange() != state.element()->isInRange())
556             return false;
557
558         if (element->isOutOfRange() != state.element()->isOutOfRange())
559             return false;
560     }
561
562     return true;
563 }
564
565 static inline bool elementHasDirectionAuto(Element* element)
566 {
567     // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
568     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
569 }
570
571 bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement* sharingCandidate) const
572 {
573     const State& state = m_state;
574     if (state.element()->elementData() == sharingCandidate->elementData())
575         return true;
576     if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate->fastGetAttribute(XMLNames::langAttr))
577         return false;
578     if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGetAttribute(langAttr))
579         return false;
580
581     if (!state.elementAffectedByClassRules()) {
582         if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCandidate->classNames()))
583             return false;
584     } else if (sharingCandidate->hasClass()) {
585 #if ENABLE(SVG)
586         // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
587         if (state.element()->isSVGElement()) {
588             if (state.element()->getAttribute(classAttr) != sharingCandidate->getAttribute(classAttr))
589                 return false;
590         } else {
591 #endif
592             if (state.element()->classNames() != sharingCandidate->classNames())
593                 return false;
594 #if ENABLE(SVG)
595         }
596 #endif
597     } else
598         return false;
599
600     if (state.styledElement()->presentationAttributeStyle() != sharingCandidate->presentationAttributeStyle())
601         return false;
602
603 #if ENABLE(PROGRESS_ELEMENT)
604     if (state.element()->hasTagName(progressTag)) {
605         if (state.element()->shouldAppearIndeterminate() != sharingCandidate->shouldAppearIndeterminate())
606             return false;
607     }
608 #endif
609
610     return true;
611 }
612
613 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
614 {
615     RenderStyle* style = element->renderStyle();
616     const State& state = m_state;
617
618     if (!style)
619         return false;
620     if (style->unique())
621         return false;
622     if (style->hasUniquePseudoStyle())
623         return false;
624     if (element->tagQName() != state.element()->tagQName())
625         return false;
626     if (element->inlineStyle())
627         return false;
628     if (element->needsStyleRecalc())
629         return false;
630 #if ENABLE(SVG)
631     if (element->isSVGElement() && toSVGElement(element)->animatedSMILStyleProperties())
632         return false;
633 #endif
634     if (element->isLink() != state.element()->isLink())
635         return false;
636     if (element->hovered() != state.element()->hovered())
637         return false;
638     if (element->active() != state.element()->active())
639         return false;
640     if (element->focused() != state.element()->focused())
641         return false;
642     if (element->shadowPseudoId() != state.element()->shadowPseudoId())
643         return false;
644     if (element == element->document().cssTarget())
645         return false;
646     if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element))
647         return false;
648     if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle())
649         return false;
650
651     if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl()))
652         return false;
653
654     // FIXME: We should share style for option and optgroup whenever possible.
655     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
656     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
657     if (isHTMLOptionElement(element) || isHTMLOptGroupElement(element))
658         return false;
659
660     bool isControl = element->isFormControlElement();
661
662     if (isControl != state.element()->isFormControlElement())
663         return false;
664
665     if (isControl && !canShareStyleWithControl(element))
666         return false;
667
668     if (style->transitions() || style->animations())
669         return false;
670
671 #if USE(ACCELERATED_COMPOSITING)
672     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
673     // See comments in RenderObject::setStyle().
674     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag))
675         return false;
676
677 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
678     // With proxying, the media elements are backed by a RenderEmbeddedObject.
679     if ((element->hasTagName(videoTag) || element->hasTagName(audioTag)) && toMediaElement(element)->shouldUseVideoPluginProxy())
680         return false;
681 #endif
682
683 #endif
684
685     if (elementHasDirectionAuto(element))
686         return false;
687
688     if (element->isLink() && state.elementLinkState() != style->insideLink())
689         return false;
690
691 #if ENABLE(VIDEO_TRACK)
692     // Deny sharing styles between WebVTT and non-WebVTT nodes.
693     if (element->isWebVTTElement() != state.element()->isWebVTTElement())
694         return false;
695
696     if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWebVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNode())
697         return false;
698 #endif
699
700 #if ENABLE(FULLSCREEN_API)
701     if (element == element->document().webkitCurrentFullScreenElement() || state.element() == state.document().webkitCurrentFullScreenElement())
702         return false;
703 #endif
704     return true;
705 }
706
707 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
708 {
709     for (; node; node = node->previousSibling()) {
710         if (!node->isStyledElement())
711             continue;
712         if (canShareStyleWithElement(toStyledElement(node)))
713             break;
714         if (count++ == cStyleSearchThreshold)
715             return 0;
716     }
717     return toStyledElement(node);
718 }
719
720 RenderStyle* StyleResolver::locateSharedStyle()
721 {
722     State& state = m_state;
723     if (!state.styledElement() || !state.parentStyle())
724         return 0;
725
726     // If the element has inline style it is probably unique.
727     if (state.styledElement()->inlineStyle())
728         return 0;
729 #if ENABLE(SVG)
730     if (state.styledElement()->isSVGElement() && toSVGElement(state.styledElement())->animatedSMILStyleProperties())
731         return 0;
732 #endif
733     // Ids stop style sharing if they show up in the stylesheets.
734     if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl()))
735         return 0;
736     if (parentElementPreventsSharing(state.element()->parentElement()))
737         return 0;
738     if (state.element() == state.document().cssTarget())
739         return 0;
740     if (elementHasDirectionAuto(state.element()))
741         return 0;
742
743     // Cache whether state.element is affected by any known class selectors.
744     // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
745     state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames()));
746
747     // Check previous siblings and their cousins.
748     unsigned count = 0;
749     unsigned visitedNodeCount = 0;
750     StyledElement* shareElement = 0;
751     Node* cousinList = state.styledElement()->previousSibling();
752     while (cousinList) {
753         shareElement = findSiblingForStyleSharing(cousinList, count);
754         if (shareElement)
755             break;
756         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
757     }
758
759     // If we have exhausted all our budget or our cousins.
760     if (!shareElement)
761         return 0;
762
763     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
764     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling()))
765         return 0;
766     // Can't share if attribute rules apply.
767     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute()))
768         return 0;
769     // Can't share if @host @-rules apply.
770     if (styleSharingCandidateMatchesHostRules())
771         return 0;
772     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
773     if (parentElementPreventsSharing(state.element()->parentElement()))
774         return 0;
775     return shareElement->renderStyle();
776 }
777
778 static inline bool isAtShadowBoundary(const Element* element)
779 {
780     if (!element)
781         return false;
782     ContainerNode* parentNode = element->parentNode();
783     return parentNode && parentNode->isShadowRoot();
784 }
785
786 PassRef<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
787     StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
788 {
789     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
790     // will vanish if a style recalc happens during loading.
791     if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) {
792         if (!s_styleNotYetAvailable) {
793             s_styleNotYetAvailable = &RenderStyle::create().leakRef();
794             s_styleNotYetAvailable->setDisplay(NONE);
795             s_styleNotYetAvailable->font().update(m_fontSelector);
796         }
797         element->document().setHasNodesWithPlaceholderStyle();
798         return *s_styleNotYetAvailable;
799     }
800
801     State& state = m_state;
802     initElement(element);
803     state.initForStyleResolve(document(), element, defaultParent, regionForStyling);
804     if (sharingBehavior == AllowStyleSharing) {
805         if (RenderStyle* sharedStyle = locateSharedStyle()) {
806             state.clear();
807             return *sharedStyle;
808         }
809     }
810
811     if (state.parentStyle()) {
812         state.setStyle(RenderStyle::create());
813         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
814     } else {
815         state.setStyle(defaultStyleForElement());
816         state.setParentStyle(RenderStyle::clone(state.style()));
817     }
818
819     if (element->isLink()) {
820         state.style()->setIsLink(true);
821         EInsideLink linkState = state.elementLinkState();
822         if (linkState != NotInsideLink) {
823             bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
824             if (forceVisited)
825                 linkState = InsideVisitedLink;
826         }
827         state.style()->setInsideLink(linkState);
828     }
829
830     bool needsCollection = false;
831     CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection);
832     if (needsCollection)
833         m_ruleSets.collectFeatures(document().isViewSource(), m_scopeResolver.get());
834
835     ElementRuleCollector collector(this, state);
836     collector.setRegionForStyling(regionForStyling);
837     collector.setMedium(m_medium.get());
838
839     if (matchingBehavior == MatchOnlyUserAgentRules)
840         collector.matchUARules();
841     else
842         collector.matchAllRules(m_matchAuthorAndUserStyles, matchingBehavior != MatchAllRulesExcludingSMIL);
843
844     applyMatchedProperties(collector.matchedResult(), element);
845
846     // Clean up our style object's display and text decorations (among other fixups).
847     adjustRenderStyle(state.style(), state.parentStyle(), element);
848
849     state.clear(); // Clear out for the next resolve.
850
851     document().didAccessStyleResolver();
852
853     // Now return the style.
854     return state.takeStyle();
855 }
856
857 PassRef<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
858 {
859     MatchResult result;
860     result.addMatchedProperties(keyframe->properties());
861
862     ASSERT(!m_state.style());
863
864     State& state = m_state;
865
866     // Create the style
867     state.setStyle(RenderStyle::clone(elementStyle));
868     state.setLineHeightValue(0);
869
870     // We don't need to bother with !important. Since there is only ever one
871     // decl, there's nothing to override. So just add the first properties.
872     bool inheritedOnly = false;
873     applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
874
875     // If our font got dirtied, go ahead and update it now.
876     updateFont();
877
878     // Line-height is set when we are sure we decided on the font-size
879     if (state.lineHeightValue())
880         applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
881
882     // Now do rest of the properties.
883     applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
884
885     // If our font got dirtied by one of the non-essential font props,
886     // go ahead and update it a second time.
887     updateFont();
888
889     // Start loading resources referenced by this style.
890     loadPendingResources();
891     
892     // Add all the animating properties to the keyframe.
893     unsigned propertyCount = keyframe->properties().propertyCount();
894     for (unsigned i = 0; i < propertyCount; ++i) {
895         CSSPropertyID property = keyframe->properties().propertyAt(i).id();
896         // Timing-function within keyframes is special, because it is not animated; it just
897         // describes the timing function between this keyframe and the next.
898         if (property != CSSPropertyWebkitAnimationTimingFunction)
899             keyframeValue.addProperty(property);
900     }
901
902     document().didAccessStyleResolver();
903
904     return state.takeStyle();
905 }
906
907 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
908 {
909     list.clear();
910
911     // Get the keyframesRule for this name
912     if (!e || list.animationName().isEmpty())
913         return;
914
915     m_keyframesRuleMap.checkConsistency();
916
917     KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
918     if (it == m_keyframesRuleMap.end())
919         return;
920
921     const StyleRuleKeyframes* keyframesRule = it->value.get();
922
923     // Construct and populate the style for each keyframe
924     const Vector<RefPtr<StyleKeyframe>>& keyframes = keyframesRule->keyframes();
925     for (unsigned i = 0; i < keyframes.size(); ++i) {
926         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
927         initElement(e);
928         m_state.initForStyleResolve(document(), e);
929
930         const StyleKeyframe* keyframe = keyframes[i].get();
931
932         KeyframeValue keyframeValue(0, 0);
933         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
934
935         // Add this keyframe style to all the indicated key times
936         Vector<double> keys;
937         keyframe->getKeys(keys);
938         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
939             keyframeValue.setKey(keys[keyIndex]);
940             list.insert(keyframeValue);
941         }
942     }
943
944     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
945     int initialListSize = list.size();
946     if (initialListSize > 0 && list[0].key()) {
947         static StyleKeyframe* zeroPercentKeyframe;
948         if (!zeroPercentKeyframe) {
949             zeroPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
950             zeroPercentKeyframe->setKeyText("0%");
951         }
952         KeyframeValue keyframeValue(0, 0);
953         keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
954         list.insert(keyframeValue);
955     }
956
957     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
958     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
959         static StyleKeyframe* hundredPercentKeyframe;
960         if (!hundredPercentKeyframe) {
961             hundredPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
962             hundredPercentKeyframe->setKeyText("100%");
963         }
964         KeyframeValue keyframeValue(1, 0);
965         keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
966         list.insert(keyframeValue);
967     }
968 }
969
970 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
971 {
972     ASSERT(parentStyle);
973     if (!e)
974         return 0;
975
976     State& state = m_state;
977
978     initElement(e);
979
980     state.initForStyleResolve(document(), e, parentStyle);
981
982     if (m_state.parentStyle()) {
983         state.setStyle(RenderStyle::create());
984         state.style()->inheritFrom(m_state.parentStyle());
985     } else {
986         state.setStyle(defaultStyleForElement());
987         state.setParentStyle(RenderStyle::clone(state.style()));
988     }
989
990     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
991     // those rules.
992
993     // Check UA, user and author rules.
994     ElementRuleCollector collector(this, state);
995     collector.setPseudoStyleRequest(pseudoStyleRequest);
996     collector.setMedium(m_medium.get());
997     collector.matchUARules();
998
999     if (m_matchAuthorAndUserStyles) {
1000         collector.matchUserRules(false);
1001         collector.matchAuthorRules(false);
1002     }
1003
1004     if (collector.matchedResult().matchedProperties.isEmpty())
1005         return 0;
1006
1007     state.style()->setStyleType(pseudoStyleRequest.pseudoId);
1008
1009     applyMatchedProperties(collector.matchedResult(), e);
1010
1011     // Clean up our style object's display and text decorations (among other fixups).
1012     adjustRenderStyle(state.style(), m_state.parentStyle(), 0);
1013
1014     // Start loading resources referenced by this style.
1015     loadPendingResources();
1016
1017     document().didAccessStyleResolver();
1018
1019     // Now return the style.
1020     return state.takeStyle();
1021 }
1022
1023 PassRef<RenderStyle> StyleResolver::styleForPage(int pageIndex)
1024 {
1025     m_state.initForStyleResolve(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
1026
1027     m_state.setStyle(RenderStyle::create());
1028     m_state.style()->inheritFrom(m_state.rootElementStyle());
1029
1030     PageRuleCollector collector(m_state, m_ruleSets);
1031     collector.matchAllPageRules(pageIndex);
1032     m_state.setLineHeightValue(0);
1033     bool inheritedOnly = false;
1034
1035     MatchResult& result = collector.matchedResult();
1036     applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1037
1038     // If our font got dirtied, go ahead and update it now.
1039     updateFont();
1040
1041     // Line-height is set when we are sure we decided on the font-size.
1042     if (m_state.lineHeightValue())
1043         applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue());
1044
1045     applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1046
1047     // Start loading resources referenced by this style.
1048     loadPendingResources();
1049
1050     document().didAccessStyleResolver();
1051
1052     // Now return the style.
1053     return m_state.takeStyle();
1054 }
1055
1056 PassRef<RenderStyle> StyleResolver::defaultStyleForElement()
1057 {
1058     m_state.setStyle(RenderStyle::create());
1059     // Make sure our fonts are initialized if we don't inherit them from our parent style.
1060     if (Settings* settings = documentSettings()) {
1061         initializeFontStyle(settings);
1062         m_state.style()->font().update(fontSelector());
1063     } else
1064         m_state.style()->font().update(0);
1065
1066     return m_state.takeStyle();
1067 }
1068
1069 static void addIntrinsicMargins(RenderStyle* style)
1070 {
1071     // Intrinsic margin value.
1072     const int intrinsicMargin = 2 * style->effectiveZoom();
1073
1074     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1075     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1076     if (style->width().isIntrinsicOrAuto()) {
1077         if (style->marginLeft().quirk())
1078             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1079         if (style->marginRight().quirk())
1080             style->setMarginRight(Length(intrinsicMargin, Fixed));
1081     }
1082
1083     if (style->height().isAuto()) {
1084         if (style->marginTop().quirk())
1085             style->setMarginTop(Length(intrinsicMargin, Fixed));
1086         if (style->marginBottom().quirk())
1087             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1088     }
1089 }
1090
1091 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
1092 {
1093     switch (display) {
1094     case BLOCK:
1095     case TABLE:
1096     case BOX:
1097     case FLEX:
1098     case GRID:
1099         return display;
1100
1101     case LIST_ITEM:
1102         // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
1103         if (!strictParsing && isFloating)
1104             return BLOCK;
1105         return display;
1106     case INLINE_TABLE:
1107         return TABLE;
1108     case INLINE_BOX:
1109         return BOX;
1110     case INLINE_FLEX:
1111         return FLEX;
1112     case INLINE_GRID:
1113         return GRID;
1114
1115     case INLINE:
1116     case RUN_IN:
1117     case COMPACT:
1118     case INLINE_BLOCK:
1119     case TABLE_ROW_GROUP:
1120     case TABLE_HEADER_GROUP:
1121     case TABLE_FOOTER_GROUP:
1122     case TABLE_ROW:
1123     case TABLE_COLUMN_GROUP:
1124     case TABLE_COLUMN:
1125     case TABLE_CELL:
1126     case TABLE_CAPTION:
1127         return BLOCK;
1128     case NONE:
1129         ASSERT_NOT_REACHED();
1130         return NONE;
1131     }
1132     ASSERT_NOT_REACHED();
1133     return BLOCK;
1134 }
1135
1136 // CSS requires text-decoration to be reset at each DOM element for tables, 
1137 // inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
1138 // and absolute or relatively positioned elements.
1139 static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e)
1140 {
1141     return style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1142         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
1143         || style->isFloating() || style->hasOutOfFlowPosition();
1144 }
1145
1146 static bool isDisplayFlexibleBox(EDisplay display)
1147 {
1148     return display == FLEX || display == INLINE_FLEX;
1149 }
1150
1151 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1152 static bool isScrollableOverflow(EOverflow overflow)
1153 {
1154     return overflow == OSCROLL || overflow == OAUTO || overflow == OOVERLAY;
1155 }
1156 #endif
1157
1158 void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1159 {
1160     ASSERT(parentStyle);
1161
1162     // Cache our original display.
1163     style->setOriginalDisplay(style->display());
1164
1165     if (style->display() != NONE) {
1166         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1167         // property.
1168         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1169         // these tags to retain their display types.
1170         if (document().inQuirksMode() && e) {
1171             if (e->hasTagName(tdTag)) {
1172                 style->setDisplay(TABLE_CELL);
1173                 style->setFloating(NoFloat);
1174             } else if (isHTMLTableElement(e))
1175                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1176         }
1177
1178         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1179             if (style->whiteSpace() == KHTML_NOWRAP) {
1180                 // Figure out if we are really nowrapping or if we should just
1181                 // use normal instead. If the width of the cell is fixed, then
1182                 // we don't actually use NOWRAP.
1183                 if (style->width().isFixed())
1184                     style->setWhiteSpace(NORMAL);
1185                 else
1186                     style->setWhiteSpace(NOWRAP);
1187             }
1188         }
1189
1190         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1191         if (e && isHTMLTableElement(e) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1192             style->setTextAlign(TASTART);
1193
1194         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1195         // fix a crash where a site tries to position these objects. They also never honor display.
1196         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1197             style->setPosition(StaticPosition);
1198             style->setDisplay(BLOCK);
1199         }
1200
1201         // Ruby text does not support float or position. This might change with evolution of the specification.
1202         if (e && e->hasTagName(rtTag)) {
1203             style->setPosition(StaticPosition);
1204             style->setFloating(NoFloat);
1205         }
1206
1207         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1208         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1209         if (e && e->hasTagName(thTag) && style->textAlign() == TASTART)
1210             style->setTextAlign(CENTER);
1211
1212         if (e && e->hasTagName(legendTag))
1213             style->setDisplay(BLOCK);
1214
1215         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1216         if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document().documentElement() == e))
1217             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document().inQuirksMode()));
1218
1219         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1220         // clear how that should work.
1221         if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
1222             style->setDisplay(INLINE_BLOCK);
1223
1224         // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
1225         // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
1226         // on some sites).
1227         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1228             || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
1229             && style->hasInFlowPosition())
1230             style->setPosition(StaticPosition);
1231
1232         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1233         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1234         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1235             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1236             || style->display() == TABLE_CELL)
1237             style->setWritingMode(parentStyle->writingMode());
1238
1239         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1240         // of block-flow to anything other than TopToBottomWritingMode.
1241         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1242         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1243             style->setWritingMode(TopToBottomWritingMode);
1244
1245         if (isDisplayFlexibleBox(parentStyle->display())) {
1246             style->setFloating(NoFloat);
1247             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document().inQuirksMode()));
1248         }
1249     }
1250
1251     // Make sure our z-index value is only applied if the object is positioned.
1252     if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle->display()))
1253         style->setHasAutoZIndex();
1254
1255     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1256     // cases where objects that should be blended as a single unit end up with a non-transparent
1257     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1258     if (style->hasAutoZIndex() && ((e && e->document().documentElement() == e)
1259         || style->opacity() < 1.0f
1260         || style->hasTransformRelatedProperty()
1261         || style->hasMask()
1262         || style->clipPath()
1263         || style->boxReflect()
1264         || style->hasFilter()
1265         || style->hasBlendMode()
1266         || style->position() == StickyPosition
1267         || (style->position() == FixedPosition && e && e->document().page() && e->document().page()->settings().fixedPositionCreatesStackingContext())
1268         || style->hasFlowFrom()
1269         ))
1270         style->setZIndex(0);
1271
1272     // Textarea considers overflow visible as auto.
1273     if (e && isHTMLTextAreaElement(e)) {
1274         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1275         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1276     }
1277
1278     if (doesNotInheritTextDecoration(style, e))
1279         style->setTextDecorationsInEffect(style->textDecoration());
1280     else
1281         style->addToTextDecorationsInEffect(style->textDecoration());
1282
1283     // If either overflow value is not visible, change to auto.
1284     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1285         style->setOverflowY(OMARQUEE);
1286     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1287         style->setOverflowX(OMARQUEE);
1288     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
1289         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
1290         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
1291         // default to auto so we can at least scroll through the pages.
1292         style->setOverflowX(OAUTO);
1293     } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1294         style->setOverflowY(OAUTO);
1295
1296     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
1297     // styles are specified on a root element, then they will be incorporated in
1298     // Style::createForDocument().
1299     if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
1300         style->setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style));
1301
1302     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1303     // FIXME: Eventually table sections will support auto and scroll.
1304     if (style->display() == TABLE || style->display() == INLINE_TABLE
1305         || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1306         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1307             style->setOverflowX(OVISIBLE);
1308         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1309             style->setOverflowY(OVISIBLE);
1310     }
1311
1312     // Menulists should have visible overflow
1313     if (style->appearance() == MenulistPart) {
1314         style->setOverflowX(OVISIBLE);
1315         style->setOverflowY(OVISIBLE);
1316     }
1317
1318 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1319     // Touch overflow scrolling creates a stacking context.
1320     if (style->hasAutoZIndex() && style->useTouchOverflowScrolling() && (isScrollableOverflow(style->overflowX()) || isScrollableOverflow(style->overflowY())))
1321         style->setZIndex(0);
1322 #endif
1323
1324     // Cull out any useless layers and also repeat patterns into additional layers.
1325     style->adjustBackgroundLayers();
1326     style->adjustMaskLayers();
1327
1328     // Do the same for animations and transitions.
1329     style->adjustAnimations();
1330     style->adjustTransitions();
1331
1332     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1333     // alter fonts and heights/widths.
1334     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1335         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1336         // so we have to treat all image buttons as though they were explicitly sized.
1337         if (!isHTMLInputElement(e) || !toHTMLInputElement(e)->isImageButton())
1338             addIntrinsicMargins(style);
1339     }
1340
1341     // Let the theme also have a crack at adjusting the style.
1342     if (style->hasAppearance())
1343         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
1344
1345     // If we have first-letter pseudo style, do not share this style.
1346     if (style->hasPseudoStyle(FIRST_LETTER))
1347         style->setUnique();
1348
1349     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
1350     if (style->preserves3D() && (style->overflowX() != OVISIBLE
1351         || style->overflowY() != OVISIBLE
1352         || style->hasFilter()))
1353         style->setTransformStyle3D(TransformStyle3DFlat);
1354
1355     // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
1356     if (e && e->hasTagName(iframeTag) && style->display() == INLINE && toHTMLIFrameElement(e)->shouldDisplaySeamlessly())
1357         style->setDisplay(INLINE_BLOCK);
1358
1359     adjustGridItemPosition(style, parentStyle);
1360
1361 #if ENABLE(SVG)
1362     if (e && e->isSVGElement()) {
1363         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1364         if (style->overflowY() == OSCROLL)
1365             style->setOverflowY(OHIDDEN);
1366         else if (style->overflowY() == OAUTO)
1367             style->setOverflowY(OVISIBLE);
1368
1369         if (style->overflowX() == OSCROLL)
1370             style->setOverflowX(OHIDDEN);
1371         else if (style->overflowX() == OAUTO)
1372             style->setOverflowX(OVISIBLE);
1373
1374         // Only the root <svg> element in an SVG document fragment tree honors css position
1375         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1376             style->setPosition(RenderStyle::initialPosition());
1377
1378         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
1379         // not be scaled again.
1380         if (e->hasTagName(SVGNames::foreignObjectTag))
1381             style->setEffectiveZoom(RenderStyle::initialZoom());
1382     }
1383 #endif
1384 }
1385
1386 void StyleResolver::adjustGridItemPosition(RenderStyle* style, RenderStyle* parentStyle) const
1387 {
1388     const GridPosition& columnStartPosition = style->gridItemColumnStart();
1389     const GridPosition& columnEndPosition = style->gridItemColumnEnd();
1390     const GridPosition& rowStartPosition = style->gridItemRowStart();
1391     const GridPosition& rowEndPosition = style->gridItemRowEnd();
1392
1393     // If opposing grid-placement properties both specify a grid span, they both compute to ‘auto’.
1394     if (columnStartPosition.isSpan() && columnEndPosition.isSpan()) {
1395         style->setGridItemColumnStart(GridPosition());
1396         style->setGridItemColumnEnd(GridPosition());
1397     }
1398
1399     if (rowStartPosition.isSpan() && rowEndPosition.isSpan()) {
1400         style->setGridItemRowStart(GridPosition());
1401         style->setGridItemRowEnd(GridPosition());
1402     }
1403
1404     // Unknown named grid area compute to 'auto'.
1405     const NamedGridAreaMap& map = parentStyle->namedGridArea();
1406
1407 #define CLEAR_UNKNOWN_NAMED_AREA(prop, Prop) \
1408     if (prop.isNamedGridArea() && !map.contains(prop.namedGridLine())) \
1409         style->setGridItem##Prop(GridPosition());
1410
1411     CLEAR_UNKNOWN_NAMED_AREA(columnStartPosition, ColumnStart);
1412     CLEAR_UNKNOWN_NAMED_AREA(columnEndPosition, ColumnEnd);
1413     CLEAR_UNKNOWN_NAMED_AREA(rowStartPosition, RowStart);
1414     CLEAR_UNKNOWN_NAMED_AREA(rowEndPosition, RowEnd);
1415 }
1416
1417 bool StyleResolver::checkRegionStyle(Element* regionElement)
1418 {
1419     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
1420     // so all region rules are global by default. Verify whether that can stand or needs changing.
1421
1422     unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size();
1423     for (unsigned i = 0; i < rulesSize; ++i) {
1424         ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1425         if (checkRegionSelector(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1426             return true;
1427     }
1428
1429     if (m_ruleSets.userStyle()) {
1430         rulesSize = m_ruleSets.userStyle()->regionSelectorsAndRuleSets().size();
1431         for (unsigned i = 0; i < rulesSize; ++i) {
1432             ASSERT(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1433             if (checkRegionSelector(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1434                 return true;
1435         }
1436     }
1437
1438     return false;
1439 }
1440
1441 static void checkForOrientationChange(RenderStyle* style)
1442 {
1443     FontOrientation fontOrientation;
1444     NonCJKGlyphOrientation glyphOrientation;
1445     style->getFontAndGlyphOrientation(fontOrientation, glyphOrientation);
1446
1447     const FontDescription& fontDescription = style->fontDescription();
1448     if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
1449         return;
1450
1451     FontDescription newFontDescription(fontDescription);
1452     newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
1453     newFontDescription.setOrientation(fontOrientation);
1454     style->setFontDescription(newFontDescription);
1455 }
1456
1457 void StyleResolver::updateFont()
1458 {
1459     if (!m_state.fontDirty())
1460         return;
1461
1462     RenderStyle* style = m_state.style();
1463 #if ENABLE(IOS_TEXT_AUTOSIZING)
1464     checkForTextSizeAdjust(style);
1465 #endif
1466     checkForGenericFamilyChange(style, m_state.parentStyle());
1467     checkForZoomChange(style, m_state.parentStyle());
1468     checkForOrientationChange(style);
1469     style->font().update(m_fontSelector);
1470     m_state.setFontDirty(false);
1471 }
1472
1473 Vector<RefPtr<StyleRuleBase>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
1474 {
1475     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1476 }
1477
1478 Vector<RefPtr<StyleRuleBase>> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
1479 {
1480     if (!e || !e->document().haveStylesheetsLoaded())
1481         return Vector<RefPtr<StyleRuleBase>>();
1482
1483     initElement(e);
1484     m_state.initForStyleResolve(document(), e, 0);
1485
1486     ElementRuleCollector collector(this, m_state);
1487     collector.setMode(SelectorChecker::CollectingRules);
1488     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1489     collector.setMedium(m_medium.get());
1490
1491     if (rulesToInclude & UAAndUserCSSRules) {
1492         // First we match rules from the user agent sheet.
1493         collector.matchUARules();
1494         
1495         // Now we check user sheet rules.
1496         if (m_matchAuthorAndUserStyles)
1497             collector.matchUserRules(rulesToInclude & EmptyCSSRules);
1498     }
1499
1500     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1501         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
1502
1503         // Check the rules in author sheets.
1504         collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
1505     }
1506
1507     return collector.matchedRuleList();
1508 }
1509
1510 // -------------------------------------------------------------------------------------
1511 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1512
1513 Length StyleResolver::convertToIntLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
1514 {
1515     return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
1516 }
1517
1518 Length StyleResolver::convertToFloatLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
1519 {
1520     return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
1521 }
1522
1523 template <StyleResolver::StyleApplicationPass pass>
1524 void StyleResolver::applyProperties(const StyleProperties* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
1525 {
1526     ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || m_state.regionForStyling());
1527     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(&document(), rule, *this);
1528
1529     unsigned propertyCount = properties->propertyCount();
1530     for (unsigned i = 0; i < propertyCount; ++i) {
1531         StyleProperties::PropertyReference current = properties->propertyAt(i);
1532         if (isImportant != current.isImportant())
1533             continue;
1534         if (inheritedOnly && !current.isInherited()) {
1535             // If the property value is explicitly inherited, we need to apply further non-inherited properties
1536             // as they might override the value inherited here. For this reason we don't allow declarations with
1537             // explicitly inherited properties to be cached.
1538             ASSERT(!current.value()->isInheritedValue());
1539             continue;
1540         }
1541         CSSPropertyID property = current.id();
1542
1543         if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(property))
1544             continue;
1545 #if ENABLE(VIDEO_TRACK)
1546         if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(property))
1547             continue;
1548 #endif
1549         switch (pass) {
1550         case HighPriorityProperties:
1551             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
1552 #if ENABLE(IOS_TEXT_AUTOSIZING)
1553             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range);
1554 #else
1555             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is_end_of_first_prop_range);
1556 #endif
1557             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
1558             // give special priority to font-xxx, color properties, etc
1559             if (property < CSSPropertyLineHeight)
1560                 applyProperty(current.id(), current.value());
1561             // we apply line-height later
1562             else if (property == CSSPropertyLineHeight)
1563                 m_state.setLineHeightValue(current.value());
1564             break;
1565         case LowPriorityProperties:
1566             if (property > CSSPropertyLineHeight)
1567                 applyProperty(current.id(), current.value());
1568         }
1569     }
1570     InspectorInstrumentation::didProcessRule(cookie);
1571 }
1572
1573 template <StyleResolver::StyleApplicationPass pass>
1574 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
1575 {
1576     if (startIndex == -1)
1577         return;
1578
1579     State& state = m_state;
1580     if (state.style()->insideLink() != NotInsideLink) {
1581         for (int i = startIndex; i <= endIndex; ++i) {
1582             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1583             unsigned linkMatchType = matchedProperties.linkMatchType;
1584             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
1585             state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
1586             state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
1587
1588             applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1589         }
1590         state.setApplyPropertyToRegularStyle(true);
1591         state.setApplyPropertyToVisitedLinkStyle(false);
1592         return;
1593     }
1594     for (int i = startIndex; i <= endIndex; ++i) {
1595         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1596         applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1597     }
1598 }
1599
1600 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1601 {
1602     
1603     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1604 }
1605
1606 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1607 {
1608     return a.firstUARule == b.firstUARule
1609         && a.lastUARule == b.lastUARule
1610         && a.firstAuthorRule == b.firstAuthorRule
1611         && a.lastAuthorRule == b.lastAuthorRule
1612         && a.firstUserRule == b.firstUserRule
1613         && a.lastUserRule == b.lastUserRule;
1614 }
1615
1616 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1617 {
1618     return !(a == b);
1619 }
1620
1621 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1622 {
1623     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
1624 }
1625
1626 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1627 {
1628     return !(a == b);
1629 }
1630
1631 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
1632 {
1633     ASSERT(hash);
1634
1635     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
1636     if (it == m_matchedPropertiesCache.end())
1637         return 0;
1638     MatchedPropertiesCacheItem& cacheItem = it->value;
1639
1640     size_t size = matchResult.matchedProperties.size();
1641     if (size != cacheItem.matchedProperties.size())
1642         return 0;
1643     for (size_t i = 0; i < size; ++i) {
1644         if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
1645             return 0;
1646     }
1647     if (cacheItem.ranges != matchResult.ranges)
1648         return 0;
1649     return &cacheItem;
1650 }
1651
1652 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
1653 {
1654     static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
1655     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps
1656         && !m_matchedPropertiesCacheSweepTimer.isActive()) {
1657         static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
1658         m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
1659     }
1660
1661     ASSERT(hash);
1662     MatchedPropertiesCacheItem cacheItem;
1663     cacheItem.matchedProperties.appendVector(matchResult.matchedProperties);
1664     cacheItem.ranges = matchResult.ranges;
1665     // Note that we don't cache the original RenderStyle instance. It may be further modified.
1666     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
1667     cacheItem.renderStyle = RenderStyle::clone(style);
1668     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
1669     m_matchedPropertiesCache.add(hash, cacheItem);
1670 }
1671
1672 void StyleResolver::invalidateMatchedPropertiesCache()
1673 {
1674     m_matchedPropertiesCache.clear();
1675 }
1676
1677 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
1678 {
1679     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
1680     if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement())
1681         return false;
1682     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
1683         return false;
1684     if (style->hasAppearance())
1685         return false;
1686     if (style->zoom() != RenderStyle::initialZoom())
1687         return false;
1688     if (style->writingMode() != RenderStyle::initialWritingMode())
1689         return false;
1690     // The cache assumes static knowledge about which properties are inherited.
1691     if (parentStyle->hasExplicitlyInheritedProperties())
1692         return false;
1693     return true;
1694 }
1695
1696 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element)
1697 {
1698     ASSERT(element);
1699     State& state = m_state;
1700     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
1701     bool applyInheritedOnly = false;
1702     const MatchedPropertiesCacheItem* cacheItem = 0;
1703     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
1704         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1705         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
1706         // element context. This is fast and saves memory by reusing the style data structures.
1707         state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
1708         if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
1709             EInsideLink linkStatus = state.style()->insideLink();
1710             // If the cache item parent style has identical inherited properties to the current parent style then the
1711             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1712             state.style()->inheritFrom(cacheItem->renderStyle.get());
1713
1714             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1715             state.style()->setInsideLink(linkStatus);
1716             return;
1717         }
1718         applyInheritedOnly = true; 
1719     }
1720
1721     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
1722     // high-priority properties first, i.e., those properties that other properties depend on.
1723     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1724     // and (4) normal important.
1725     state.setLineHeightValue(0);
1726     applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1727     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1728     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1729     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1730
1731     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
1732         state.setFontDirty(true);
1733         applyInheritedOnly = false;
1734     }
1735
1736     // If our font got dirtied, go ahead and update it now.
1737     updateFont();
1738
1739     // Line-height is set when we are sure we decided on the font-size.
1740     if (state.lineHeightValue())
1741         applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
1742
1743     // Many properties depend on the font. If it changes we just apply all properties.
1744     if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
1745         applyInheritedOnly = false;
1746
1747     // Now do the normal priority UA properties.
1748     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1749     
1750     // Cache our border and background so that we can examine them later.
1751     state.cacheBorderAndBackground();
1752     
1753     // Now do the author and user normal priority properties and all the !important properties.
1754     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1755     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1756     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1757     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1758    
1759     // Start loading resources referenced by this style.
1760     loadPendingResources();
1761     
1762     ASSERT(!state.fontDirty());
1763     
1764     if (cacheItem || !cacheHash)
1765         return;
1766     if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
1767         return;
1768     addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
1769 }
1770
1771 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
1772 {
1773     initElement(0);
1774     m_state.initForStyleResolve(document(), 0, style);
1775     m_state.setStyle(*style);
1776     applyPropertyToCurrentStyle(id, value);
1777 }
1778
1779 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
1780 {
1781     if (value)
1782         applyProperty(id, value);
1783 }
1784
1785 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
1786 {
1787     switch (id) {
1788     case CSSPropertyBackgroundColor:
1789     case CSSPropertyBorderLeftColor:
1790     case CSSPropertyBorderRightColor:
1791     case CSSPropertyBorderTopColor:
1792     case CSSPropertyBorderBottomColor:
1793     case CSSPropertyColor:
1794     case CSSPropertyOutlineColor:
1795     case CSSPropertyWebkitColumnRuleColor:
1796 #if ENABLE(CSS3_TEXT_DECORATION)
1797     case CSSPropertyWebkitTextDecorationColor:
1798 #endif
1799     case CSSPropertyWebkitTextEmphasisColor:
1800     case CSSPropertyWebkitTextFillColor:
1801     case CSSPropertyWebkitTextStrokeColor:
1802 #if ENABLE(SVG)
1803     case CSSPropertyFill:
1804     case CSSPropertyStroke:
1805 #endif
1806         return true;
1807     default:
1808         break;
1809     }
1810
1811     return false;
1812 }
1813
1814 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
1815 // FIXME: add incremental support for other region styling properties.
1816 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
1817 {
1818     switch (id) {
1819     case CSSPropertyBackgroundColor:
1820     case CSSPropertyColor:
1821         return true;
1822     default:
1823         break;
1824     }
1825
1826     return false;
1827 }
1828
1829 #if ENABLE(VIDEO_TRACK)
1830 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
1831 {
1832     switch (id) {
1833     case CSSPropertyBackground:
1834     case CSSPropertyBackgroundAttachment:
1835     case CSSPropertyBackgroundClip:
1836     case CSSPropertyBackgroundColor:
1837     case CSSPropertyBackgroundImage:
1838     case CSSPropertyBackgroundOrigin:
1839     case CSSPropertyBackgroundPosition:
1840     case CSSPropertyBackgroundPositionX:
1841     case CSSPropertyBackgroundPositionY:
1842     case CSSPropertyBackgroundRepeat:
1843     case CSSPropertyBackgroundRepeatX:
1844     case CSSPropertyBackgroundRepeatY:
1845     case CSSPropertyBackgroundSize:
1846     case CSSPropertyColor:
1847     case CSSPropertyFont:
1848     case CSSPropertyFontFamily:
1849     case CSSPropertyFontSize:
1850     case CSSPropertyFontStyle:
1851     case CSSPropertyFontVariant:
1852     case CSSPropertyFontWeight:
1853     case CSSPropertyLineHeight:
1854     case CSSPropertyOpacity:
1855     case CSSPropertyOutline:
1856     case CSSPropertyOutlineColor:
1857     case CSSPropertyOutlineOffset:
1858     case CSSPropertyOutlineStyle:
1859     case CSSPropertyOutlineWidth:
1860     case CSSPropertyVisibility:
1861     case CSSPropertyWhiteSpace:
1862     case CSSPropertyTextDecoration:
1863     case CSSPropertyTextShadow:
1864     case CSSPropertyBorderStyle:
1865         return true;
1866     default:
1867         break;
1868     }
1869     return false;
1870 }
1871 #endif
1872 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
1873 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
1874 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
1875 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
1876 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
1877 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
1878 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
1879 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
1880 bool StyleResolver::useSVGZoomRules()
1881 {
1882     return m_state.element() && m_state.element()->isSVGElement();
1883 }
1884
1885 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, GridLength& workingLength)
1886 {
1887     if (primitiveValue->getValueID() == CSSValueWebkitMinContent) {
1888         workingLength = Length(MinContent);
1889         return true;
1890     }
1891
1892     if (primitiveValue->getValueID() == CSSValueWebkitMaxContent) {
1893         workingLength = Length(MaxContent);
1894         return true;
1895     }
1896
1897     if (primitiveValue->isFlex()) {
1898         // Fractional unit.
1899         workingLength.setFlex(primitiveValue->getDoubleValue());
1900         return true;
1901     }
1902
1903     workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
1904     if (workingLength.length().isUndefined())
1905         return false;
1906
1907     if (primitiveValue->isLength())
1908         workingLength.length().setQuirk(primitiveValue->isQuirkValue());
1909
1910     return true;
1911 }
1912
1913 static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolver::State& state)
1914 {
1915     if (!value->isPrimitiveValue())
1916         return false;
1917
1918     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1919     Pair* minMaxTrackBreadth = primitiveValue->getPairValue();
1920     if (!minMaxTrackBreadth) {
1921         GridLength workingLength;
1922         if (!createGridTrackBreadth(primitiveValue, state, workingLength))
1923             return false;
1924
1925         trackSize.setLength(workingLength);
1926         return true;
1927     }
1928
1929     GridLength minTrackBreadth;
1930     GridLength maxTrackBreadth;
1931     if (!createGridTrackBreadth(minMaxTrackBreadth->first(), state, minTrackBreadth) || !createGridTrackBreadth(minMaxTrackBreadth->second(), state, maxTrackBreadth))
1932         return false;
1933
1934     trackSize.setMinMax(minTrackBreadth, maxTrackBreadth);
1935     return true;
1936 }
1937
1938 static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, const StyleResolver::State& state)
1939 {
1940     // Handle 'none'.
1941     if (value->isPrimitiveValue()) {
1942         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1943         return primitiveValue->getValueID() == CSSValueNone;
1944     }
1945
1946     if (!value->isValueList())
1947         return false;
1948
1949     size_t currentNamedGridLine = 0;
1950     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
1951         CSSValue* currValue = i.value();
1952         if (currValue->isPrimitiveValue()) {
1953             CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(currValue);
1954             if (primitiveValue->isString()) {
1955                 NamedGridLinesMap::AddResult result = namedGridLines.add(primitiveValue->getStringValue(), Vector<size_t>());
1956                 result.iterator->value.append(currentNamedGridLine);
1957                 continue;
1958             }
1959         }
1960
1961         ++currentNamedGridLine;
1962         GridTrackSize trackSize;
1963         if (!createGridTrackSize(currValue, trackSize, state))
1964             return false;
1965
1966         trackSizes.append(trackSize);
1967     }
1968
1969     // The parser should have rejected any <track-list> without any <track-size> as
1970     // this is not conformant to the syntax.
1971     ASSERT(!trackSizes.isEmpty());
1972     return true;
1973 }
1974
1975
1976 static bool createGridPosition(CSSValue* value, GridPosition& position)
1977 {
1978     // We accept the specification's grammar:
1979     // 'auto' | [ <integer> || <string> ] | [ span && [ <integer> || string ] ] | <ident>
1980     if (value->isPrimitiveValue()) {
1981         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1982         // We translate <ident> to <string> during parsing as it makes handling it simpler.
1983         if (primitiveValue->isString()) {
1984             position.setNamedGridArea(primitiveValue->getStringValue());
1985             return true;
1986         }
1987
1988         ASSERT(primitiveValue->getValueID() == CSSValueAuto);
1989         return true;
1990     }
1991
1992     CSSValueList* values = toCSSValueList(value);
1993     ASSERT(values->length());
1994
1995     bool isSpanPosition = false;
1996     // The specification makes the <integer> optional, in which case it default to '1'.
1997     int gridLineNumber = 1;
1998     String gridLineName;
1999
2000     CSSValueListIterator it = values;
2001     CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value());
2002     if (currentValue->getValueID() == CSSValueSpan) {
2003         isSpanPosition = true;
2004         it.advance();
2005         currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
2006     }
2007
2008     if (currentValue && currentValue->isNumber()) {
2009         gridLineNumber = currentValue->getIntValue();
2010         it.advance();
2011         currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
2012     }
2013
2014     if (currentValue && currentValue->isString()) {
2015         gridLineName = currentValue->getStringValue();
2016         it.advance();
2017     }
2018
2019     ASSERT(!it.hasMore());
2020     if (isSpanPosition)
2021         position.setSpanPosition(gridLineNumber, gridLineName);
2022     else
2023         position.setExplicitPosition(gridLineNumber, gridLineName);
2024
2025     return true;
2026 }
2027
2028 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
2029 {
2030     ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
2031
2032     State& state = m_state;
2033
2034     if (CSSProperty::isDirectionAwareProperty(id)) {
2035         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
2036         ASSERT(newId != id);
2037         return applyProperty(newId, value);
2038     }
2039
2040     bool isInherit = state.parentNode() && value->isInheritedValue();
2041     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
2042
2043     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2044     ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
2045
2046     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2047         // Limit the properties that can be applied to only the ones honored by :visited.
2048         return;
2049     }
2050
2051     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
2052         state.parentStyle()->setHasExplicitlyInheritedProperties();
2053
2054     // Check lookup table for implementations and use when available.
2055     const PropertyHandler& handler = m_deprecatedStyleBuilder.propertyHandler(id);
2056     if (handler.isValid()) {
2057         if (isInherit)
2058             handler.applyInheritValue(id, this);
2059         else if (isInitial)
2060             handler.applyInitialValue(id, this);
2061         else
2062             handler.applyValue(id, this, value);
2063         return;
2064     }
2065
2066     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0;
2067
2068     float zoomFactor = state.style()->effectiveZoom();
2069
2070     // What follows is a list that maps the CSS properties into their corresponding front-end
2071     // RenderStyle values.
2072     switch (id) {
2073     // lists
2074     case CSSPropertyContent:
2075         // list of string, uri, counter, attr, i
2076         {
2077             // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2078             // note is a reminder that eventually "inherit" needs to be supported.
2079
2080             if (isInitial) {
2081                 state.style()->clearContent();
2082                 return;
2083             }
2084
2085             if (!value->isValueList())
2086                 return;
2087
2088             bool didSet = false;
2089             for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2090                 CSSValue* item = i.value();
2091                 if (item->isImageGeneratorValue()) {
2092                     if (item->isGradientValue())
2093                         state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(this).get()), didSet);
2094                     else
2095                         state.style()->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
2096                     didSet = true;
2097 #if ENABLE(CSS_IMAGE_SET)
2098                 } else if (item->isImageSetValue()) {
2099                     state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
2100                     didSet = true;
2101 #endif
2102                 }
2103
2104                 if (item->isImageValue()) {
2105                     state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, toCSSImageValue(item)), didSet);
2106                     didSet = true;
2107                     continue;
2108                 }
2109
2110                 if (!item->isPrimitiveValue())
2111                     continue;
2112
2113                 CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
2114
2115                 if (contentValue->isString()) {
2116                     state.style()->setContent(contentValue->getStringValue().impl(), didSet);
2117                     didSet = true;
2118                 } else if (contentValue->isAttr()) {
2119                     // FIXME: Can a namespace be specified for an attr(foo)?
2120                     if (state.style()->styleType() == NOPSEUDO)
2121                         state.style()->setUnique();
2122                     else
2123                         state.parentStyle()->setUnique();
2124                     QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2125                     const AtomicString& value = state.element()->getAttribute(attr);
2126                     state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2127                     didSet = true;
2128                     // Register the fact that the attribute value affects the style.
2129                     m_ruleSets.features().attrsInRules.add(attr.localName().impl());
2130                 } else if (contentValue->isCounter()) {
2131                     Counter* counterValue = contentValue->getCounterValue();
2132                     EListStyleType listStyleType = NoneListStyle;
2133                     CSSValueID listStyleIdent = counterValue->listStyleIdent();
2134                     if (listStyleIdent != CSSValueNone)
2135                         listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2136                     auto counter = std::make_unique<CounterContent>(counterValue->identifier(), listStyleType, counterValue->separator());
2137                     state.style()->setContent(std::move(counter), didSet);
2138                     didSet = true;
2139                 } else {
2140                     switch (contentValue->getValueID()) {
2141                     case CSSValueOpenQuote:
2142                         state.style()->setContent(OPEN_QUOTE, didSet);
2143                         didSet = true;
2144                         break;
2145                     case CSSValueCloseQuote:
2146                         state.style()->setContent(CLOSE_QUOTE, didSet);
2147                         didSet = true;
2148                         break;
2149                     case CSSValueNoOpenQuote:
2150                         state.style()->setContent(NO_OPEN_QUOTE, didSet);
2151                         didSet = true;
2152                         break;
2153                     case CSSValueNoCloseQuote:
2154                         state.style()->setContent(NO_CLOSE_QUOTE, didSet);
2155                         didSet = true;
2156                         break;
2157                     default:
2158                         // normal and none do not have any effect.
2159                         { }
2160                     }
2161                 }
2162             }
2163             if (!didSet)
2164                 state.style()->clearContent();
2165             return;
2166         }
2167     case CSSPropertyWebkitAlt:
2168         {
2169             bool didSet = false;
2170             if (primitiveValue->isString()) {
2171                 state.style()->setContentAltText(primitiveValue->getStringValue().impl());
2172                 didSet = true;
2173             } else if (primitiveValue->isAttr()) {
2174                 // FIXME: Can a namespace be specified for an attr(foo)?
2175                 if (state.style()->styleType() == NOPSEUDO)
2176                     state.style()->setUnique();
2177                 else
2178                     state.parentStyle()->setUnique();
2179                 QualifiedName attr(nullAtom, primitiveValue->getStringValue().impl(), nullAtom);
2180                 const AtomicString& value = state.element()->getAttribute(attr);
2181                 state.style()->setContentAltText(value.isNull() ? emptyAtom : value.impl());
2182                 didSet = true;
2183                 // Register the fact that the attribute value affects the style.
2184                 m_ruleSets.features().attrsInRules.add(attr.localName().impl());
2185             }
2186             if (!didSet)
2187                 state.style()->setContentAltText(emptyAtom);
2188         }
2189     case CSSPropertyQuotes:
2190         if (isInherit) {
2191             state.style()->setQuotes(state.parentStyle()->quotes());
2192             return;
2193         }
2194         if (isInitial) {
2195             state.style()->setQuotes(0);
2196             return;
2197         }
2198         if (value->isValueList()) {
2199             CSSValueList* list = toCSSValueList(value);
2200             Vector<std::pair<String, String>> quotes;
2201             for (size_t i = 0; i < list->length(); i += 2) {
2202                 CSSValue* first = list->itemWithoutBoundsCheck(i);
2203                 // item() returns null if out of bounds so this is safe.
2204                 CSSValue* second = list->item(i + 1);
2205                 if (!second)
2206                     continue;
2207                 ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue());
2208                 ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue());
2209                 String startQuote = toCSSPrimitiveValue(first)->getStringValue();
2210                 String endQuote = toCSSPrimitiveValue(second)->getStringValue();
2211                 quotes.append(std::make_pair(startQuote, endQuote));
2212             }
2213             state.style()->setQuotes(QuotesData::create(quotes));
2214             return;
2215         }
2216         if (primitiveValue) {
2217             if (primitiveValue->getValueID() == CSSValueNone)
2218                 state.style()->setQuotes(QuotesData::create(Vector<std::pair<String, String>>()));
2219         }
2220         return;
2221     // Shorthand properties.
2222     case CSSPropertyFont:
2223         if (isInherit) {
2224             FontDescription fontDescription = state.parentStyle()->fontDescription();
2225             state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight());
2226             state.setLineHeightValue(0);
2227             setFontDescription(fontDescription);
2228         } else if (isInitial) {
2229             Settings* settings = documentSettings();
2230             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
2231             if (!settings)
2232                 return;
2233             initializeFontStyle(settings);
2234         } else if (primitiveValue) {
2235             state.style()->setLineHeight(RenderStyle::initialLineHeight());
2236             state.setLineHeightValue(0);
2237
2238             FontDescription fontDescription;
2239             RenderTheme::defaultTheme()->systemFont(primitiveValue->getValueID(), fontDescription);
2240
2241             // Double-check and see if the theme did anything. If not, don't bother updating the font.
2242             if (fontDescription.isAbsoluteSize()) {
2243                 // Make sure the rendering mode and printer font settings are updated.
2244                 Settings* settings = documentSettings();
2245                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
2246                 if (!settings)
2247                     return;
2248                 fontDescription.setRenderingMode(settings->fontRenderingMode());
2249                 fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
2250
2251                 // Handle the zoom factor.
2252                 fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(fontDescription.specifiedSize(), fontDescription.isAbsoluteSize(), useSVGZoomRules(), state.style(), document()));
2253                 setFontDescription(fontDescription);
2254             }
2255         } else if (value->isFontValue()) {
2256             CSSFontValue* font = toCSSFontValue(value);
2257             if (!font->style || !font->variant || !font->weight
2258                 || !font->size || !font->lineHeight || !font->family)
2259                 return;
2260             applyProperty(CSSPropertyFontStyle, font->style.get());
2261             applyProperty(CSSPropertyFontVariant, font->variant.get());
2262             applyProperty(CSSPropertyFontWeight, font->weight.get());
2263             // The previous properties can dirty our font but they don't try to read the font's
2264             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
2265             // need query the dirtied font's x-height to get the computed size. To be safe in this
2266             // case, let's just update the font now.
2267             updateFont();
2268             applyProperty(CSSPropertyFontSize, font->size.get());
2269
2270             state.setLineHeightValue(font->lineHeight.get());
2271
2272             applyProperty(CSSPropertyFontFamily, font->family.get());
2273         }
2274         return;
2275
2276     case CSSPropertyBackground:
2277     case CSSPropertyBackgroundPosition:
2278     case CSSPropertyBackgroundRepeat:
2279     case CSSPropertyBorder:
2280     case CSSPropertyBorderBottom:
2281     case CSSPropertyBorderColor:
2282     case CSSPropertyBorderImage:
2283     case CSSPropertyBorderLeft:
2284     case CSSPropertyBorderRadius:
2285     case CSSPropertyBorderRight:
2286     case CSSPropertyBorderSpacing:
2287     case CSSPropertyBorderStyle:
2288     case CSSPropertyBorderTop:
2289     case CSSPropertyBorderWidth:
2290     case CSSPropertyListStyle:
2291     case CSSPropertyMargin:
2292     case CSSPropertyOutline:
2293     case CSSPropertyOverflow:
2294     case CSSPropertyPadding:
2295     case CSSPropertyTransition:
2296     case CSSPropertyWebkitAnimation:
2297     case CSSPropertyWebkitBorderAfter:
2298     case CSSPropertyWebkitBorderBefore:
2299     case CSSPropertyWebkitBorderEnd:
2300     case CSSPropertyWebkitBorderStart:
2301     case CSSPropertyWebkitBorderRadius:
2302     case CSSPropertyWebkitColumns:
2303     case CSSPropertyWebkitColumnRule:
2304     case CSSPropertyWebkitFlex:
2305     case CSSPropertyWebkitFlexFlow:
2306     case CSSPropertyWebkitGridArea:
2307     case CSSPropertyWebkitGridColumn:
2308     case CSSPropertyWebkitGridRow:
2309     case CSSPropertyWebkitMarginCollapse:
2310     case CSSPropertyWebkitMarquee:
2311     case CSSPropertyWebkitMask:
2312     case CSSPropertyWebkitMaskPosition:
2313     case CSSPropertyWebkitMaskRepeat:
2314     case CSSPropertyWebkitTextEmphasis:
2315     case CSSPropertyWebkitTextStroke:
2316     case CSSPropertyWebkitTransition:
2317     case CSSPropertyWebkitTransformOrigin:
2318         ASSERT(isExpandedShorthand(id));
2319         ASSERT_NOT_REACHED();
2320         break;
2321
2322     // CSS3 Properties
2323     case CSSPropertyTextShadow:
2324     case CSSPropertyBoxShadow:
2325     case CSSPropertyWebkitBoxShadow: {
2326         if (isInherit) {
2327             if (id == CSSPropertyTextShadow)
2328                 return state.style()->setTextShadow(state.parentStyle()->textShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr);
2329             return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr);
2330         }
2331         if (isInitial || primitiveValue) // initial | none
2332             return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr);
2333
2334         if (!value->isValueList())
2335             return;
2336
2337         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2338             CSSValue* currValue = i.value();
2339             if (!currValue->isShadowValue())
2340                 continue;
2341             CSSShadowValue* item = toCSSShadowValue(currValue);
2342             int x = item->x->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
2343             if (item->x->isViewportPercentageLength())
2344                 x = viewportPercentageValue(*item->x, x);
2345             int y = item->y->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
2346             if (item->y->isViewportPercentageLength())
2347                 y = viewportPercentageValue(*item->y, y);
2348             int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
2349             if (item->blur && item->blur->isViewportPercentageLength())
2350                 blur = viewportPercentageValue(*item->blur, blur);
2351             int spread = item->spread ? item->spread->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
2352             if (item->spread && item->spread->isViewportPercentageLength())
2353                 spread = viewportPercentageValue(*item->spread, spread);
2354             ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal;
2355             Color color;
2356             if (item->color)
2357                 color = colorFromPrimitiveValue(item->color.get());
2358             else if (state.style())
2359                 color = state.style()->color();
2360
2361             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
2362             if (id == CSSPropertyTextShadow)
2363                 state.style()->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
2364             else
2365                 state.style()->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
2366         }
2367         return;
2368     }
2369     case CSSPropertyWebkitBoxReflect: {
2370         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
2371         if (primitiveValue) {
2372             state.style()->setBoxReflect(RenderStyle::initialBoxReflect());
2373             return;
2374         }
2375
2376         if (!value->isReflectValue())
2377             return;
2378
2379         CSSReflectValue* reflectValue = toCSSReflectValue(value);
2380         RefPtr<StyleReflection> reflection = StyleReflection::create();
2381         reflection->setDirection(*reflectValue->direction());
2382         if (reflectValue->offset())
2383             reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.style(), state.rootElementStyle(), zoomFactor));
2384         NinePieceImage mask;
2385         mask.setMaskDefaults();
2386         m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
2387         reflection->setMask(mask);
2388
2389         state.style()->setBoxReflect(reflection.release());
2390         return;
2391     }
2392     case CSSPropertySrc: // Only used in @font-face rules.
2393         return;
2394     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
2395         return;
2396     case CSSPropertyWebkitLocale: {
2397         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
2398         if (!primitiveValue)
2399             return;
2400         if (primitiveValue->getValueID() == CSSValueAuto)
2401             state.style()->setLocale(nullAtom);
2402         else
2403             state.style()->setLocale(primitiveValue->getStringValue());
2404         FontDescription fontDescription = state.style()->fontDescription();
2405         fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale()));
2406         setFontDescription(fontDescription);
2407         return;
2408     }
2409 #if ENABLE(IOS_TEXT_AUTOSIZING)
2410     case CSSPropertyWebkitTextSizeAdjust: {
2411         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
2412         if (!primitiveValue)
2413             return;
2414
2415         if (primitiveValue->getValueID() == CSSValueAuto)
2416             state.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment));
2417         else if (primitiveValue->getValueID() == CSSValueNone)
2418             state.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
2419         else
2420             state.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue->getFloatValue()));
2421
2422         state.setFontDirty(true);
2423         return;
2424     }
2425 #endif
2426 #if ENABLE(DASHBOARD_SUPPORT)
2427     case CSSPropertyWebkitDashboardRegion:
2428     {
2429         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
2430         if (!primitiveValue)
2431             return;
2432
2433         if (primitiveValue->getValueID() == CSSValueNone) {
2434             state.style()->setDashboardRegions(RenderStyle::noneDashboardRegions());
2435             return;
2436         }
2437
2438         DashboardRegion* region = primitiveValue->getDashboardRegionValue();
2439         if (!region)
2440             return;
2441
2442         DashboardRegion* first = region;
2443         while (region) {
2444             Length top = convertToIntLength(region->top(), state.style(), state.rootElementStyle());
2445             Length right = convertToIntLength(region->right(), state.style(), state.rootElementStyle());
2446             Length bottom = convertToIntLength(region->bottom(), state.style(), state.rootElementStyle());
2447             Length left = convertToIntLength(region->left(), state.style(), state.rootElementStyle());
2448
2449             if (top.isUndefined())
2450                 top = Length();
2451             if (right.isUndefined())
2452                 right = Length();
2453             if (bottom.isUndefined())
2454                 bottom = Length();
2455             if (left.isUndefined())
2456                 left = Length();
2457
2458             if (region->m_isCircle)
2459                 state.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
2460             else if (region->m_isRectangle)
2461                 state.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
2462             region = region->m_next.get();
2463         }
2464
2465         state.document().setHasAnnotatedRegions(true);
2466
2467         return;
2468     }
2469 #endif
2470 #if ENABLE(DRAGGABLE_REGION)
2471     case CSSPropertyWebkitAppRegion: {
2472         if (!primitiveValue || !primitiveValue->getValueID())
2473             return;
2474         state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
2475         state.document().setHasAnnotatedRegions(true);
2476         return;
2477     }
2478 #endif
2479     case CSSPropertyWebkitTextStrokeWidth: {
2480         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
2481         float width = 0;
2482         switch (primitiveValue->getValueID()) {
2483         case CSSValueThin:
2484         case CSSValueMedium:
2485         case CSSValueThick: {
2486             double result = 1.0 / 48;
2487             if (primitiveValue->getValueID() == CSSValueMedium)
2488                 result *= 3;
2489             else if (primitiveValue->getValueID() == CSSValueThick)
2490                 result *= 5;
2491             Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS));
2492             width = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2493             break;
2494         }
2495         default:
2496             width = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2497             break;
2498         }
2499         state.style()->setTextStrokeWidth(width);
2500         return;
2501     }
2502     case CSSPropertyWebkitTransform: {
2503         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
2504         TransformOperations operations;
2505         transformsForValue(state.style(), state.rootElementStyle(), value, operations);
2506         state.style()->setTransform(operations);
2507         return;
2508     }
2509     case CSSPropertyWebkitPerspective: {
2510         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
2511
2512         if (!primitiveValue)
2513             return;
2514
2515         if (primitiveValue->getValueID() == CSSValueNone) {
2516             state.style()->setPerspective(0);
2517             return;
2518         }
2519
2520         float perspectiveValue;
2521         if (primitiveValue->isLength())
2522             perspectiveValue = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2523         else if (primitiveValue->isNumber()) {
2524             // For backward compatibility, treat valueless numbers as px.
2525             Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX));
2526             perspectiveValue = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2527         } else
2528             return;
2529
2530         if (perspectiveValue >= 0.0f)
2531             state.style()->setPerspective(perspectiveValue);
2532         return;
2533     }
2534 #if PLATFORM(IOS)
2535     case CSSPropertyWebkitTouchCallout: {
2536         HANDLE_INHERIT_AND_INITIAL(touchCalloutEnabled, TouchCalloutEnabled);
2537         if (!primitiveValue)
2538             break;
2539
2540         state.style()->setTouchCalloutEnabled(primitiveValue->getStringValue().lower() != "none");
2541         return;
2542     }
2543 #endif
2544 #if ENABLE(TOUCH_EVENTS)
2545     case CSSPropertyWebkitTapHighlightColor: {
2546         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
2547         if (!primitiveValue)
2548             break;
2549
2550         Color col = colorFromPrimitiveValue(primitiveValue);
2551         state.style()->setTapHighlightColor(col);
2552         return;
2553     }
2554 #endif
2555 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
2556     case CSSPropertyWebkitOverflowScrolling: {
2557         HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
2558         if (!primitiveValue)
2559             break;
2560         state.style()->setUseTouchOverflowScrolling(primitiveValue->getValueID() == CSSValueTouch);
2561         return;
2562     }
2563 #endif
2564     case CSSPropertyInvalid:
2565         return;
2566     case CSSPropertyFontStretch:
2567     case CSSPropertyPage:
2568     case CSSPropertyTextLineThrough:
2569     case CSSPropertyTextLineThroughColor:
2570     case CSSPropertyTextLineThroughMode:
2571     case CSSPropertyTextLineThroughStyle:
2572     case CSSPropertyTextLineThroughWidth:
2573     case CSSPropertyTextOverline:
2574     case CSSPropertyTextOverlineColor:
2575     case CSSPropertyTextOverlineMode:
2576     case CSSPropertyTextOverlineStyle:
2577     case CSSPropertyTextOverlineWidth:
2578     case CSSPropertyTextUnderline:
2579     case CSSPropertyTextUnderlineColor:
2580     case CSSPropertyTextUnderlineMode:
2581     case CSSPropertyTextUnderlineStyle:
2582     case CSSPropertyTextUnderlineWidth:
2583     case CSSPropertyWebkitFontSizeDelta:
2584     case CSSPropertyWebkitTextDecorationsInEffect:
2585         return;
2586
2587     // CSS Text Layout Module Level 3: Vertical writing support
2588     case CSSPropertyWebkitWritingMode: {
2589         HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
2590         
2591         if (primitiveValue)
2592             setWritingMode(*primitiveValue);
2593
2594         // FIXME: It is not ok to modify document state while applying style.
2595         if (state.element() && state.element() == state.document().documentElement())
2596             state.document().setWritingModeSetOnDocumentElement(true);
2597         return;
2598     }
2599
2600     case CSSPropertyWebkitTextOrientation: {
2601         HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation);
2602
2603         if (primitiveValue)
2604             setTextOrientation(*primitiveValue);
2605
2606         return;
2607     }
2608
2609     case CSSPropertyWebkitLineBoxContain: {
2610         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
2611         if (primitiveValue && primitiveValue->getValueID() == CSSValueNone) {
2612             state.style()->setLineBoxContain(LineBoxContainNone);
2613             return;
2614         }
2615
2616         if (!value->isLineBoxContainValue())
2617             return;
2618
2619         state.style()->setLineBoxContain(toCSSLineBoxContainValue(value)->value());
2620         return;
2621     }
2622
2623     // CSS Fonts Module Level 3
2624     case CSSPropertyWebkitFontFeatureSettings: {
2625         if (primitiveValue && primitiveValue->getValueID() == CSSValueNormal) {
2626             setFontDescription(state.style()->fontDescription().makeNormalFeatureSettings());
2627             return;
2628         }
2629
2630         if (!value->isValueList())
2631             return;
2632
2633         FontDescription fontDescription = state.style()->fontDescription();
2634         CSSValueList* list = toCSSValueList(value);
2635         RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
2636         int len = list->length();
2637         for (int i = 0; i < len; ++i) {
2638             CSSValue* item = list->itemWithoutBoundsCheck(i);
2639             if (!item->isFontFeatureValue())
2640                 continue;
2641             CSSFontFeatureValue* feature = toCSSFontFeatureValue(item);
2642             settings->append(FontFeature(feature->tag(), feature->value()));
2643         }
2644         fontDescription.setFeatureSettings(settings.release());
2645         setFontDescription(fontDescription);
2646         return;
2647     }
2648
2649 #if ENABLE(CSS_FILTERS)
2650     case CSSPropertyWebkitFilter: {
2651         HANDLE_INHERIT_AND_INITIAL(filter, Filter);
2652         FilterOperations operations;
2653         if (createFilterOperations(value, operations))
2654             state.style()->setFilter(operations);
2655         return;
2656     }
2657 #endif
2658     case CSSPropertyWebkitGridAutoColumns: {
2659         HANDLE_INHERIT_AND_INITIAL(gridAutoColumns, GridAutoColumns);
2660         GridTrackSize trackSize;
2661         if (!createGridTrackSize(value, trackSize, state))
2662             return;
2663         state.style()->setGridAutoColumns(trackSize);
2664         return;
2665     }
2666     case CSSPropertyWebkitGridAutoRows: {
2667         HANDLE_INHERIT_AND_INITIAL(gridAutoRows, GridAutoRows);
2668         GridTrackSize trackSize;
2669         if (!createGridTrackSize(value, trackSize, state))
2670             return;
2671         state.style()->setGridAutoRows(trackSize);
2672         return;
2673     }
2674     case CSSPropertyWebkitGridDefinitionColumns: {
2675         if (isInherit) {
2676             m_state.style()->setGridColumns(m_state.parentStyle()->gridColumns());
2677             m_state.style()->setNamedGridColumnLines(m_state.parentStyle()->namedGridColumnLines());
2678             return;
2679         }
2680         if (isInitial) {
2681             m_state.style()->setGridColumns(RenderStyle::initialGridColumns());
2682             m_state.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines());
2683             return;
2684         }
2685         Vector<GridTrackSize> trackSizes;
2686         NamedGridLinesMap namedGridLines;
2687         if (!createGridTrackList(value, trackSizes, namedGridLines, state))
2688             return;
2689         state.style()->setGridColumns(trackSizes);
2690         state.style()->setNamedGridColumnLines(namedGridLines);
2691         return;
2692     }
2693     case CSSPropertyWebkitGridDefinitionRows: {
2694         if (isInherit) {
2695             m_state.style()->setGridRows(m_state.parentStyle()->gridRows());
2696             m_state.style()->setNamedGridRowLines(m_state.parentStyle()->namedGridRowLines());
2697             return;
2698         }
2699         if (isInitial) {
2700             m_state.style()->setGridRows(RenderStyle::initialGridRows());
2701             m_state.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines());
2702             return;
2703         }
2704         Vector<GridTrackSize> trackSizes;
2705         NamedGridLinesMap namedGridLines;
2706         if (!createGridTrackList(value, trackSizes, namedGridLines, state))
2707             return;
2708         state.style()->setGridRows(trackSizes);
2709         state.style()->setNamedGridRowLines(namedGridLines);
2710         return;
2711     }
2712
2713     case CSSPropertyWebkitGridColumnStart: {
2714         HANDLE_INHERIT_AND_INITIAL(gridItemColumnStart, GridItemColumnStart);
2715         GridPosition columnStartPosition;
2716         if (!createGridPosition(value, columnStartPosition))
2717             return;
2718         state.style()->setGridItemColumnStart(columnStartPosition);
2719         return;
2720     }
2721     case CSSPropertyWebkitGridColumnEnd: {
2722         HANDLE_INHERIT_AND_INITIAL(gridItemColumnEnd, GridItemColumnEnd);
2723         GridPosition columnEndPosition;
2724         if (!createGridPosition(value, columnEndPosition))
2725             return;
2726         state.style()->setGridItemColumnEnd(columnEndPosition);
2727         return;
2728     }
2729
2730     case CSSPropertyWebkitGridRowStart: {
2731         HANDLE_INHERIT_AND_INITIAL(gridItemRowStart, GridItemRowStart);
2732         GridPosition rowStartPosition;
2733         if (!createGridPosition(value, rowStartPosition))
2734             return;
2735         state.style()->setGridItemRowStart(rowStartPosition);
2736         return;
2737     }
2738     case CSSPropertyWebkitGridRowEnd: {
2739         HANDLE_INHERIT_AND_INITIAL(gridItemRowEnd, GridItemRowEnd);
2740         GridPosition rowEndPosition;
2741         if (!createGridPosition(value, rowEndPosition))
2742             return;
2743         state.style()->setGridItemRowEnd(rowEndPosition);
2744         return;
2745     }
2746     case CSSPropertyWebkitGridTemplate: {
2747         if (isInherit) {
2748             state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
2749             state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
2750             state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
2751             return;
2752         }
2753         if (isInitial) {
2754             state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
2755             state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
2756             state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
2757             return;
2758         }
2759
2760         if (value->isPrimitiveValue()) {
2761             ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
2762             return;
2763         }
2764
2765         CSSGridTemplateValue* gridTemplateValue = toCSSGridTemplateValue(value);
2766         state.style()->setNamedGridArea(gridTemplateValue->gridAreaMap());
2767         state.style()->setNamedGridAreaRowCount(gridTemplateValue->rowCount());
2768         state.style()->setNamedGridAreaColumnCount(gridTemplateValue->columnCount());
2769         return;
2770     }
2771
2772     // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version.
2773     case CSSPropertyTransitionDelay:
2774     case CSSPropertyTransitionDuration:
2775     case CSSPropertyTransitionProperty:
2776     case CSSPropertyTransitionTimingFunction:
2777         return;
2778     // These properties are implemented in the DeprecatedStyleBuilder lookup table.
2779     case CSSPropertyBackgroundAttachment:
2780     case CSSPropertyBackgroundClip:
2781     case CSSPropertyBackgroundColor:
2782     case CSSPropertyBackgroundImage:
2783     case CSSPropertyBackgroundOrigin:
2784     case CSSPropertyBackgroundPositionX:
2785     case CSSPropertyBackgroundPositionY:
2786     case CSSPropertyBackgroundRepeatX:
2787     case CSSPropertyBackgroundRepeatY:
2788     case CSSPropertyBackgroundSize:
2789     case CSSPropertyBorderBottomColor:
2790     case CSSPropertyBorderBottomLeftRadius:
2791     case CSSPropertyBorderBottomRightRadius:
2792     case CSSPropertyBorderBottomStyle:
2793     case CSSPropertyBorderBottomWidth:
2794     case CSSPropertyBorderCollapse:
2795     case CSSPropertyBorderImageOutset:
2796     case CSSPropertyBorderImageRepeat:
2797     case CSSPropertyBorderImageSlice:
2798     case CSSPropertyBorderImageSource:
2799     case CSSPropertyBorderImageWidth:
2800     case CSSPropertyBorderLeftColor:
2801     case CSSPropertyBorderLeftStyle:
2802     case CSSPropertyBorderLeftWidth:
2803     case CSSPropertyBorderRightColor:
2804     case CSSPropertyBorderRightStyle:
2805     case CSSPropertyBorderRightWidth:
2806     case CSSPropertyBorderTopColor:
2807     case CSSPropertyBorderTopLeftRadius:
2808     case CSSPropertyBorderTopRightRadius:
2809     case CSSPropertyBorderTopStyle:
2810     case CSSPropertyBorderTopWidth:
2811     case CSSPropertyBottom:
2812     case CSSPropertyBoxSizing:
2813     case CSSPropertyCaptionSide:
2814     case CSSPropertyClear:
2815     case CSSPropertyClip:
2816     case CSSPropertyColor:
2817     case CSSPropertyCounterIncrement:
2818     case CSSPropertyCounterReset:
2819     case CSSPropertyCursor:
2820     case CSSPropertyDirection:
2821     case CSSPropertyDisplay:
2822     case CSSPropertyEmptyCells:
2823     case CSSPropertyFloat:
2824     case CSSPropertyFontSize:
2825     case CSSPropertyFontStyle:
2826     case CSSPropertyFontVariant:
2827     case CSSPropertyFontWeight:
2828     case CSSPropertyHeight:
2829 #if ENABLE(CSS_IMAGE_ORIENTATION)
2830     case CSSPropertyImageOrientation:
2831 #endif
2832     case CSSPropertyImageRendering:
2833 #if ENABLE(CSS_IMAGE_RESOLUTION)
2834     case CSSPropertyImageResolution:
2835 #endif
2836     case CSSPropertyLeft:
2837     case CSSPropertyLetterSpacing:
2838     case CSSPropertyLineHeight:
2839     case CSSPropertyListStyleImage:
2840     case CSSPropertyListStylePosition:
2841     case CSSPropertyListStyleType:
2842     case CSSPropertyMarginBottom:
2843     case CSSPropertyMarginLeft:
2844     case CSSPropertyMarginRight:
2845     case CSSPropertyMarginTop:
2846     case CSSPropertyMaxHeight:
2847     case CSSPropertyMaxWidth:
2848     case CSSPropertyMinHeight:
2849     case CSSPropertyMinWidth:
2850     case CSSPropertyObjectFit:
2851     case CSSPropertyOpacity:
2852     case CSSPropertyOrphans:
2853     case CSSPropertyOutlineColor:
2854     case CSSPropertyOutlineOffset:
2855     case CSSPropertyOutlineStyle:
2856     case CSSPropertyOutlineWidth:
2857     case CSSPropertyOverflowWrap:
2858     case CSSPropertyOverflowX:
2859     case CSSPropertyOverflowY:
2860     case CSSPropertyPaddingBottom:
2861     case CSSPropertyPaddingLeft:
2862     case CSSPropertyPaddingRight:
2863     case CSSPropertyPaddingTop:
2864     case CSSPropertyPageBreakAfter:
2865     case CSSPropertyPageBreakBefore:
2866     case CSSPropertyPageBreakInside:
2867     case CSSPropertyPointerEvents:
2868     case CSSPropertyPosition:
2869     case CSSPropertyResize:
2870     case CSSPropertyRight:
2871     case CSSPropertySize:
2872     case CSSPropertySpeak:
2873     case CSSPropertyTabSize:
2874     case CSSPropertyTableLayout:
2875     case CSSPropertyTextAlign:
2876     case CSSPropertyTextDecoration:
2877     case CSSPropertyTextIndent:
2878     case CSSPropertyTextOverflow:
2879     case CSSPropertyTextRendering:
2880     case CSSPropertyTextTransform:
2881     case CSSPropertyTop:
2882     case CSSPropertyUnicodeBidi:
2883     case CSSPropertyVerticalAlign:
2884     case CSSPropertyVisibility:
2885     case CSSPropertyWebkitAnimationDelay:
2886     case CSSPropertyWebkitAnimationDirection:
2887     case CSSPropertyWebkitAnimationDuration:
2888     case CSSPropertyWebkitAnimationFillMode:
2889     case CSSPropertyWebkitAnimationIterationCount:
2890     case CSSPropertyWebkitAnimationName:
2891     case CSSPropertyWebkitAnimationPlayState:
2892     case CSSPropertyWebkitAnimationTimingFunction:
2893     case CSSPropertyWebkitAppearance:
2894     case CSSPropertyWebkitAspectRatio:
2895     case CSSPropertyWebkitBackfaceVisibility:
2896     case CSSPropertyWebkitBackgroundClip:
2897     case CSSPropertyWebkitBackgroundComposite:
2898     case CSSPropertyWebkitBackgroundOrigin:
2899     case CSSPropertyWebkitBackgroundSize:
2900     case CSSPropertyWebkitBorderFit:
2901     case CSSPropertyWebkitBorderHorizontalSpacing:
2902     case CSSPropertyWebkitBorderImage:
2903     case CSSPropertyWebkitBorderVerticalSpacing:
2904     case CSSPropertyWebkitBoxAlign:
2905 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2906     case CSSPropertyWebkitBoxDecorationBreak:
2907 #endif
2908     case CSSPropertyWebkitBoxDirection:
2909     case CSSPropertyWebkitBoxFlex:
2910     case CSSPropertyWebkitBoxFlexGroup:
2911     case CSSPropertyWebkitBoxLines:
2912     case CSSPropertyWebkitBoxOrdinalGroup:
2913     case CSSPropertyWebkitBoxOrient:
2914     case CSSPropertyWebkitBoxPack:
2915     case CSSPropertyWebkitColorCorrection:
2916     case CSSPropertyWebkitColumnAxis:
2917     case CSSPropertyWebkitColumnBreakAfter:
2918     case CSSPropertyWebkitColumnBreakBefore:
2919     case CSSPropertyWebkitColumnBreakInside:
2920     case CSSPropertyWebkitColumnCount:
2921     case CSSPropertyWebkitColumnGap:
2922     case CSSPropertyWebkitColumnProgression:
2923     case CSSPropertyWebkitColumnRuleColor:
2924     case CSSPropertyWebkitColumnRuleStyle:
2925     case CSSPropertyWebkitColumnRuleWidth:
2926     case CSSPropertyWebkitColumnSpan:
2927     case CSSPropertyWebkitColumnWidth:
2928 #if ENABLE(CURSOR_VISIBILITY)
2929     case CSSPropertyWebkitCursorVisibility:
2930 #endif
2931     case CSSPropertyWebkitAlignContent:
2932     case CSSPropertyWebkitAlignItems:
2933     case CSSPropertyWebkitAlignSelf:
2934     case CSSPropertyWebkitFlexBasis:
2935     case CSSPropertyWebkitFlexDirection:
2936     case CSSPropertyWebkitFlexGrow:
2937     case CSSPropertyWebkitFlexShrink:
2938     case CSSPropertyWebkitFlexWrap:
2939     case CSSPropertyWebkitJustifyContent:
2940     case CSSPropertyWebkitOrder:
2941 #if ENABLE(CSS_REGIONS)
2942     case CSSPropertyWebkitFlowFrom:
2943     case CSSPropertyWebkitFlowInto:
2944 #endif
2945     case CSSPropertyWebkitFontKerning:
2946     case CSSPropertyWebkitFontSmoothing:
2947     case CSSPropertyWebkitFontVariantLigatures:
2948     case CSSPropertyWebkitHighlight:
2949     case CSSPropertyWebkitHyphenateCharacter:
2950     case CSSPropertyWebkitHyphenateLimitAfter:
2951     case CSSPropertyWebkitHyphenateLimitBefore:
2952     case CSSPropertyWebkitHyphenateLimitLines:
2953     case CSSPropertyWebkitHyphens:
2954     case CSSPropertyWebkitLineAlign:
2955     case CSSPropertyWebkitLineBreak:
2956     case CSSPropertyWebkitLineClamp:
2957     case CSSPropertyWebkitLineGrid:
2958     case CSSPropertyWebkitLineSnap:
2959     case CSSPropertyWebkitMarqueeDirection:
2960     case CSSPropertyWebkitMarqueeIncrement:
2961     case CSSPropertyWebkitMarqueeRepetition:
2962     case CSSPropertyWebkitMarqueeSpeed:
2963     case CSSPropertyWebkitMarqueeStyle:
2964     case CSSPropertyWebkitMaskBoxImage:
2965     case CSSPropertyWebkitMaskBoxImageOutset:
2966     case CSSPropertyWebkitMaskBoxImageRepeat:
2967     case CSSPropertyWebkitMaskBoxImageSlice:
2968     case CSSPropertyWebkitMaskBoxImageSource:
2969     case CSSPropertyWebkitMaskBoxImageWidth:
2970     case CSSPropertyWebkitMaskClip:
2971     case CSSPropertyWebkitMaskComposite:
2972     case CSSPropertyWebkitMaskImage:
2973     case CSSPropertyWebkitMaskOrigin:
2974     case CSSPropertyWebkitMaskPositionX:
2975     case CSSPropertyWebkitMaskPositionY:
2976     case CSSPropertyWebkitMaskRepeatX:
2977     case CSSPropertyWebkitMaskRepeatY:
2978     case CSSPropertyWebkitMaskSize:
2979     case CSSPropertyWebkitMaskSourceType:
2980     case CSSPropertyWebkitNbspMode:
2981     case CSSPropertyWebkitPerspectiveOrigin:
2982     case CSSPropertyWebkitPerspectiveOriginX:
2983     case CSSPropertyWebkitPerspectiveOriginY:
2984     case CSSPropertyWebkitPrintColorAdjust:
2985 #if ENABLE(CSS_REGIONS)
2986     case CSSPropertyWebkitRegionBreakAfter:
2987     case CSSPropertyWebkitRegionBreakBefore:
2988     case CSSPropertyWebkitRegionBreakInside:
2989     case CSSPropertyWebkitRegionFragment:
2990 #endif
2991     case CSSPropertyWebkitRtlOrdering:
2992     case CSSPropertyWebkitRubyPosition:
2993     case CSSPropertyWebkitTextCombine:
2994 #if ENABLE(CSS3_TEXT)
2995     case CSSPropertyWebkitTextAlignLast:
2996     case CSSPropertyWebkitTextJustify:
2997 #endif // CSS3_TEXT
2998 #if ENABLE(CSS3_TEXT_DECORATION)
2999     case CSSPropertyWebkitTextDecorationLine:
3000     case CSSPropertyWebkitTextDecorationStyle:
3001     case CSSPropertyWebkitTextDecorationColor:
3002     case CSSPropertyWebkitTextDecorationSkip:
3003     case CSSPropertyWebkitTextUnderlinePosition:
3004 #endif
3005     case CSSPropertyWebkitTextEmphasisColor:
3006     case CSSPropertyWebkitTextEmphasisPosition:
3007     case CSSPropertyWebkitTextEmphasisStyle:
3008     case CSSPropertyWebkitTextFillColor:
3009     case CSSPropertyWebkitTextSecurity:
3010     case CSSPropertyWebkitTextStrokeColor:
3011     case CSSPropertyWebkitTransformOriginX:
3012     case CSSPropertyWebkitTransformOriginY:
3013     case CSSPropertyWebkitTransformOriginZ:
3014     case CSSPropertyWebkitTransformStyle:
3015     case CSSPropertyWebkitTransitionDelay:
3016     case CSSPropertyWebkitTransitionDuration:
3017     case CSSPropertyWebkitTransitionProperty:
3018     case CSSPropertyWebkitTransitionTimingFunction:
3019     case CSSPropertyWebkitUserDrag:
3020     case CSSPropertyWebkitUserModify:
3021     case CSSPropertyWebkitUserSelect:
3022     case CSSPropertyWebkitClipPath:
3023 #if ENABLE(CSS_SHAPES)
3024     case CSSPropertyWebkitShapeMargin:
3025     case CSSPropertyWebkitShapePadding:
3026     case CSSPropertyWebkitShapeImageThreshold:
3027     case CSSPropertyWebkitShapeInside:
3028     case CSSPropertyWebkitShapeOutside:
3029 #endif
3030 #if ENABLE(CSS_EXCLUSIONS)
3031     case CSSPropertyWebkitWrapFlow:
3032     case CSSPropertyWebkitWrapThrough:
3033 #endif
3034 #if ENABLE(CSS_SHADERS)
3035     case CSSPropertyMix:
3036     case CSSPropertyParameters:
3037 #endif
3038     case CSSPropertyWhiteSpace:
3039     case CSSPropertyWidows:
3040     case CSSPropertyWidth:
3041     case CSSPropertyWordBreak:
3042     case CSSPropertyWordSpacing:
3043     case CSSPropertyWordWrap:
3044     case CSSPropertyZIndex:
3045     case CSSPropertyZoom:
3046 #if ENABLE(CSS_DEVICE_ADAPTATION)
3047     case CSSPropertyMaxZoom:
3048     case CSSPropertyMinZoom:
3049     case CSSPropertyOrientation:
3050     case CSSPropertyUserZoom:
3051 #endif
3052         ASSERT_NOT_REACHED();
3053         return;
3054     default:
3055 #if ENABLE(SVG)
3056         // Try the SVG properties
3057         applySVGProperty(id, value);
3058 #endif
3059         return;
3060     }
3061 }
3062
3063 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value)
3064 {
3065     if (value->isImageValue())
3066         return cachedOrPendingFromValue(property, toCSSImageValue(value));
3067
3068     if (value->isImageGeneratorValue()) {
3069         if (value->isGradientValue())
3070             return generatedOrPendingFromValue(property, toCSSGradientValue(value)->gradientWithStylesResolved(this).get());
3071         return generatedOrPendingFromValue(property, static_cast<CSSImageGeneratorValue*>(value));
3072     }
3073
3074 #if ENABLE(CSS_IMAGE_SET)
3075     if (value->isImageSetValue())
3076         return setOrPendingFromValue(property, toCSSImageSetValue(value));
3077 #endif
3078
3079     if (value->isCursorImageValue())
3080         return cursorOrPendingFromValue(property, toCSSCursorImageValue(value));
3081
3082     return 0;
3083 }
3084
3085 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
3086 {
3087     RefPtr<StyleImage> image = value->cachedOrPendingImage();
3088     if (image && image->isPendingImage())
3089         m_state.pendingImageProperties().set(property, value);
3090     return image.release();
3091 }
3092
3093 PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue* value)
3094 {
3095 #if ENABLE(CSS_FILTERS)
3096     if (value->isFilterImageValue()) {
3097         // FilterImage needs to calculate FilterOperations.
3098         toCSSFilterImageValue(value)->createFilterOperations(this);
3099     }
3100 #endif
3101     if (value->isPending()) {
3102         m_state.pendingImageProperties().set(property, value);
3103         return StylePendingImage::create(value);
3104     }
3105     return StyleGeneratedImage::create(value);
3106 }
3107
3108 #if ENABLE(CSS_IMAGE_SET)
3109 PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value)
3110 {
3111     RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document());
3112     if (image && image->isPendingImage())
3113         m_state.pendingImageProperties().set(property, value);
3114     return image.release();
3115 }
3116 #endif
3117
3118 PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue* value)
3119 {
3120     RefPtr<StyleImage> image = value->cachedOrPendingImage(document());
3121     if (image && image->isPendingImage())
3122         m_state.pendingImageProperties().set(property, value);
3123     return image.release();
3124 }
3125
3126 #if ENABLE(IOS_TEXT_AUTOSIZING)
3127 void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
3128 {
3129     if (style->textSizeAdjust().isAuto())
3130         return;
3131
3132     FontDescription newFontDescription(style->fontDescription());
3133     if (!style->textSizeAdjust().isNone())
3134         newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier());
3135     else
3136         newFontDescription.setComputedSize(newFontDescription.specifiedSize());
3137     style->setFontDescription(newFontDescription);
3138 }
3139 #endif
3140
3141 void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
3142 {
3143     if (style->effectiveZoom() == parentStyle->effectiveZoom())
3144         return;
3145
3146     const FontDescription& childFont = style->fontDescription();
3147     FontDescription newFontDescription(childFont);
3148     setFontSize(newFontDescription, childFont.specifiedSize());
3149     style->setFontDescription(newFontDescription);
3150 }
3151
3152 void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
3153 {
3154     const FontDescription& childFont = style->fontDescription();
3155
3156     if (childFont.isAbsoluteSize() || !parentStyle)
3157         return;
3158
3159     const FontDescription& parentFont = parentStyle->fontDescription();
3160     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
3161         return;
3162
3163     // For now, lump all families but monospace together.
3164     if (childFont.genericFamily() != FontDescription::MonospaceFamily
3165         && parentFont.genericFamily() != FontDescription::MonospaceFamily)
3166         return;
3167
3168     // We know the parent is monospace or the child is monospace, and that font
3169     // size was unspecified. We want to scale our font size as appropriate.
3170     // If the font uses a keyword size, then we refetch from the table rather than
3171     // multiplying by our scale factor.
3172     float size;
3173     if (childFont.keywordSize())
3174         size = Style::fontSizeForKeyword(CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize(), document());
3175     else {
3176         Settings* settings = documentSettings();
3177         float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
3178             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
3179             : 1;
3180         size = parentFont.useFixedDefaultSize() ?
3181                 childFont.specifiedSize() / fixedScaleFactor :
3182                 childFont.specifiedSize() * fixedScaleFactor;
3183     }
3184
3185     FontDescription newFontDescription(childFont);
3186     setFontSize(newFontDescription, size);
3187     style->setFontDescription(newFontDescription);
3188 }
3189
3190 void StyleResolver::initializeFontStyle(Settings* settings)
3191 {
3192     FontDescription fontDescription;
3193     fontDescription.setGenericFamily(FontDescription::StandardFamily);
3194     fontDescription.setRenderingMode(settings->fontRenderingMode());
3195     fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
3196     const AtomicString& standardFontFamily = documentSettings()->standardFontFamily();
3197     if (!standardFontFamily.isEmpty())
3198         fontDescription.setOneFamily(standardFontFamily);
3199     fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3200     setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
3201     m_state.style()->setLineHeight(RenderStyle::initialLineHeight());
3202     m_state.setLineHeightValue(0);
3203     setFontDescription(fontDescription);
3204 }
3205
3206 void StyleResolver::setFontSize(FontDescription& fontDescription, float size)
3207 {
3208     fontDescription.setSpecifiedSize(size);
3209     fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
3210 }
3211
3212 static Color colorForCSSValue(CSSValueID cssValueId)
3213 {
3214     struct ColorValue {
3215         CSSValueID cssValueId;
3216         RGBA32 color;
3217     };
3218
3219     static const ColorValue colorValues[] = {
3220         { CSSValueAqua, 0xFF00FFFF },
3221         { CSSValueBlack, 0xFF000000 },
3222         { CSSValueBlue, 0xFF0000FF },
3223         { CSSValueFuchsia, 0xFFFF00FF },
3224         { CSSValueGray, 0xFF808080 },
3225         { CSSValueGreen, 0xFF008000  },
3226         { CSSValueGrey, 0xFF808080 },
3227         { CSSValueLime, 0xFF00FF00 },
3228         { CSSValueMaroon, 0xFF800000 },
3229         { CSSValueNavy, 0xFF000080 },
3230         { CSSValueOlive, 0xFF808000  },
3231         { CSSValueOrange, 0xFFFFA500 },
3232         { CSSValuePurple, 0xFF800080 },
3233         { CSSValueRed, 0xFFFF0000 },
3234         { CSSValueSilver, 0xFFC0C0C0 },
3235         { CSSValueTeal, 0xFF008080  },
3236         { CSSValueTransparent, 0x00000000 },
3237         { CSSValueWhite, 0xFFFFFFFF },
3238         { CSSValueYellow, 0xFFFFFF00 },
3239         { CSSValueInvalid, CSSValueInvalid }
3240     };
3241
3242     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
3243         if (col->cssValueId == cssValueId)
3244             return col->color;
3245     }
3246     return RenderTheme::defaultTheme()->systemColor(cssValueId);
3247 }
3248
3249 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue* value)
3250 {
3251     int ident = value->getValueID();
3252     switch (ident) {
3253     case CSSValueWebkitText:
3254     case CSSValueWebkitLink:
3255     case CSSValueWebkitActivelink:
3256     case CSSValueCurrentcolor:
3257         return true;
3258     default:
3259         return false;
3260     }
3261 }
3262
3263 Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const
3264 {
3265     if (value->isRGBColor())
3266         return Color(value->getRGBA32Value());
3267
3268     const State& state = m_state;
3269     CSSValueID ident = value->getValueID();
3270     switch (ident) {
3271     case 0:
3272         return Color();
3273     case CSSValueWebkitText:
3274         return state.document().textColor();
3275     case CSSValueWebkitLink:
3276         return (state.element()->isLink() && forVisitedLink) ? state.document().visitedLinkColor() : state.document().linkColor();
3277     case CSSValueWebkitActivelink:
3278         return state.document().activeLinkColor();
3279     case CSSValueWebkitFocusRingColor:
3280         return RenderTheme::focusRingColor();
3281     case CSSValueCurrentcolor:
3282         return state.style()->color();
3283     default:
3284         return colorForCSSValue(ident);
3285     }
3286 }
3287
3288 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
3289 {
3290     m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*expr, result)));
3291 }
3292
3293 bool StyleResolver::affectedByViewportChange() const
3294 {
3295     unsigned s = m_viewportDependentMediaQueryResults.size();
3296     for (unsigned i = 0; i < s; i++) {
3297         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
3298             return true;
3299     }
3300     return false;
3301 }
3302
3303 #if ENABLE(CSS_FILTERS)
3304 static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
3305 {
3306     switch (type) {
3307     case WebKitCSSFilterValue::ReferenceFilterOperation:
3308         return FilterOperation::REFERENCE;
3309     case WebKitCSSFilterValue::GrayscaleFilterOperation:
3310         return FilterOperation::GRAYSCALE;
3311     case WebKitCSSFilterValue::SepiaFilterOperation:
3312         return FilterOperation::SEPIA;
3313     case WebKitCSSFilterValue::SaturateFilterOperation:
3314         return FilterOperation::SATURATE;
3315     case WebKitCSSFilterValue::HueRotateFilterOperation:
3316         return FilterOperation::HUE_ROTATE;
3317     case WebKitCSSFilterValue::InvertFilterOperation:
3318         return FilterOperation::INVERT;
3319     case WebKitCSSFilterValue::OpacityFilterOperation:
3320         return FilterOperation::OPACITY;
3321     case WebKitCSSFilterValue::BrightnessFilterOperation:
3322         return FilterOperation::BRIGHTNESS;
3323     case WebKitCSSFilterValue::ContrastFilterOperation:
3324         return FilterOperation::CONTRAST;
3325     case WebKitCSSFilterValue::BlurFilterOperation:
3326         return FilterOperation::BLUR;
3327     case WebKitCSSFilterValue::DropShadowFilterOperation:
3328         return FilterOperation::DROP_SHADOW;
3329 #if ENABLE(CSS_SHADERS)
3330     case WebKitCSSFilterValue::CustomFilterOperation:
3331         return FilterOperation::CUSTOM;
3332 #endif
3333     case WebKitCSSFilterValue::UnknownFilterOperation:
3334         return FilterOperation::NONE;
3335     }
3336     return FilterOperation::NONE;
3337 }
3338
3339 #if ENABLE(CSS_FILTERS) && ENABLE(SVG)
3340 void StyleResolver::loadPendingSVGDocuments()
3341 {
3342     State& state = m_state;
3343
3344     // Crash reports indicate that we've seen calls to this function when our
3345     // style is NULL. We don't know exactly why this happens. Our guess is
3346     // reentering styleForElement().
3347     ASSERT(state.style());
3348     if (!state.style() || !state.style()->hasFilter() || state.pendingSVGDocuments().isEmpty())
3349         return;
3350
3351     CachedResourceLoader* cachedResourceLoader = state.document().cachedResourceLoader();
3352     Vector<RefPtr<FilterOperation>>& filterOperations = state.style()->mutableFilter().operations();
3353     for (unsigned i = 0; i < filterOperations.size(); ++i) {
3354         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
3355         if (filterOperation->type() == FilterOperation::REFERENCE) {
3356             ReferenceFilterOperation* referenceFilter = static_cast<ReferenceFilterOperation*>(filterOperation.get());
3357
3358             WebKitCSSSVGDocumentValue* value = state.pendingSVGDocuments().get(referenceFilter);
3359             if (!value)
3360                 continue;
3361             CachedSVGDocument* cachedDocument = value->load(cachedResourceLoader);
3362             if (!cachedDocument)
3363                 continue;
3364
3365             // Stash the CachedSVGDocument on the reference filter.
3366             referenceFilter->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(cachedDocument)));
3367         }
3368     }
3369     state.pendingSVGDocuments().clear();
3370 }
3371 #endif
3372
3373 #if ENABLE(CSS_SHADERS)
3374 StyleShader* StyleResolver::styleShader(CSSValue* value)
3375 {
3376     if (value->isWebKitCSSShaderValue())
3377         return cachedOrPendingStyleShaderFromValue(toWebKitCSSShaderValue(value));
3378     return 0;
3379 }
3380
3381 StyleShader* StyleResolver::cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue* value)
3382 {
3383     StyleShader* shader = value->cachedOrPendingShader();
3384     if (shader && shader->isPendingShader())
3385         m_state.setHasPendingShaders(true);
3386     return shader;
3387 }
3388
3389 PassRefPtr<CustomFilterProgram> StyleResolver::lookupCustomFilterProgram(WebKitCSSShaderValue* vertexShader, WebKitCSSShaderValue* fragmentShader, 
3390     CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
3391 {
3392     CachedResourceLoader* cachedResourceLoader = m_state.document().cachedResourceLoader();
3393     URL vertexShaderURL = vertexShader ? vertexShader->completeURL(cachedResourceLoader) : URL();
3394     URL fragmentShaderURL = fragmentShader ? fragmentShader->completeURL(cachedResourceLoader) : URL();
3395     RefPtr<StyleCustomFilterProgram> program;
3396     if (m_customFilterProgramCache)
3397         program = m_customFilterProgramCache->lookup(CustomFilterProgramInfo(vertexShaderURL, fragmentShaderURL, programType, mixSettings, meshType));
3398     if (!program) {
3399         // Create a new StyleCustomFilterProgram that will be resolved during the loadPendingShaders and added to the cache.
3400         program = StyleCustomFilterProgram::create(vertexShaderURL, vertexShader ? styleShader(vertexShader) : 0, 
3401             fragmentShaderURL, fragmentShader ? styleShader(fragmentShader) : 0, programType, mixSettings, meshType);
3402     }
3403     return program.release();
3404 }
3405
3406 void StyleResolver::loadPendingShaders()
3407 {
3408     // FIXME: We shouldn't have to check that style is non-null. This is a speculative fix for:
3409     // https://bugs.webkit.org/show_bug.cgi?id=117665
3410     if (!m_state.hasPendingShaders() || !m_state.style() || !m_state.style()->hasFilter())
3411         return;
3412
3413     CachedResourceLoader* cachedResourceLoader = m_state.document().cachedResourceLoader();
3414
3415     Vector<RefPtr<FilterOperation>>& filterOperations = m_state.style()->mutableFilter().operations();
3416     for (unsigned i = 0; i < filterOperations.size(); ++i) {
3417         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
3418         if (filterOperation->type() == FilterOperation::CUSTOM) {
3419             CustomFilterOperation* customFilter = static_cast<CustomFilterOperation*>(filterOperation.get());
3420             ASSERT(customFilter->program());
3421             StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customFilter->program());
3422             // Note that the StylePendingShaders could be already resolved to StyleCachedShaders. That's because the rule was matched before.
3423             // However, the StyleCustomFilterProgram that was initially created could have been removed from the cache in the meanwhile,
3424           &nb