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