summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/StyleResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/StyleResolver.cpp')
-rw-r--r--Source/WebCore/css/StyleResolver.cpp2766
1 files changed, 2120 insertions, 646 deletions
diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp
index a8f26df84..827388f29 100644
--- a/Source/WebCore/css/StyleResolver.cpp
+++ b/Source/WebCore/css/StyleResolver.cpp
@@ -1,15 +1,14 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
* Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
* Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Copyright (C) Research In Motion Limited 2011. All rights reserved.
- * Copyright (C) 2012, 2013 Google Inc. All rights reserved.
- * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -30,10 +29,10 @@
#include "config.h"
#include "StyleResolver.h"
+#include "Attribute.h"
#include "CSSBorderImage.h"
#include "CSSCalculationValue.h"
#include "CSSCursorImageValue.h"
-#include "CSSCustomPropertyValue.h"
#include "CSSDefaultStyleSheets.h"
#include "CSSFilterImageValue.h"
#include "CSSFontFaceRule.h"
@@ -41,10 +40,7 @@
#include "CSSFontSelector.h"
#include "CSSFontValue.h"
#include "CSSFunctionValue.h"
-#include "CSSInheritedValue.h"
-#include "CSSInitialValue.h"
-#include "CSSKeyframeRule.h"
-#include "CSSKeyframesRule.h"
+#include "CSSGridTemplateValue.h"
#include "CSSLineBoxContainValue.h"
#include "CSSPageRule.h"
#include "CSSParser.h"
@@ -58,19 +54,16 @@
#include "CSSSupportsRule.h"
#include "CSSTimingFunctionValue.h"
#include "CSSValueList.h"
-#include "CSSValuePool.h"
-#include "CSSVariableDependentValue.h"
#include "CachedImage.h"
#include "CachedResourceLoader.h"
-#include "CachedSVGDocument.h"
-#include "CachedSVGDocumentReference.h"
#include "CalculationValue.h"
#include "ContentData.h"
#include "Counter.h"
#include "CounterContent.h"
#include "CursorList.h"
+#include "DeprecatedStyleBuilder.h"
+#include "DocumentStyleSheetCollection.h"
#include "ElementRuleCollector.h"
-#include "FilterOperation.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "FrameView.h"
@@ -84,6 +77,7 @@
#include "HTMLStyleElement.h"
#include "HTMLTableElement.h"
#include "HTMLTextAreaElement.h"
+#include "InsertionPoint.h"
#include "InspectorInstrumentation.h"
#include "KeyframeList.h"
#include "LinkHash.h"
@@ -92,13 +86,12 @@
#include "MediaList.h"
#include "MediaQueryEvaluator.h"
#include "NodeRenderStyle.h"
+#include "NodeRenderingTraversal.h"
#include "Page.h"
#include "PageRuleCollector.h"
#include "Pair.h"
-#include "PseudoElement.h"
#include "QuotesData.h"
#include "Rect.h"
-#include "RenderGrid.h"
#include "RenderRegion.h"
#include "RenderScrollbar.h"
#include "RenderScrollbarTheme.h"
@@ -106,17 +99,13 @@
#include "RenderTheme.h"
#include "RenderView.h"
#include "RuleSet.h"
-#include "SVGDocument.h"
#include "SVGDocumentExtensions.h"
#include "SVGFontFaceElement.h"
-#include "SVGNames.h"
-#include "SVGSVGElement.h"
-#include "SVGURIReference.h"
#include "SecurityOrigin.h"
+#include "SelectorCheckerFastPath.h"
#include "Settings.h"
#include "ShadowData.h"
#include "ShadowRoot.h"
-#include "StyleBuilder.h"
#include "StyleCachedImage.h"
#include "StyleFontSizeFunctions.h"
#include "StyleGeneratedImage.h"
@@ -125,7 +114,6 @@
#include "StylePropertyShorthand.h"
#include "StyleRule.h"
#include "StyleRuleImport.h"
-#include "StyleScrollSnapPoints.h"
#include "StyleSheetContents.h"
#include "StyleSheetList.h"
#include "Text.h"
@@ -134,20 +122,19 @@
#include "UserAgentStyleSheets.h"
#include "ViewportStyleResolver.h"
#include "VisitedLinkState.h"
-#include "WebKitCSSFilterValue.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
#include "WebKitCSSRegionRule.h"
#include "WebKitCSSTransformValue.h"
#include "WebKitFontFamilyNames.h"
#include "XMLNames.h"
#include <bitset>
#include <wtf/StdLibExtras.h>
-#include <wtf/TemporaryChange.h>
#include <wtf/Vector.h>
-#include <wtf/text/AtomicStringHash.h>
-#if ENABLE(CSS_GRID_LAYOUT)
-#include "CSSGridLineNamesValue.h"
-#include "CSSGridTemplateAreasValue.h"
+#if ENABLE(CSS_FILTERS)
+#include "FilterOperation.h"
+#include "WebKitCSSFilterValue.h"
#endif
#if ENABLE(CSS_IMAGE_SET)
@@ -159,23 +146,81 @@
#include "DashboardRegion.h"
#endif
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "HTMLAudioElement.h"
+#endif
+
+#if ENABLE(SVG)
+#include "CachedSVGDocument.h"
+#include "CachedSVGDocumentReference.h"
+#include "SVGDocument.h"
+#include "SVGElement.h"
+#include "SVGNames.h"
+#include "SVGURIReference.h"
+#endif
+
#if ENABLE(VIDEO_TRACK)
#include "WebVTTElement.h"
#endif
-#if ENABLE(CSS_SCROLL_SNAP)
-#include "LengthRepeat.h"
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "HTMLMediaElement.h"
#endif
namespace WebCore {
using namespace HTMLNames;
-static const CSSPropertyID lastHighPriorityProperty = CSSPropertyFontSynthesis;
-static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
+class StyleResolver::CascadedProperties {
+public:
+ CascadedProperties(TextDirection, WritingMode);
+
+ struct Property {
+ void apply(StyleResolver&);
+
+ CSSPropertyID id;
+ CSSValue* cssValue[3];
+ };
+
+ bool hasProperty(CSSPropertyID id) const { return m_propertyIsPresent.test(id); }
+ Property& property(CSSPropertyID);
+ bool addMatches(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly = false);
+
+ void set(CSSPropertyID, CSSValue&, unsigned linkMatchType);
+ void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType);
+
+ void applyDeferredProperties(StyleResolver&);
+
+private:
+ bool addStyleProperties(const StyleProperties&, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType);
+ static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType);
+
+ Property m_properties[numCSSProperties + 1];
+ std::bitset<numCSSProperties + 1> m_propertyIsPresent;
+
+ Vector<Property, 8> m_deferredProperties;
+
+ TextDirection m_direction;
+ WritingMode m_writingMode;
+};
static void extractDirectionAndWritingMode(const RenderStyle&, const StyleResolver::MatchResult&, TextDirection&, WritingMode&);
+#define HANDLE_INHERIT(prop, Prop) \
+if (isInherit) { \
+ m_state.style()->set##Prop(m_state.parentStyle()->prop()); \
+ return; \
+}
+
+#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
+HANDLE_INHERIT(prop, Prop) \
+if (isInitial) { \
+ m_state.style()->set##Prop(RenderStyle::initial##Prop()); \
+ return; \
+}
+
+RenderStyle* StyleResolver::s_styleNotYetAvailable;
+
inline void StyleResolver::State::cacheBorderAndBackground()
{
m_hasUAAppearance = m_style->hasAppearance();
@@ -189,65 +234,36 @@ inline void StyleResolver::State::cacheBorderAndBackground()
inline void StyleResolver::State::clear()
{
m_element = nullptr;
+ m_styledElement = nullptr;
m_parentStyle = nullptr;
+ m_parentNode = nullptr;
m_regionForStyling = nullptr;
m_pendingImageProperties.clear();
+#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
m_filtersWithPendingSVGDocuments.clear();
- m_cssToLengthConversionData = CSSToLengthConversionData();
+#endif
}
void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
{
- m_matchedProperties.grow(m_matchedProperties.size() + 1);
- StyleResolver::MatchedProperties& newProperties = m_matchedProperties.last();
+ matchedProperties.grow(matchedProperties.size() + 1);
+ StyleResolver::MatchedProperties& newProperties = matchedProperties.last();
newProperties.properties = const_cast<StyleProperties*>(&properties);
newProperties.linkMatchType = linkMatchType;
newProperties.whitelistType = propertyWhitelistType;
matchedRules.append(rule);
-
- if (isCacheable) {
- for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
- // Currently the property cache only copy the non-inherited values and resolve
- // the inherited ones.
- // Here we define some exception were we have to resolve some properties that are not inherited
- // by default. If those exceptions become too common on the web, it should be possible
- // to build a list of exception to resolve instead of completely disabling the cache.
-
- StyleProperties::PropertyReference current = properties.propertyAt(i);
- if (!current.isInherited()) {
- // If the property value is explicitly inherited, we need to apply further non-inherited properties
- // as they might override the value inherited here. For this reason we don't allow declarations with
- // explicitly inherited properties to be cached.
- const CSSValue& value = *current.value();
- if (value.isInheritedValue()) {
- isCacheable = false;
- break;
- }
-
- // The value currentColor has implicitely the same side effect. It depends on the value of color,
- // which is an inherited value, making the non-inherited property implicitly inherited.
- if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueCurrentcolor) {
- isCacheable = false;
- break;
- }
-
- if (value.isVariableDependentValue()) {
- isCacheable = false;
- break;
- }
- }
- }
- }
}
-StyleResolver::StyleResolver(Document& document)
+StyleResolver::StyleResolver(Document& document, bool matchAuthorAndUserStyles)
: m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
- , m_matchedPropertiesCacheSweepTimer(*this, &StyleResolver::sweepMatchedPropertiesCache)
+ , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
, m_document(document)
- , m_matchAuthorAndUserStyles(m_document.settings() ? m_document.settings()->authorAndUserStylesEnabled() : true)
+ , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
+ , m_fontSelector(CSSFontSelector::create(&m_document))
#if ENABLE(CSS_DEVICE_ADAPTATION)
, m_viewportStyleResolver(ViewportStyleResolver::create(&document))
#endif
+ , m_deprecatedStyleBuilder(DeprecatedStyleBuilder::sharedStyleBuilder())
, m_styleMap(this)
{
Element* root = m_document.documentElement();
@@ -267,35 +283,81 @@ StyleResolver::StyleResolver(Document& document)
m_medium = std::make_unique<MediaQueryEvaluator>("all");
if (root)
- m_rootDefaultStyle = styleForElement(*root, m_document.renderStyle(), MatchOnlyUserAgentRules);
+ m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
if (m_rootDefaultStyle && view)
m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType(), &view->frame(), m_rootDefaultStyle.get());
m_ruleSets.resetAuthorStyle();
- m_ruleSets.initUserStyle(m_document.extensionStyleSheets(), *m_medium, *this);
+ DocumentStyleSheetCollection& styleSheetCollection = m_document.styleSheetCollection();
+ m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this);
#if ENABLE(SVG_FONTS)
if (m_document.svgExtensions()) {
const HashSet<SVGFontFaceElement*>& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements();
- for (auto* svgFontFaceElement : svgFontFaceElements)
- m_document.fontSelector().addFontFaceRule(svgFontFaceElement->fontFaceRule(), svgFontFaceElement->isInUserAgentShadowTree());
+ HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
+ for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
+ fontSelector()->addFontFaceRule((*it)->fontFaceRule());
}
#endif
+
+ appendAuthorStyleSheets(0, styleSheetCollection.activeAuthorStyleSheets());
}
-void StyleResolver::appendAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet>>& styleSheets)
+void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet>>& styleSheets)
{
- m_ruleSets.appendAuthorStyleSheets(styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, this);
+ m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, document().isViewSource(), this);
if (auto renderView = document().renderView())
- renderView->style().fontCascade().update(&document().fontSelector());
+ renderView->style().font().update(fontSelector());
#if ENABLE(CSS_DEVICE_ADAPTATION)
viewportStyleResolver()->resolve();
#endif
}
+void StyleResolver::pushParentElement(Element* parent)
+{
+ const ContainerNode* parentsParent = parent->parentOrShadowHostElement();
+
+ // We are not always invoked consistently. For example, script execution can cause us to enter
+ // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
+ // Reset the stack in this case, or if we see a new root element.
+ // Otherwise just push the new parent.
+ if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
+ m_selectorFilter.setupParentStack(parent);
+ else
+ m_selectorFilter.pushParent(parent);
+
+ // Note: We mustn't skip ShadowRoot nodes for the scope stack.
+ if (m_scopeResolver)
+ m_scopeResolver->push(parent, parent->parentOrShadowHostNode());
+}
+
+void StyleResolver::popParentElement(Element* parent)
+{
+ // Note that we may get invoked for some random elements in some wacky cases during style resolve.
+ // Pause maintaining the stack in this case.
+ if (m_selectorFilter.parentStackIsConsistent(parent))
+ m_selectorFilter.popParent();
+ if (m_scopeResolver)
+ m_scopeResolver->pop(parent);
+}
+
+void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
+{
+ ASSERT(shadowRoot->hostElement());
+ if (m_scopeResolver)
+ m_scopeResolver->push(shadowRoot, shadowRoot->hostElement());
+}
+
+void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
+{
+ ASSERT(shadowRoot->hostElement());
+ if (m_scopeResolver)
+ m_scopeResolver->pop(shadowRoot);
+}
+
// This is a simplified style setting function for keyframe styles
void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
{
@@ -305,14 +367,14 @@ void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
StyleResolver::~StyleResolver()
{
- RELEASE_ASSERT(!m_inLoadPendingImages);
+ m_fontSelector->clearDocument();
#if ENABLE(CSS_DEVICE_ADAPTATION)
m_viewportStyleResolver->clearDocument();
#endif
}
-void StyleResolver::sweepMatchedPropertiesCache()
+void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
{
// Look for cache entries containing a style declaration with a single ref and remove them.
// This may happen when an element attribute mutation causes it to generate a new inlineStyle()
@@ -335,34 +397,396 @@ void StyleResolver::sweepMatchedPropertiesCache()
m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
}
-StyleResolver::State::State(Element& element, RenderStyle* parentStyle, const RenderRegion* regionForStyling, const SelectorFilter* selectorFilter)
- : m_element(&element)
- , m_parentStyle(parentStyle)
- , m_regionForStyling(regionForStyling)
- , m_elementLinkState(element.document().visitedLinkState().determineLinkState(element))
- , m_selectorFilter(selectorFilter)
+inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
{
- bool resetStyleInheritance = hasShadowRootParent(element) && downcast<ShadowRoot>(element.parentNode())->resetStyleInheritance();
- if (resetStyleInheritance)
- m_parentStyle = nullptr;
+#if ENABLE(SHADOW_DOM)
+ return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_state.element());
+#else
+ return false;
+#endif
+}
- auto& document = element.document();
- auto* documentElement = document.documentElement();
- m_rootElementStyle = (!documentElement || documentElement == &element) ? document.renderStyle() : documentElement->renderStyle();
+bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
+{
+ for (unsigned i = 0; i < classNames.size(); ++i) {
+ if (m_ruleSets.features().classesInRules.contains(classNames[i].impl()))
+ return true;
+ }
+ return false;
+}
- updateConversionData();
+inline void StyleResolver::State::initElement(Element* e)
+{
+ m_element = e;
+ m_styledElement = e && e->isStyledElement() ? toStyledElement(e) : nullptr;
+ m_elementLinkState = e ? e->document().visitedLinkState().determineLinkState(e) : NotInsideLink;
}
-inline void StyleResolver::State::updateConversionData()
+inline void StyleResolver::initElement(Element* e)
{
- m_cssToLengthConversionData = CSSToLengthConversionData(m_style.get(), m_rootElementStyle, m_element ? document().renderView() : nullptr);
+ if (m_state.element() != e) {
+ m_state.initElement(e);
+ if (e && e == e->document().documentElement()) {
+ e->document().setDirectionSetOnDocumentElement(false);
+ e->document().setWritingModeSetOnDocumentElement(false);
+ }
+ }
+}
+
+inline void StyleResolver::State::initForStyleResolve(Document& document, Element* e, RenderStyle* parentStyle, RenderRegion* regionForStyling)
+{
+ m_regionForStyling = regionForStyling;
+
+ if (e) {
+ m_parentNode = NodeRenderingTraversal::parent(e);
+ bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance();
+ m_parentStyle = resetStyleInheritance ? 0 :
+ parentStyle ? parentStyle :
+ m_parentNode ? m_parentNode->renderStyle() : 0;
+ } else {
+ m_parentNode = 0;
+ m_parentStyle = parentStyle;
+ }
+
+ Node* docElement = e ? e->document().documentElement() : 0;
+ RenderStyle* docStyle = document.renderStyle();
+ m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
+
+ m_style = 0;
+ m_pendingImageProperties.clear();
+ m_fontDirty = false;
}
-inline void StyleResolver::State::setStyle(Ref<RenderStyle>&& style)
+static const unsigned cStyleSearchThreshold = 10;
+static const unsigned cStyleSearchLevelThreshold = 10;
+
+static inline bool parentElementPreventsSharing(const Element* parentElement)
{
- m_style = WTFMove(style);
- updateConversionData();
+ if (!parentElement)
+ return false;
+ return parentElement->hasFlagsSetDuringStylingOfChildren();
}
+
+Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
+{
+ if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
+ return 0;
+ if (!parent || !parent->isStyledElement())
+ return 0;
+ StyledElement* p = toStyledElement(parent);
+ if (p->inlineStyle())
+ return 0;
+#if ENABLE(SVG)
+ if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties())
+ return 0;
+#endif
+ if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleResolution().impl()))
+ return 0;
+
+ RenderStyle* parentStyle = p->renderStyle();
+ unsigned subcount = 0;
+ Node* thisCousin = p;
+ Node* currentNode = p->previousSibling();
+
+ // Reserve the tries for this level. This effectively makes sure that the algorithm
+ // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
+ visitedNodeCount += cStyleSearchThreshold;
+ while (thisCousin) {
+ while (currentNode) {
+ ++subcount;
+ if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()
+ && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode))
+#if ENABLE(SHADOW_DOM)
+ && !toElement(currentNode)->authorShadowRoot()
+#endif
+ ) {
+ // Adjust for unused reserved tries.
+ visitedNodeCount -= cStyleSearchThreshold - subcount;
+ return currentNode->lastChild();
+ }
+ if (subcount >= cStyleSearchThreshold)
+ return 0;
+ currentNode = currentNode->previousSibling();
+ }
+ currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
+ thisCousin = currentNode;
+ }
+
+ return 0;
+}
+
+bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
+{
+ if (!ruleSet)
+ return false;
+
+ ElementRuleCollector collector(this, m_state);
+ return collector.hasAnyMatchingRules(ruleSet);
+}
+
+bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
+{
+ const State& state = m_state;
+ HTMLInputElement* thisInputElement = element->toInputElement();
+ HTMLInputElement* otherInputElement = state.element()->toInputElement();
+
+ if (!thisInputElement || !otherInputElement)
+ return false;
+
+ if (thisInputElement->elementData() != otherInputElement->elementData()) {
+ if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
+ return false;
+ if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
+ return false;
+ }
+
+ if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
+ return false;
+ if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
+ return false;
+ if (thisInputElement->shouldAppearIndeterminate() != otherInputElement->shouldAppearIndeterminate())
+ return false;
+ if (thisInputElement->isRequired() != otherInputElement->isRequired())
+ return false;
+
+ if (element->isDisabledFormControl() != state.element()->isDisabledFormControl())
+ return false;
+
+ if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonForForm())
+ return false;
+
+ if (state.document().containsValidityStyleRules()) {
+ bool willValidate = element->willValidate();
+
+ if (willValidate != state.element()->willValidate())
+ return false;
+
+ if (willValidate && (element->isValidFormControlElement() != state.element()->isValidFormControlElement()))
+ return false;
+
+ if (element->isInRange() != state.element()->isInRange())
+ return false;
+
+ if (element->isOutOfRange() != state.element()->isOutOfRange())
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool elementHasDirectionAuto(Element* element)
+{
+ // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
+ return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
+}
+
+bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement* sharingCandidate) const
+{
+ const State& state = m_state;
+ if (state.element()->elementData() == sharingCandidate->elementData())
+ return true;
+ if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate->fastGetAttribute(XMLNames::langAttr))
+ return false;
+ if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGetAttribute(langAttr))
+ return false;
+
+ if (!state.elementAffectedByClassRules()) {
+ if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCandidate->classNames()))
+ return false;
+ } else if (sharingCandidate->hasClass()) {
+#if ENABLE(SVG)
+ // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
+ if (state.element()->isSVGElement()) {
+ if (state.element()->getAttribute(classAttr) != sharingCandidate->getAttribute(classAttr))
+ return false;
+ } else {
+#endif
+ if (state.element()->classNames() != sharingCandidate->classNames())
+ return false;
+#if ENABLE(SVG)
+ }
+#endif
+ } else
+ return false;
+
+ if (state.styledElement()->presentationAttributeStyle() != sharingCandidate->presentationAttributeStyle())
+ return false;
+
+#if ENABLE(PROGRESS_ELEMENT)
+ if (state.element()->hasTagName(progressTag)) {
+ if (state.element()->shouldAppearIndeterminate() != sharingCandidate->shouldAppearIndeterminate())
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
+{
+ RenderStyle* style = element->renderStyle();
+ const State& state = m_state;
+
+ if (!style)
+ return false;
+ if (style->unique())
+ return false;
+ if (style->hasUniquePseudoStyle())
+ return false;
+ if (element->tagQName() != state.element()->tagQName())
+ return false;
+ if (element->inlineStyle())
+ return false;
+ if (element->needsStyleRecalc())
+ return false;
+#if ENABLE(SVG)
+ if (element->isSVGElement() && toSVGElement(element)->animatedSMILStyleProperties())
+ return false;
+#endif
+ if (element->isLink() != state.element()->isLink())
+ return false;
+ if (element->hovered() != state.element()->hovered())
+ return false;
+ if (element->active() != state.element()->active())
+ return false;
+ if (element->focused() != state.element()->focused())
+ return false;
+ if (element->shadowPseudoId() != state.element()->shadowPseudoId())
+ return false;
+ if (element == element->document().cssTarget())
+ return false;
+ if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element))
+ return false;
+ if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle())
+ return false;
+
+ if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl()))
+ return false;
+
+ // FIXME: We should share style for option and optgroup whenever possible.
+ // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
+ // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
+ if (isHTMLOptionElement(element) || isHTMLOptGroupElement(element))
+ return false;
+
+ bool isControl = element->isFormControlElement();
+
+ if (isControl != state.element()->isFormControlElement())
+ return false;
+
+ if (isControl && !canShareStyleWithControl(element))
+ return false;
+
+ if (style->transitions() || style->animations())
+ return false;
+
+#if USE(ACCELERATED_COMPOSITING)
+ // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
+ // See comments in RenderObject::setStyle().
+ if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag))
+ return false;
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ // With proxying, the media elements are backed by a RenderEmbeddedObject.
+ if ((element->hasTagName(videoTag) || element->hasTagName(audioTag)) && toHTMLMediaElement(element)->shouldUseVideoPluginProxy())
+ return false;
+#endif
+
+#endif
+
+ if (elementHasDirectionAuto(element))
+ return false;
+
+ if (element->isLink() && state.elementLinkState() != style->insideLink())
+ return false;
+
+#if ENABLE(VIDEO_TRACK)
+ // Deny sharing styles between WebVTT and non-WebVTT nodes.
+ if (element->isWebVTTElement() != state.element()->isWebVTTElement())
+ return false;
+
+ if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWebVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNode())
+ return false;
+#endif
+
+#if ENABLE(FULLSCREEN_API)
+ if (element == element->document().webkitCurrentFullScreenElement() || state.element() == state.document().webkitCurrentFullScreenElement())
+ return false;
+#endif
+ return true;
+}
+
+inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
+{
+ for (; node; node = node->previousSibling()) {
+ if (!node->isStyledElement())
+ continue;
+ if (canShareStyleWithElement(toStyledElement(node)))
+ break;
+ if (count++ == cStyleSearchThreshold)
+ return 0;
+ }
+ return toStyledElement(node);
+}
+
+RenderStyle* StyleResolver::locateSharedStyle()
+{
+ State& state = m_state;
+ if (!state.styledElement() || !state.parentStyle())
+ return 0;
+
+ // If the element has inline style it is probably unique.
+ if (state.styledElement()->inlineStyle())
+ return 0;
+#if ENABLE(SVG)
+ if (state.styledElement()->isSVGElement() && toSVGElement(state.styledElement())->animatedSMILStyleProperties())
+ return 0;
+#endif
+ // Ids stop style sharing if they show up in the stylesheets.
+ if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl()))
+ return 0;
+ if (parentElementPreventsSharing(state.element()->parentElement()))
+ return 0;
+ if (state.element() == state.document().cssTarget())
+ return 0;
+ if (elementHasDirectionAuto(state.element()))
+ return 0;
+
+ // Cache whether state.element is affected by any known class selectors.
+ // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
+ state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames()));
+
+ // Check previous siblings and their cousins.
+ unsigned count = 0;
+ unsigned visitedNodeCount = 0;
+ StyledElement* shareElement = 0;
+ Node* cousinList = state.styledElement()->previousSibling();
+ while (cousinList) {
+ shareElement = findSiblingForStyleSharing(cousinList, count);
+ if (shareElement)
+ break;
+ cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
+ }
+
+ // If we have exhausted all our budget or our cousins.
+ if (!shareElement)
+ return 0;
+
+ // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
+ if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling()))
+ return 0;
+ // Can't share if attribute rules apply.
+ if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute()))
+ return 0;
+ // Can't share if @host @-rules apply.
+ if (styleSharingCandidateMatchesHostRules())
+ return 0;
+ // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
+ if (parentElementPreventsSharing(state.element()->parentElement()))
+ return 0;
+ return shareElement->renderStyle();
+}
+
static inline bool isAtShadowBoundary(const Element* element)
{
if (!element)
@@ -371,35 +795,56 @@ static inline bool isAtShadowBoundary(const Element* element)
return parentNode && parentNode->isShadowRoot();
}
-Ref<RenderStyle> StyleResolver::styleForElement(Element& element, RenderStyle* parentStyle, RuleMatchingBehavior matchingBehavior, const RenderRegion* regionForStyling, const SelectorFilter* selectorFilter)
+PassRef<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
+ StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
{
- RELEASE_ASSERT(!m_inLoadPendingImages);
+ // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
+ // will vanish if a style recalc happens during loading.
+ if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) {
+ if (!s_styleNotYetAvailable) {
+ s_styleNotYetAvailable = &RenderStyle::create().leakRef();
+ s_styleNotYetAvailable->setDisplay(NONE);
+ s_styleNotYetAvailable->font().update(m_fontSelector);
+ }
+ element->document().setHasNodesWithPlaceholderStyle();
+ return *s_styleNotYetAvailable;
+ }
- m_state = State(element, parentStyle, regionForStyling, selectorFilter);
State& state = m_state;
+ initElement(element);
+ state.initForStyleResolve(document(), element, defaultParent, regionForStyling);
+ if (sharingBehavior == AllowStyleSharing) {
+ if (RenderStyle* sharedStyle = locateSharedStyle()) {
+ state.clear();
+ return *sharedStyle;
+ }
+ }
if (state.parentStyle()) {
state.setStyle(RenderStyle::create());
- state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(&element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
+ state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
} else {
state.setStyle(defaultStyleForElement());
state.setParentStyle(RenderStyle::clone(state.style()));
}
- if (element.isLink()) {
+ if (element->isLink()) {
state.style()->setIsLink(true);
EInsideLink linkState = state.elementLinkState();
if (linkState != NotInsideLink) {
- bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoClassVisited);
+ bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
if (forceVisited)
linkState = InsideVisitedLink;
}
state.style()->setInsideLink(linkState);
}
- CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element);
+ bool needsCollection = false;
+ CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection);
+ if (needsCollection)
+ m_ruleSets.collectFeatures(document().isViewSource(), m_scopeResolver.get());
- ElementRuleCollector collector(element, state.style(), m_ruleSets, m_state.selectorFilter());
+ ElementRuleCollector collector(this, state);
collector.setRegionForStyling(regionForStyling);
collector.setMedium(m_medium.get());
@@ -411,21 +856,18 @@ Ref<RenderStyle> StyleResolver::styleForElement(Element& element, RenderStyle* p
applyMatchedProperties(collector.matchedResult(), element);
// Clean up our style object's display and text decorations (among other fixups).
- adjustRenderStyle(*state.style(), *state.parentStyle(), &element);
-
- if (state.style()->hasViewportUnits())
- document().setHasStyleWithViewportUnits();
+ adjustRenderStyle(*state.style(), *state.parentStyle(), element);
state.clear(); // Clear out for the next resolve.
+ document().didAccessStyleResolver();
+
// Now return the style.
return state.takeStyle();
}
-Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
+PassRef<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
{
- RELEASE_ASSERT(!m_inLoadPendingImages);
-
MatchResult result;
result.addMatchedProperties(keyframe->properties());
@@ -435,7 +877,7 @@ Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle
// Create the style
state.setStyle(RenderStyle::clone(elementStyle));
- state.setParentStyle(RenderStyle::clone(elementStyle));
+ state.setLineHeightValue(0);
TextDirection direction;
WritingMode writingMode;
@@ -444,25 +886,25 @@ Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle
// We don't need to bother with !important. Since there is only ever one
// decl, there's nothing to override. So just add the first properties.
CascadedProperties cascade(direction, writingMode);
- cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
-
- // Resolve custom properties first.
- applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
+ cascade.addMatches(result, false, 0, result.matchedProperties.size() - 1);
- applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
+ applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight);
- // If our font got dirtied, update it now.
+ // If our font got dirtied, go ahead and update it now.
updateFont();
+ // Line-height is set when we are sure we decided on the font-size
+ if (state.lineHeightValue())
+ applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
+
// Now do rest of the properties.
- applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
+ applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty);
- // If our font got dirtied by one of the non-essential font props, update it a second time.
+ // If our font got dirtied by one of the non-essential font props,
+ // go ahead and update it a second time.
updateFont();
- cascade.applyDeferredProperties(*this, &result);
-
- adjustRenderStyle(*state.style(), *state.parentStyle(), nullptr);
+ cascade.applyDeferredProperties(*this);
// Start loading resources referenced by this style.
loadPendingResources();
@@ -473,19 +915,21 @@ Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle
CSSPropertyID property = keyframe->properties().propertyAt(i).id();
// Timing-function within keyframes is special, because it is not animated; it just
// describes the timing function between this keyframe and the next.
- if (property != CSSPropertyWebkitAnimationTimingFunction && property != CSSPropertyAnimationTimingFunction)
+ if (property != CSSPropertyWebkitAnimationTimingFunction)
keyframeValue.addProperty(property);
}
+ document().didAccessStyleResolver();
+
return state.takeStyle();
}
-void StyleResolver::keyframeStylesForAnimation(Element& element, const RenderStyle* elementStyle, KeyframeList& list)
+void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
{
list.clear();
// Get the keyframesRule for this name
- if (list.animationName().isEmpty())
+ if (!e || list.animationName().isEmpty())
return;
m_keyframesRuleMap.checkConsistency();
@@ -500,16 +944,19 @@ void StyleResolver::keyframeStylesForAnimation(Element& element, const RenderSty
const Vector<RefPtr<StyleKeyframe>>& keyframes = keyframesRule->keyframes();
for (unsigned i = 0; i < keyframes.size(); ++i) {
// Apply the declaration to the style. This is a simplified version of the logic in styleForElement
- m_state = State(element, nullptr);
+ initElement(e);
+ m_state.initForStyleResolve(document(), e);
const StyleKeyframe* keyframe = keyframes[i].get();
- KeyframeValue keyframeValue(0, nullptr);
+ KeyframeValue keyframeValue(0, 0);
keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
// Add this keyframe style to all the indicated key times
- for (auto& key: keyframe->keys()) {
- keyframeValue.setKey(key);
+ Vector<double> keys;
+ keyframe->getKeys(keys);
+ for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
+ keyframeValue.setKey(keys[keyIndex]);
list.insert(keyframeValue);
}
}
@@ -519,10 +966,10 @@ void StyleResolver::keyframeStylesForAnimation(Element& element, const RenderSty
if (initialListSize > 0 && list[0].key()) {
static StyleKeyframe* zeroPercentKeyframe;
if (!zeroPercentKeyframe) {
- zeroPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
+ zeroPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
zeroPercentKeyframe->setKeyText("0%");
}
- KeyframeValue keyframeValue(0, nullptr);
+ KeyframeValue keyframeValue(0, 0);
keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
list.insert(keyframeValue);
}
@@ -531,21 +978,27 @@ void StyleResolver::keyframeStylesForAnimation(Element& element, const RenderSty
if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
static StyleKeyframe* hundredPercentKeyframe;
if (!hundredPercentKeyframe) {
- hundredPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
+ hundredPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
hundredPercentKeyframe->setKeyText("100%");
}
- KeyframeValue keyframeValue(1, nullptr);
+ KeyframeValue keyframeValue(1, 0);
keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
list.insert(keyframeValue);
}
}
-PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle& parentStyle)
+PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
{
- m_state = State(element, &parentStyle);
+ ASSERT(parentStyle);
+ if (!e)
+ return 0;
State& state = m_state;
+ initElement(e);
+
+ state.initForStyleResolve(document(), e, parentStyle);
+
if (m_state.parentStyle()) {
state.setStyle(RenderStyle::create());
state.style()->inheritFrom(m_state.parentStyle());
@@ -558,7 +1011,7 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element& element, c
// those rules.
// Check UA, user and author rules.
- ElementRuleCollector collector(element, m_state.style(), m_ruleSets, m_state.selectorFilter());
+ ElementRuleCollector collector(this, state);
collector.setPseudoStyleRequest(pseudoStyleRequest);
collector.setMedium(m_medium.get());
collector.matchUARules();
@@ -568,41 +1021,35 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element& element, c
collector.matchAuthorRules(false);
}
- if (collector.matchedResult().matchedProperties().isEmpty())
- return nullptr;
+ if (collector.matchedResult().matchedProperties.isEmpty())
+ return 0;
state.style()->setStyleType(pseudoStyleRequest.pseudoId);
- applyMatchedProperties(collector.matchedResult(), element);
+ applyMatchedProperties(collector.matchedResult(), e);
// Clean up our style object's display and text decorations (among other fixups).
- adjustRenderStyle(*state.style(), *m_state.parentStyle(), nullptr);
-
- if (state.style()->hasViewportUnits())
- document().setHasStyleWithViewportUnits();
+ adjustRenderStyle(*state.style(), *m_state.parentStyle(), 0);
// Start loading resources referenced by this style.
loadPendingResources();
+ document().didAccessStyleResolver();
+
// Now return the style.
return state.takeStyle();
}
-Ref<RenderStyle> StyleResolver::styleForPage(int pageIndex)
+PassRef<RenderStyle> StyleResolver::styleForPage(int pageIndex)
{
- RELEASE_ASSERT(!m_inLoadPendingImages);
-
- auto* documentElement = m_document.documentElement();
- if (!documentElement)
- return RenderStyle::create();
-
- m_state = State(*documentElement, m_document.renderStyle());
+ m_state.initForStyleResolve(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
m_state.setStyle(RenderStyle::create());
m_state.style()->inheritFrom(m_state.rootElementStyle());
PageRuleCollector collector(m_state, m_ruleSets);
collector.matchAllPageRules(pageIndex);
+ m_state.setLineHeightValue(0);
MatchResult& result = collector.matchedResult();
@@ -611,36 +1058,39 @@ Ref<RenderStyle> StyleResolver::styleForPage(int pageIndex)
extractDirectionAndWritingMode(*m_state.style(), result, direction, writingMode);
CascadedProperties cascade(direction, writingMode);
- cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
-
- // Resolve custom properties first.
- applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
+ cascade.addMatches(result, false, 0, result.matchedProperties.size() - 1);
- applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
+ applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight);
- // If our font got dirtied, update it now.
+ // If our font got dirtied, go ahead and update it now.
updateFont();
- applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
+ // Line-height is set when we are sure we decided on the font-size.
+ if (m_state.lineHeightValue())
+ applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue());
+
+ applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty);
- cascade.applyDeferredProperties(*this, &result);
+ cascade.applyDeferredProperties(*this);
// Start loading resources referenced by this style.
loadPendingResources();
+ document().didAccessStyleResolver();
+
// Now return the style.
return m_state.takeStyle();
}
-Ref<RenderStyle> StyleResolver::defaultStyleForElement()
+PassRef<RenderStyle> StyleResolver::defaultStyleForElement()
{
m_state.setStyle(RenderStyle::create());
// Make sure our fonts are initialized if we don't inherit them from our parent style.
- initializeFontStyle(documentSettings());
- if (documentSettings())
- m_state.style()->fontCascade().update(&document().fontSelector());
- else
- m_state.style()->fontCascade().update(nullptr);
+ if (Settings* settings = documentSettings()) {
+ initializeFontStyle(settings);
+ m_state.style()->font().update(fontSelector());
+ } else
+ m_state.style()->font().update(0);
return m_state.takeStyle();
}
@@ -651,18 +1101,18 @@ static void addIntrinsicMargins(RenderStyle& style)
const int intrinsicMargin = 2 * style.effectiveZoom();
// FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
- // FIXME: Using "hasQuirk" to decide the margin wasn't set is kind of lame.
+ // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
if (style.width().isIntrinsicOrAuto()) {
- if (style.marginLeft().hasQuirk())
+ if (style.marginLeft().quirk())
style.setMarginLeft(Length(intrinsicMargin, Fixed));
- if (style.marginRight().hasQuirk())
+ if (style.marginRight().quirk())
style.setMarginRight(Length(intrinsicMargin, Fixed));
}
if (style.height().isAuto()) {
- if (style.marginTop().hasQuirk())
+ if (style.marginTop().quirk())
style.setMarginTop(Length(intrinsicMargin, Fixed));
- if (style.marginBottom().hasQuirk())
+ if (style.marginBottom().quirk())
style.setMarginBottom(Length(intrinsicMargin, Fixed));
}
}
@@ -674,10 +1124,7 @@ static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool s
case TABLE:
case BOX:
case FLEX:
- case WEBKIT_FLEX:
-#if ENABLE(CSS_GRID_LAYOUT)
case GRID:
-#endif
return display;
case LIST_ITEM:
@@ -690,14 +1137,12 @@ static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool s
case INLINE_BOX:
return BOX;
case INLINE_FLEX:
- case WEBKIT_INLINE_FLEX:
return FLEX;
-#if ENABLE(CSS_GRID_LAYOUT)
case INLINE_GRID:
return GRID;
-#endif
case INLINE:
+ case RUN_IN:
case COMPACT:
case INLINE_BLOCK:
case TABLE_ROW_GROUP:
@@ -718,15 +1163,20 @@ static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool s
}
// CSS requires text-decoration to be reset at each DOM element for tables,
-// inline blocks, inline tables, shadow DOM crossings, floating elements,
+// inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
// and absolute or relatively positioned elements.
static bool doesNotInheritTextDecoration(const RenderStyle& style, Element* e)
{
- return style.display() == TABLE || style.display() == INLINE_TABLE
+ return style.display() == TABLE || style.display() == INLINE_TABLE || style.display() == RUN_IN
|| style.display() == INLINE_BLOCK || style.display() == INLINE_BOX || isAtShadowBoundary(e)
|| style.isFloating() || style.hasOutOfFlowPosition();
}
+static bool isDisplayFlexibleBox(EDisplay display)
+{
+ return display == FLEX || display == INLINE_FLEX;
+}
+
#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
static bool isScrollableOverflow(EOverflow overflow)
{
@@ -734,16 +1184,6 @@ static bool isScrollableOverflow(EOverflow overflow)
}
#endif
-void StyleResolver::adjustStyleForInterCharacterRuby()
-{
- RenderStyle* style = m_state.style();
- if (style->rubyPosition() != RubyPositionInterCharacter || !m_state.element() || !m_state.element()->hasTagName(rtTag))
- return;
- style->setTextAlign(CENTER);
- if (style->isHorizontalWritingMode())
- style->setWritingMode(LeftToRightWritingMode);
-}
-
void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& parentStyle, Element *e)
{
// Cache our original display.
@@ -758,7 +1198,7 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
if (e->hasTagName(tdTag)) {
style.setDisplay(TABLE_CELL);
style.setFloating(NoFloat);
- } else if (is<HTMLTableElement>(*e))
+ } else if (isHTMLTableElement(e))
style.setDisplay(style.isDisplayInlineType() ? INLINE_TABLE : TABLE);
}
@@ -775,7 +1215,7 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
}
// Tables never support the -webkit-* values for text-align and will reset back to the default.
- if (is<HTMLTableElement>(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT))
+ if (e && isHTMLTableElement(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT))
style.setTextAlign(TASTART);
// Frames and framesets never honor position:relative or position:absolute. This is necessary to
@@ -829,14 +1269,14 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
if (style.writingMode() != TopToBottomWritingMode && (style.display() == BOX || style.display() == INLINE_BOX))
style.setWritingMode(TopToBottomWritingMode);
- if (parentStyle.isDisplayFlexibleOrGridBox()) {
+ if (isDisplayFlexibleBox(parentStyle.display())) {
style.setFloating(NoFloat);
style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
}
}
// Make sure our z-index value is only applied if the object is positioned.
- if (style.position() == StaticPosition && !parentStyle.isDisplayFlexibleOrGridBox())
+ if (style.position() == StaticPosition && !isDisplayFlexibleBox(parentStyle.display()))
style.setHasAutoZIndex();
// Auto z-index becomes 0 for the root element and transparent objects. This prevents
@@ -849,28 +1289,19 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
|| style.clipPath()
|| style.boxReflect()
|| style.hasFilter()
-#if ENABLE(FILTERS_LEVEL_2)
- || style.hasBackdropFilter()
-#endif
|| style.hasBlendMode()
- || style.hasIsolation()
|| style.position() == StickyPosition
- || (style.position() == FixedPosition && documentSettings() && documentSettings()->fixedPositionCreatesStackingContext())
+ || (style.position() == FixedPosition && e && e->document().page() && e->document().page()->settings().fixedPositionCreatesStackingContext())
|| style.hasFlowFrom()
- || style.willChangeCreatesStackingContext()
))
style.setZIndex(0);
// Textarea considers overflow visible as auto.
- if (is<HTMLTextAreaElement>(e)) {
+ if (e && isHTMLTextAreaElement(e)) {
style.setOverflowX(style.overflowX() == OVISIBLE ? OAUTO : style.overflowX());
style.setOverflowY(style.overflowY() == OVISIBLE ? OAUTO : style.overflowY());
}
- // Disallow -webkit-user-modify on :pseudo and ::pseudo elements.
- if (e && !e->shadowPseudoId().isNull())
- style.setUserModify(READ_ONLY);
-
if (doesNotInheritTextDecoration(style, e))
style.setTextDecorationsInEffect(style.textDecoration());
else
@@ -927,10 +1358,10 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
// Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
// alter fonts and heights/widths.
- if (is<HTMLFormControlElement>(e) && style.fontSize() >= 11) {
+ if (e && e->isFormControlElement() && style.fontSize() >= 11) {
// Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
// so we have to treat all image buttons as though they were explicitly sized.
- if (!is<HTMLInputElement>(*e) || !downcast<HTMLInputElement>(*e).isImageButton())
+ if (!isHTMLInputElement(e) || !toHTMLInputElement(e)->isImageButton())
addIntrinsicMargins(style);
}
@@ -945,14 +1376,28 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
// FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
if (style.preserves3D() && (style.overflowX() != OVISIBLE
|| style.overflowY() != OVISIBLE
- || style.hasFilter()
-#if ENABLE(FILTERS_LEVEL_2)
- || style.hasBackdropFilter()
-#endif
- || style.hasBlendMode()))
+ || style.hasFilter()))
style.setTransformStyle3D(TransformStyle3DFlat);
+ // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
+ if (e && e->hasTagName(iframeTag) && style.display() == INLINE && toHTMLIFrameElement(e)->shouldDisplaySeamlessly())
+ style.setDisplay(INLINE_BLOCK);
+
+ adjustGridItemPosition(style, parentStyle);
+
+#if ENABLE(SVG)
if (e && e->isSVGElement()) {
+ // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
+ if (style.overflowY() == OSCROLL)
+ style.setOverflowY(OHIDDEN);
+ else if (style.overflowY() == OAUTO)
+ style.setOverflowY(OVISIBLE);
+
+ if (style.overflowX() == OSCROLL)
+ style.setOverflowX(OHIDDEN);
+ else if (style.overflowX() == OAUTO)
+ style.setOverflowX(OVISIBLE);
+
// Only the root <svg> element in an SVG document fragment tree honors css position
if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
style.setPosition(RenderStyle::initialPosition());
@@ -966,15 +1411,45 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
if ((e->hasTagName(SVGNames::foreignObjectTag) || e->hasTagName(SVGNames::textTag)) && style.isDisplayInlineType())
style.setDisplay(BLOCK);
}
+#endif
+}
+
+void StyleResolver::adjustGridItemPosition(RenderStyle& style, const RenderStyle& parentStyle) const
+{
+ const GridPosition& columnStartPosition = style.gridItemColumnStart();
+ const GridPosition& columnEndPosition = style.gridItemColumnEnd();
+ const GridPosition& rowStartPosition = style.gridItemRowStart();
+ const GridPosition& rowEndPosition = style.gridItemRowEnd();
+
+ // If opposing grid-placement properties both specify a grid span, they both compute to ‘auto’.
+ if (columnStartPosition.isSpan() && columnEndPosition.isSpan()) {
+ style.setGridItemColumnStart(GridPosition());
+ style.setGridItemColumnEnd(GridPosition());
+ }
+
+ if (rowStartPosition.isSpan() && rowEndPosition.isSpan()) {
+ style.setGridItemRowStart(GridPosition());
+ style.setGridItemRowEnd(GridPosition());
+ }
+
+ // Unknown named grid area compute to 'auto'.
+ const NamedGridAreaMap& map = parentStyle.namedGridArea();
+
+#define CLEAR_UNKNOWN_NAMED_AREA(prop, Prop) \
+ if (prop.isNamedGridArea() && !map.contains(prop.namedGridLine())) \
+ style.setGridItem##Prop(GridPosition());
- // If the inherited value of justify-items includes the legacy keyword, 'auto'
- // computes to the the inherited value.
- if (parentStyle.justifyItemsPositionType() == LegacyPosition && style.justifyItemsPosition() == ItemPositionAuto)
- style.setJustifyItems(parentStyle.justifyItems());
+ CLEAR_UNKNOWN_NAMED_AREA(columnStartPosition, ColumnStart);
+ CLEAR_UNKNOWN_NAMED_AREA(columnEndPosition, ColumnEnd);
+ CLEAR_UNKNOWN_NAMED_AREA(rowStartPosition, RowStart);
+ CLEAR_UNKNOWN_NAMED_AREA(rowEndPosition, RowEnd);
}
bool StyleResolver::checkRegionStyle(Element* regionElement)
{
+ // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
+ // so all region rules are global by default. Verify whether that can stand or needs changing.
+
unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size();
for (unsigned i = 0; i < rulesSize; ++i) {
ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
@@ -998,13 +1473,13 @@ static void checkForOrientationChange(RenderStyle* style)
{
FontOrientation fontOrientation;
NonCJKGlyphOrientation glyphOrientation;
- std::tie(fontOrientation, glyphOrientation) = style->fontAndGlyphOrientation();
+ style->getFontAndGlyphOrientation(fontOrientation, glyphOrientation);
- const auto& fontDescription = style->fontDescription();
+ const FontDescription& fontDescription = style->fontDescription();
if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
return;
- auto newFontDescription = fontDescription;
+ FontDescription newFontDescription(fontDescription);
newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
newFontDescription.setOrientation(fontOrientation);
style->setFontDescription(newFontDescription);
@@ -1022,26 +1497,25 @@ void StyleResolver::updateFont()
checkForGenericFamilyChange(style, m_state.parentStyle());
checkForZoomChange(style, m_state.parentStyle());
checkForOrientationChange(style);
- style->fontCascade().update(&document().fontSelector());
- if (m_state.fontSizeHasViewportUnits())
- style->setHasViewportUnits(true);
+ style->font().update(m_fontSelector);
m_state.setFontDirty(false);
}
-Vector<RefPtr<StyleRule>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
+Vector<RefPtr<StyleRuleBase>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
{
return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
}
-Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
+Vector<RefPtr<StyleRuleBase>> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
{
- if (!element || !element->document().haveStylesheetsLoaded())
- return Vector<RefPtr<StyleRule>>();
+ if (!e || !e->document().haveStylesheetsLoaded())
+ return Vector<RefPtr<StyleRuleBase>>();
- m_state = State(*element, nullptr);
+ initElement(e);
+ m_state.initForStyleResolve(document(), e, 0);
- ElementRuleCollector collector(*element, nullptr, m_ruleSets, m_state.selectorFilter());
- collector.setMode(SelectorChecker::Mode::CollectingRules);
+ ElementRuleCollector collector(this, m_state);
+ collector.setMode(SelectorChecker::CollectingRules);
collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
collector.setMedium(m_medium.get());
@@ -1064,15 +1538,22 @@ Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(Element* ele
return collector.matchedRuleList();
}
+// -------------------------------------------------------------------------------------
+// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
+
+Length StyleResolver::convertToIntLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
+{
+ return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
+}
+
+Length StyleResolver::convertToFloatLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
+{
+ return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
+}
+
static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
{
switch (propertyID) {
- case CSSPropertyWebkitBackgroundClip:
- case CSSPropertyBackgroundClip:
- case CSSPropertyWebkitBackgroundOrigin:
- case CSSPropertyBackgroundOrigin:
- case CSSPropertyWebkitBackgroundSize:
- case CSSPropertyBackgroundSize:
case CSSPropertyWebkitBorderImage:
case CSSPropertyBorderImage:
case CSSPropertyBorderImageSlice:
@@ -1080,8 +1561,6 @@ static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
case CSSPropertyBorderImageOutset:
case CSSPropertyBorderImageRepeat:
case CSSPropertyBorderImageWidth:
- case CSSPropertyWebkitBoxShadow:
- case CSSPropertyBoxShadow:
case CSSPropertyWebkitTextDecoration:
case CSSPropertyWebkitTextDecorationLine:
case CSSPropertyWebkitTextDecorationStyle:
@@ -1144,18 +1623,18 @@ const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedP
MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
if (it == m_matchedPropertiesCache.end())
- return nullptr;
+ return 0;
MatchedPropertiesCacheItem& cacheItem = it->value;
- size_t size = matchResult.matchedProperties().size();
+ size_t size = matchResult.matchedProperties.size();
if (size != cacheItem.matchedProperties.size())
- return nullptr;
+ return 0;
for (size_t i = 0; i < size; ++i) {
- if (matchResult.matchedProperties()[i] != cacheItem.matchedProperties[i])
- return nullptr;
+ if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
+ return 0;
}
if (cacheItem.ranges != matchResult.ranges)
- return nullptr;
+ return 0;
return &cacheItem;
}
@@ -1170,13 +1649,13 @@ void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const
ASSERT(hash);
MatchedPropertiesCacheItem cacheItem;
- cacheItem.matchedProperties.appendVector(matchResult.matchedProperties());
+ cacheItem.matchedProperties.appendVector(matchResult.matchedProperties);
cacheItem.ranges = matchResult.ranges;
// Note that we don't cache the original RenderStyle instance. It may be further modified.
// The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
cacheItem.renderStyle = RenderStyle::clone(style);
cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
- m_matchedPropertiesCache.add(hash, WTFMove(cacheItem));
+ m_matchedPropertiesCache.add(hash, std::move(cacheItem));
}
void StyleResolver::invalidateMatchedPropertiesCache()
@@ -1184,22 +1663,10 @@ void StyleResolver::invalidateMatchedPropertiesCache()
m_matchedPropertiesCache.clear();
}
-void StyleResolver::clearCachedPropertiesAffectedByViewportUnits()
+static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
{
- Vector<unsigned, 16> toRemove;
- for (auto& cacheKeyValue : m_matchedPropertiesCache) {
- if (cacheKeyValue.value.renderStyle->hasViewportUnits())
- toRemove.append(cacheKeyValue.key);
- }
- for (auto key : toRemove)
- m_matchedPropertiesCache.remove(key);
-}
-
-static bool isCacheableInMatchedPropertiesCache(const Element& element, const RenderStyle* style, const RenderStyle* parentStyle)
-{
- // FIXME: Writing mode and direction properties modify state when applying to document element by calling
- // Document::setWritingMode/DirectionSetOnDocumentElement. We can't skip the applying by caching.
- if (&element == element.document().documentElement())
+ // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
+ if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement())
return false;
if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
return false;
@@ -1207,7 +1674,7 @@ static bool isCacheableInMatchedPropertiesCache(const Element& element, const Re
return false;
if (style->zoom() != RenderStyle::initialZoom())
return false;
- if (style->writingMode() != RenderStyle::initialWritingMode() || style->direction() != RenderStyle::initialDirection())
+ if (style->writingMode() != RenderStyle::initialWritingMode())
return false;
// The cache assumes static knowledge about which properties are inherited.
if (parentStyle->hasExplicitlyInheritedProperties())
@@ -1223,7 +1690,7 @@ void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolve
bool hadImportantWebkitWritingMode = false;
bool hadImportantDirection = false;
- for (const auto& matchedProperties : matchResult.matchedProperties()) {
+ for (auto& matchedProperties : matchResult.matchedProperties) {
for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) {
auto property = matchedProperties.properties->propertyAt(i);
if (!property.value()->isPrimitiveValue())
@@ -1231,13 +1698,13 @@ void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolve
switch (property.id()) {
case CSSPropertyWebkitWritingMode:
if (!hadImportantWebkitWritingMode || property.isImportant()) {
- writingMode = downcast<CSSPrimitiveValue>(*property.value());
+ writingMode = toCSSPrimitiveValue(*property.value());
hadImportantWebkitWritingMode = property.isImportant();
}
break;
case CSSPropertyDirection:
if (!hadImportantDirection || property.isImportant()) {
- direction = downcast<CSSPrimitiveValue>(*property.value());
+ direction = toCSSPrimitiveValue(*property.value());
hadImportantDirection = property.isImportant();
}
break;
@@ -1248,19 +1715,19 @@ void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolve
}
}
-void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element& element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache)
+void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache)
{
+ ASSERT(element);
State& state = m_state;
- unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties().data(), matchResult.matchedProperties().size()) : 0;
+ unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
bool applyInheritedOnly = false;
- const MatchedPropertiesCacheItem* cacheItem = nullptr;
- if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))
- && isCacheableInMatchedPropertiesCache(element, state.style(), state.parentStyle())) {
+ const MatchedPropertiesCacheItem* cacheItem = 0;
+ if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
// We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
// style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
// element context. This is fast and saves memory by reusing the style data structures.
state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
- if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(&element)) {
+ if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
EInsideLink linkStatus = state.style()->insideLink();
// If the cache item parent style has identical inherited properties to the current parent style then the
// resulting style will be identical too. We copy the inherited properties over from the cache and are done.
@@ -1284,60 +1751,53 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
// Find out if there's a -webkit-appearance property in effect from the UA sheet.
// If so, we cache the border and background styles so that RenderTheme::adjustStyle()
// can look at them later to figure out if this is a styled form control or not.
+ state.setLineHeightValue(nullptr);
CascadedProperties cascade(direction, writingMode);
- cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
- cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
+ if (!cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly)
+ || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly))
+ return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
- applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
- adjustStyleForInterCharacterRuby();
-
- // Resolve custom variables first.
- applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
-
- // Start by applying properties that other properties may depend on.
- applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
-
+ applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight);
updateFont();
- applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
+ applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty);
state.cacheBorderAndBackground();
}
CascadedProperties cascade(direction, writingMode);
- cascade.addMatches(matchResult, false, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly);
- cascade.addMatches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
- cascade.addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
- cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
-
- // Resolve custom properties first.
- applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
+ if (!cascade.addMatches(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly)
+ || !cascade.addMatches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly)
+ || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly)
+ || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly))
+ return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
- applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
-
- // Adjust the font size to be smaller if ruby-position is inter-character.
- adjustStyleForInterCharacterRuby();
+ state.setLineHeightValue(nullptr);
// Start by applying properties that other properties may depend on.
- applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
+ applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight);
// If the effective zoom value changes, we can't use the matched properties cache. Start over.
if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom())
return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
- // If our font got dirtied, update it now.
+ // If our font got dirtied, go ahead and update it now.
updateFont();
+ // Line-height is set when we are sure we decided on the font-size.
+ if (state.lineHeightValue())
+ applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
+
// If the font changed, we can't use the matched properties cache. Start over.
if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
// Apply properties that no other properties depend on.
- applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
+ applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty);
// Finally, some properties must be applied in the order they were parsed.
// There are some CSS properties that affect the same RenderStyle values,
// so to preserve behavior, we queue them up during cascade and flush here.
- cascade.applyDeferredProperties(*this, &matchResult);
+ cascade.applyDeferredProperties(*this);
// Start loading resources referenced by this style.
loadPendingResources();
@@ -1346,15 +1806,15 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
if (cacheItem || !cacheHash)
return;
- if (!isCacheableInMatchedPropertiesCache(*state.element(), state.style(), state.parentStyle()))
+ if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
return;
addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
}
void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
{
- m_state = State();
- m_state.setParentStyle(*style);
+ initElement(0);
+ m_state.initForStyleResolve(document(), 0, style);
m_state.setStyle(*style);
applyPropertyToCurrentStyle(id, value);
}
@@ -1375,13 +1835,15 @@ inline bool isValidVisitedLinkProperty(CSSPropertyID id)
case CSSPropertyBorderBottomColor:
case CSSPropertyColor:
case CSSPropertyOutlineColor:
- case CSSPropertyColumnRuleColor:
+ case CSSPropertyWebkitColumnRuleColor:
case CSSPropertyWebkitTextDecorationColor:
case CSSPropertyWebkitTextEmphasisColor:
case CSSPropertyWebkitTextFillColor:
case CSSPropertyWebkitTextStrokeColor:
+#if ENABLE(SVG)
case CSSPropertyFill:
case CSSPropertyStroke:
+#endif
return true;
default:
break;
@@ -1427,7 +1889,7 @@ inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
case CSSPropertyFontFamily:
case CSSPropertyFontSize:
case CSSPropertyFontStyle:
- case CSSPropertyFontVariantCaps:
+ case CSSPropertyFontVariant:
case CSSPropertyFontWeight:
case CSSPropertyLineHeight:
case CSSPropertyOpacity:
@@ -1461,200 +1923,1219 @@ bool StyleResolver::useSVGZoomRules()
return m_state.element() && m_state.element()->isSVGElement();
}
-// Scale with/height properties on inline SVG root.
-bool StyleResolver::useSVGZoomRulesForLength()
+static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, GridLength& workingLength)
{
- return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
+ if (primitiveValue->getValueID() == CSSValueWebkitMinContent) {
+ workingLength = Length(MinContent);
+ return true;
+ }
+
+ if (primitiveValue->getValueID() == CSSValueWebkitMaxContent) {
+ workingLength = Length(MaxContent);
+ return true;
+ }
+
+ if (primitiveValue->isFlex()) {
+ // Fractional unit.
+ workingLength.setFlex(primitiveValue->getDoubleValue());
+ return true;
+ }
+
+ workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
+ if (workingLength.length().isUndefined())
+ return false;
+
+ if (primitiveValue->isLength())
+ workingLength.length().setQuirk(primitiveValue->isQuirkValue());
+
+ return true;
}
-StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(const MatchResult& matchResult)
+static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolver::State& state)
{
- ASSERT(cascadeLevel() != UserAgentLevel);
-
- TextDirection direction;
- WritingMode writingMode;
- extractDirectionAndWritingMode(*state().style(), matchResult, direction, writingMode);
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+ GridLength workingLength;
+ if (!createGridTrackBreadth(primitiveValue, state, workingLength))
+ return false;
- if (cascadeLevel() == AuthorLevel) {
- CascadedProperties* authorRollback = state().authorRollback();
- if (authorRollback)
- return authorRollback;
-
- auto newAuthorRollback(std::make_unique<CascadedProperties>(direction, writingMode));
-
- // This special rollback cascade contains UA rules and user rules but no author rules.
- newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
- newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
- newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
- newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
-
- state().setAuthorRollback(newAuthorRollback);
- return state().authorRollback();
- }
-
- if (cascadeLevel() == UserLevel) {
- CascadedProperties* userRollback = state().userRollback();
- if (userRollback)
- return userRollback;
-
- auto newUserRollback(std::make_unique<CascadedProperties>(direction, writingMode));
-
- // This special rollback cascade contains only UA rules.
- newUserRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
- newUserRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
-
- state().setUserRollback(newUserRollback);
- return state().userRollback();
+ trackSize.setLength(workingLength);
+ return true;
}
-
- return nullptr;
+
+ CSSFunctionValue* minmaxFunction = toCSSFunctionValue(value);
+ CSSValueList* arguments = minmaxFunction->arguments();
+ ASSERT_WITH_SECURITY_IMPLICATION(arguments->length() == 2);
+ GridLength minTrackBreadth;
+ GridLength maxTrackBreadth;
+ if (!createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(0)), state, minTrackBreadth) || !createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(1)), state, maxTrackBreadth))
+ return false;
+
+ trackSize.setMinMax(minTrackBreadth, maxTrackBreadth);
+ return true;
}
-void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChecker::LinkMatchMask linkMatchMask, const MatchResult* matchResult)
+static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, const StyleResolver::State& state)
{
- ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
+ // Handle 'none'.
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+ return primitiveValue->getValueID() == CSSValueNone;
+ }
- State& state = m_state;
-
- RefPtr<CSSValue> valueToApply = value;
- if (value->isVariableDependentValue()) {
- valueToApply = resolvedVariableValue(id, *downcast<CSSVariableDependentValue>(value));
- if (!valueToApply) {
- if (CSSProperty::isInheritedProperty(id))
- valueToApply = CSSValuePool::singleton().createInheritedValue();
- else
- valueToApply = CSSValuePool::singleton().createExplicitInitialValue();
+ if (!value->isValueList())
+ return false;
+
+ size_t currentNamedGridLine = 0;
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (currValue->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(currValue);
+ if (primitiveValue->isString()) {
+ NamedGridLinesMap::AddResult result = namedGridLines.add(primitiveValue->getStringValue(), Vector<size_t>());
+ result.iterator->value.append(currentNamedGridLine);
+ continue;
+ }
}
+
+ ++currentNamedGridLine;
+ GridTrackSize trackSize;
+ if (!createGridTrackSize(currValue, trackSize, state))
+ return false;
+
+ trackSizes.append(trackSize);
+ }
+
+ // The parser should have rejected any <track-list> without any <track-size> as
+ // this is not conformant to the syntax.
+ ASSERT(!trackSizes.isEmpty());
+ return true;
+}
+
+
+static bool createGridPosition(CSSValue* value, GridPosition& position)
+{
+ // We accept the specification's grammar:
+ // 'auto' | [ <integer> || <string> ] | [ span && [ <integer> || string ] ] | <ident>
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+ // We translate <ident> to <string> during parsing as it makes handling it simpler.
+ if (primitiveValue->isString()) {
+ position.setNamedGridArea(primitiveValue->getStringValue());
+ return true;
+ }
+
+ ASSERT(primitiveValue->getValueID() == CSSValueAuto);
+ return true;
+ }
+
+ CSSValueList* values = toCSSValueList(value);
+ ASSERT(values->length());
+
+ bool isSpanPosition = false;
+ // The specification makes the <integer> optional, in which case it default to '1'.
+ int gridLineNumber = 1;
+ String gridLineName;
+
+ CSSValueListIterator it = values;
+ CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value());
+ if (currentValue->getValueID() == CSSValueSpan) {
+ isSpanPosition = true;
+ it.advance();
+ currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
}
+ if (currentValue && currentValue->isNumber()) {
+ gridLineNumber = currentValue->getIntValue();
+ it.advance();
+ currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
+ }
+
+ if (currentValue && currentValue->isString()) {
+ gridLineName = currentValue->getStringValue();
+ it.advance();
+ }
+
+ ASSERT(!it.hasMore());
+ if (isSpanPosition)
+ position.setSpanPosition(gridLineNumber, gridLineName);
+ else
+ position.setExplicitPosition(gridLineNumber, gridLineName);
+
+ return true;
+}
+
+void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
+{
+ ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
+
+ State& state = m_state;
+
if (CSSProperty::isDirectionAwareProperty(id)) {
CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
ASSERT(newId != id);
- return applyProperty(newId, valueToApply.get(), linkMatchMask, matchResult);
+ return applyProperty(newId, value);
}
-
- CSSValue* valueToCheckForInheritInitial = valueToApply.get();
- CSSCustomPropertyValue* customPropertyValue = nullptr;
-
- if (id == CSSPropertyCustom) {
- customPropertyValue = &downcast<CSSCustomPropertyValue>(*valueToApply);
- valueToCheckForInheritInitial = customPropertyValue->value().get();
+
+ bool isInherit = state.parentNode() && value->isInheritedValue();
+ bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
+
+ ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
+ ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
+
+ if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
+ // Limit the properties that can be applied to only the ones honored by :visited.
+ return;
}
- bool isInherit = state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue();
- bool isInitial = valueToCheckForInheritInitial->isInitialValue() || (!state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue());
-
- bool isUnset = valueToCheckForInheritInitial->isUnsetValue();
- bool isRevert = valueToCheckForInheritInitial->isRevertValue();
-
- if (isRevert) {
- if (cascadeLevel() == UserAgentLevel || !matchResult)
- isUnset = true;
- else {
- // Fetch the correct rollback object from the state, building it if necessary.
- // This requires having the original MatchResult available.
- auto* rollback = cascadedPropertiesForRollback(*matchResult);
- ASSERT(rollback);
-
- // With the cascade built, we need to obtain the property and apply it. If the property is
- // not present, then we behave like "unset." Otherwise we apply the property instead of
- // our own.
- if (customPropertyValue) {
- if (rollback->hasCustomProperty(customPropertyValue->name())) {
- auto property = rollback->customProperty(customPropertyValue->name());
- if (property.cssValue[linkMatchMask])
- applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
- return;
- }
- } else if (rollback->hasProperty(id)) {
- auto& property = rollback->property(id);
- if (property.cssValue[linkMatchMask])
- applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
+ if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
+ state.parentStyle()->setHasExplicitlyInheritedProperties();
+
+ // Check lookup table for implementations and use when available.
+ const PropertyHandler& handler = m_deprecatedStyleBuilder.propertyHandler(id);
+ if (handler.isValid()) {
+ if (isInherit)
+ handler.applyInheritValue(id, this);
+ else if (isInitial)
+ handler.applyInitialValue(id, this);
+ else
+ handler.applyValue(id, this, value);
+ return;
+ }
+
+ CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0;
+
+ float zoomFactor = state.style()->effectiveZoom();
+
+ // What follows is a list that maps the CSS properties into their corresponding front-end
+ // RenderStyle values.
+ switch (id) {
+ // lists
+ case CSSPropertyContent:
+ // list of string, uri, counter, attr, i
+ {
+ // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
+ // note is a reminder that eventually "inherit" needs to be supported.
+
+ if (isInitial) {
+ state.style()->clearContent();
return;
}
+
+ if (!value->isValueList())
+ return;
+
+ bool didSet = false;
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* item = i.value();
+ if (item->isImageGeneratorValue()) {
+ if (item->isGradientValue())
+ state.style()->setContent(StyleGeneratedImage::create(*toCSSGradientValue(item)->gradientWithStylesResolved(this)), didSet);
+ else
+ state.style()->setContent(StyleGeneratedImage::create(*toCSSImageGeneratorValue(item)), didSet);
+ didSet = true;
+#if ENABLE(CSS_IMAGE_SET)
+ } else if (item->isImageSetValue()) {
+ state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
+ didSet = true;
+#endif
+ }
+
+ if (item->isImageValue()) {
+ state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, toCSSImageValue(item)), didSet);
+ didSet = true;
+ continue;
+ }
+
+ if (!item->isPrimitiveValue())
+ continue;
+
+ CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
+
+ if (contentValue->isString()) {
+ state.style()->setContent(contentValue->getStringValue().impl(), didSet);
+ didSet = true;
+ } else if (contentValue->isAttr()) {
+ // FIXME: Can a namespace be specified for an attr(foo)?
+ if (state.style()->styleType() == NOPSEUDO)
+ state.style()->setUnique();
+ else
+ state.parentStyle()->setUnique();
+ QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
+ const AtomicString& value = state.element()->getAttribute(attr);
+ state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
+ didSet = true;
+ // Register the fact that the attribute value affects the style.
+ m_ruleSets.features().attrsInRules.add(attr.localName().impl());
+ } else if (contentValue->isCounter()) {
+ Counter* counterValue = contentValue->getCounterValue();
+ EListStyleType listStyleType = NoneListStyle;
+ CSSValueID listStyleIdent = counterValue->listStyleIdent();
+ if (listStyleIdent != CSSValueNone)
+ listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
+ auto counter = std::make_unique<CounterContent>(counterValue->identifier(), listStyleType, counterValue->separator());
+ state.style()->setContent(std::move(counter), didSet);
+ didSet = true;
+ } else {
+ switch (contentValue->getValueID()) {
+ case CSSValueOpenQuote:
+ state.style()->setContent(OPEN_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueCloseQuote:
+ state.style()->setContent(CLOSE_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueNoOpenQuote:
+ state.style()->setContent(NO_OPEN_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueNoCloseQuote:
+ state.style()->setContent(NO_CLOSE_QUOTE, didSet);
+ didSet = true;
+ break;
+ default:
+ // normal and none do not have any effect.
+ { }
+ }
+ }
+ }
+ if (!didSet)
+ state.style()->clearContent();
+ return;
+ }
+ case CSSPropertyWebkitAlt:
+ {
+ bool didSet = false;
+ if (primitiveValue->isString()) {
+ state.style()->setContentAltText(primitiveValue->getStringValue().impl());
+ didSet = true;
+ } else if (primitiveValue->isAttr()) {
+ // FIXME: Can a namespace be specified for an attr(foo)?
+ if (state.style()->styleType() == NOPSEUDO)
+ state.style()->setUnique();
+ else
+ state.parentStyle()->setUnique();
+ QualifiedName attr(nullAtom, primitiveValue->getStringValue().impl(), nullAtom);
+ const AtomicString& value = state.element()->getAttribute(attr);
+ state.style()->setContentAltText(value.isNull() ? emptyAtom : value.impl());
+ didSet = true;
+ // Register the fact that the attribute value affects the style.
+ m_ruleSets.features().attrsInRules.add(attr.localName().impl());
+ }
+ if (!didSet)
+ state.style()->setContentAltText(emptyAtom);
+ return;
+ }
- isUnset = true;
+ case CSSPropertyQuotes:
+ if (isInherit) {
+ state.style()->setQuotes(state.parentStyle()->quotes());
+ return;
+ }
+ if (isInitial) {
+ state.style()->setQuotes(0);
+ return;
+ }
+ if (value->isValueList()) {
+ CSSValueList* list = toCSSValueList(value);
+ Vector<std::pair<String, String>> quotes;
+ for (size_t i = 0; i < list->length(); i += 2) {
+ CSSValue* first = list->itemWithoutBoundsCheck(i);
+ // item() returns null if out of bounds so this is safe.
+ CSSValue* second = list->item(i + 1);
+ if (!second)
+ continue;
+ ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue());
+ ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue());
+ String startQuote = toCSSPrimitiveValue(first)->getStringValue();
+ String endQuote = toCSSPrimitiveValue(second)->getStringValue();
+ quotes.append(std::make_pair(startQuote, endQuote));
+ }
+ state.style()->setQuotes(QuotesData::create(quotes));
+ return;
+ }
+ if (primitiveValue) {
+ if (primitiveValue->getValueID() == CSSValueNone)
+ state.style()->setQuotes(QuotesData::create(Vector<std::pair<String, String>>()));
}
+ return;
+ // Shorthand properties.
+ case CSSPropertyFont:
+ if (isInherit) {
+ FontDescription fontDescription = state.parentStyle()->fontDescription();
+ state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight());
+ state.setLineHeightValue(0);
+ setFontDescription(fontDescription);
+ } else if (isInitial) {
+ Settings* settings = documentSettings();
+ ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
+ if (!settings)
+ return;
+ initializeFontStyle(settings);
+ } else if (primitiveValue) {
+ state.style()->setLineHeight(RenderStyle::initialLineHeight());
+ state.setLineHeightValue(0);
+
+ FontDescription fontDescription;
+ RenderTheme::defaultTheme()->systemFont(primitiveValue->getValueID(), fontDescription);
+
+ // Double-check and see if the theme did anything. If not, don't bother updating the font.
+ if (fontDescription.isAbsoluteSize()) {
+ // Make sure the rendering mode and printer font settings are updated.
+ Settings* settings = documentSettings();
+ ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
+ if (!settings)
+ return;
+ fontDescription.setRenderingMode(settings->fontRenderingMode());
+ fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
+
+ // Handle the zoom factor.
+ fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(fontDescription.specifiedSize(), fontDescription.isAbsoluteSize(), useSVGZoomRules(), state.style(), document()));
+ setFontDescription(fontDescription);
+ }
+ } else if (value->isFontValue()) {
+ CSSFontValue* font = toCSSFontValue(value);
+ if (!font->style || !font->variant || !font->weight
+ || !font->size || !font->lineHeight || !font->family)
+ return;
+ applyProperty(CSSPropertyFontStyle, font->style.get());
+ applyProperty(CSSPropertyFontVariant, font->variant.get());
+ applyProperty(CSSPropertyFontWeight, font->weight.get());
+ // The previous properties can dirty our font but they don't try to read the font's
+ // properties back, which is safe. However if font-size is using the 'ex' unit, it will
+ // need query the dirtied font's x-height to get the computed size. To be safe in this
+ // case, let's just update the font now.
+ updateFont();
+ applyProperty(CSSPropertyFontSize, font->size.get());
+
+ state.setLineHeightValue(font->lineHeight.get());
+
+ applyProperty(CSSPropertyFontFamily, font->family.get());
+ }
+ return;
+
+ case CSSPropertyBackground:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBorder:
+ case CSSPropertyBorderBottom:
+ case CSSPropertyBorderColor:
+ case CSSPropertyBorderImage:
+ case CSSPropertyBorderLeft:
+ case CSSPropertyBorderRadius:
+ case CSSPropertyBorderRight:
+ case CSSPropertyBorderSpacing:
+ case CSSPropertyBorderStyle:
+ case CSSPropertyBorderTop:
+ case CSSPropertyBorderWidth:
+ case CSSPropertyListStyle:
+ case CSSPropertyMargin:
+ case CSSPropertyOutline:
+ case CSSPropertyOverflow:
+ case CSSPropertyPadding:
+ case CSSPropertyTransition:
+ case CSSPropertyWebkitAnimation:
+ case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyWebkitBorderStart:
+ case CSSPropertyWebkitBorderRadius:
+ case CSSPropertyWebkitColumns:
+ case CSSPropertyWebkitColumnRule:
+ case CSSPropertyWebkitFlex:
+ case CSSPropertyWebkitFlexFlow:
+ case CSSPropertyWebkitGridArea:
+ case CSSPropertyWebkitGridColumn:
+ case CSSPropertyWebkitGridRow:
+ case CSSPropertyWebkitMarginCollapse:
+ case CSSPropertyWebkitMarquee:
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskPosition:
+ case CSSPropertyWebkitMaskRepeat:
+ case CSSPropertyWebkitTextEmphasis:
+ case CSSPropertyWebkitTextStroke:
+ case CSSPropertyWebkitTransition:
+ case CSSPropertyWebkitTransformOrigin:
+ ASSERT(isExpandedShorthand(id));
+ ASSERT_NOT_REACHED();
+ break;
+
+ // CSS3 Properties
+ case CSSPropertyTextShadow:
+ case CSSPropertyBoxShadow:
+ case CSSPropertyWebkitBoxShadow: {
+ if (isInherit) {
+ if (id == CSSPropertyTextShadow)
+ return state.style()->setTextShadow(state.parentStyle()->textShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr);
+ return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr);
+ }
+ if (isInitial || primitiveValue) // initial | none
+ return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr);
+
+ if (!value->isValueList())
+ return;
+
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isShadowValue())
+ continue;
+ CSSShadowValue* item = toCSSShadowValue(currValue);
+ int x = item->x->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
+ if (item->x->isViewportPercentageLength())
+ x = viewportPercentageValue(*item->x, x);
+ int y = item->y->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
+ if (item->y->isViewportPercentageLength())
+ y = viewportPercentageValue(*item->y, y);
+ int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
+ if (item->blur && item->blur->isViewportPercentageLength())
+ blur = viewportPercentageValue(*item->blur, blur);
+ int spread = item->spread ? item->spread->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
+ if (item->spread && item->spread->isViewportPercentageLength())
+ spread = viewportPercentageValue(*item->spread, spread);
+ ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal;
+ Color color;
+ if (item->color)
+ color = colorFromPrimitiveValue(item->color.get());
+ else if (state.style())
+ color = state.style()->color();
+
+ OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
+ if (id == CSSPropertyTextShadow)
+ state.style()->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
+ else
+ state.style()->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
+ }
+ return;
}
-
- if (isUnset) {
- if (CSSProperty::isInheritedProperty(id))
- isInherit = true;
+ case CSSPropertyWebkitBoxReflect: {
+ HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
+ if (primitiveValue) {
+ state.style()->setBoxReflect(RenderStyle::initialBoxReflect());
+ return;
+ }
+
+ if (!value->isReflectValue())
+ return;
+
+ CSSReflectValue* reflectValue = toCSSReflectValue(value);
+ RefPtr<StyleReflection> reflection = StyleReflection::create();
+ reflection->setDirection(*reflectValue->direction());
+ if (reflectValue->offset())
+ reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.style(), state.rootElementStyle(), zoomFactor));
+ NinePieceImage mask;
+ mask.setMaskDefaults();
+ m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
+ reflection->setMask(mask);
+
+ state.style()->setBoxReflect(reflection.release());
+ return;
+ }
+ case CSSPropertySrc: // Only used in @font-face rules.
+ return;
+ case CSSPropertyUnicodeRange: // Only used in @font-face rules.
+ return;
+ case CSSPropertyWebkitLocale: {
+ HANDLE_INHERIT_AND_INITIAL(locale, Locale);
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getValueID() == CSSValueAuto)
+ state.style()->setLocale(nullAtom);
else
- isInitial = true;
+ state.style()->setLocale(primitiveValue->getStringValue());
+ FontDescription fontDescription = state.style()->fontDescription();
+ fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale()));
+ setFontDescription(fontDescription);
+ return;
}
+#if ENABLE(IOS_TEXT_AUTOSIZING)
+ case CSSPropertyWebkitTextSizeAdjust: {
+ HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
+ if (!primitiveValue)
+ return;
- ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
+ if (primitiveValue->getValueID() == CSSValueAuto)
+ state.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment));
+ else if (primitiveValue->getValueID() == CSSValueNone)
+ state.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
+ else
+ state.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue->getFloatValue()));
- if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
- // Limit the properties that can be applied to only the ones honored by :visited.
+ state.setFontDirty(true);
return;
}
+#endif
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion:
+ {
+ HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
+ if (!primitiveValue)
+ return;
- if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
- state.parentStyle()->setHasExplicitlyInheritedProperties();
-
- if (id == CSSPropertyCustom) {
- CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
+ if (primitiveValue->getValueID() == CSSValueNone) {
+ state.style()->setDashboardRegions(RenderStyle::noneDashboardRegions());
+ return;
+ }
+
+ DashboardRegion* region = primitiveValue->getDashboardRegionValue();
+ if (!region)
+ return;
+
+ DashboardRegion* first = region;
+ while (region) {
+ Length top = convertToIntLength(region->top(), state.style(), state.rootElementStyle());
+ Length right = convertToIntLength(region->right(), state.style(), state.rootElementStyle());
+ Length bottom = convertToIntLength(region->bottom(), state.style(), state.rootElementStyle());
+ Length left = convertToIntLength(region->left(), state.style(), state.rootElementStyle());
+
+ if (top.isUndefined())
+ top = Length();
+ if (right.isUndefined())
+ right = Length();
+ if (bottom.isUndefined())
+ bottom = Length();
+ if (left.isUndefined())
+ left = Length();
+
+ if (region->m_isCircle)
+ state.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
+ else if (region->m_isRectangle)
+ state.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
+ region = region->m_next.get();
+ }
+
+ state.document().setHasAnnotatedRegions(true);
+
+ return;
+ }
+#endif
+ case CSSPropertyWebkitTextStrokeWidth: {
+ HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
+ float width = 0;
+ switch (primitiveValue->getValueID()) {
+ case CSSValueThin:
+ case CSSValueMedium:
+ case CSSValueThick: {
+ double result = 1.0 / 48;
+ if (primitiveValue->getValueID() == CSSValueMedium)
+ result *= 3;
+ else if (primitiveValue->getValueID() == CSSValueThick)
+ result *= 5;
+ Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS));
+ width = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
+ break;
+ }
+ default:
+ width = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
+ break;
+ }
+ state.style()->setTextStrokeWidth(width);
+ return;
+ }
+ case CSSPropertyWebkitTransform: {
+ HANDLE_INHERIT_AND_INITIAL(transform, Transform);
+ TransformOperations operations;
+ transformsForValue(state.style(), state.rootElementStyle(), value, operations);
+ state.style()->setTransform(operations);
+ return;
+ }
+ case CSSPropertyWebkitPerspective: {
+ HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
+
+ if (!primitiveValue)
+ return;
+
+ if (primitiveValue->getValueID() == CSSValueNone) {
+ state.style()->setPerspective(0);
+ return;
+ }
+
+ float perspectiveValue;
+ if (primitiveValue->isLength())
+ perspectiveValue = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
+ else if (primitiveValue->isNumber()) {
+ // For backward compatibility, treat valueless numbers as px.
+ Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX));
+ perspectiveValue = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
+ } else
+ return;
+
+ if (perspectiveValue >= 0.0f)
+ state.style()->setPerspective(perspectiveValue);
+ return;
+ }
+#if PLATFORM(IOS)
+ case CSSPropertyWebkitTouchCallout: {
+ HANDLE_INHERIT_AND_INITIAL(touchCalloutEnabled, TouchCalloutEnabled);
+ if (!primitiveValue)
+ break;
+
+ state.style()->setTouchCalloutEnabled(primitiveValue->getStringValue().lower() != "none");
+ return;
+ }
+
+ // FIXME: CSSPropertyWebkitCompositionFillColor shouldn't be iOS-specific. Once we fix up its usage in
+ // InlineTextBox::paintCompositionBackground() we should move it outside the PLATFORM(IOS)-guard.
+ // See <https://bugs.webkit.org/show_bug.cgi?id=126296>.
+ case CSSPropertyWebkitCompositionFillColor: {
+ HANDLE_INHERIT_AND_INITIAL(compositionFillColor, CompositionFillColor);
+ if (!primitiveValue)
+ break;
+ state.style()->setCompositionFillColor(colorFromPrimitiveValue(primitiveValue));
+ return;
+ }
+#endif
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor: {
+ HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
+ if (!primitiveValue)
+ break;
+
+ Color col = colorFromPrimitiveValue(primitiveValue);
+ state.style()->setTapHighlightColor(col);
+ return;
+ }
+#endif
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+ case CSSPropertyWebkitOverflowScrolling: {
+ HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
+ if (!primitiveValue)
+ break;
+ state.style()->setUseTouchOverflowScrolling(primitiveValue->getValueID() == CSSValueTouch);
+ return;
+ }
+#endif
+ case CSSPropertyInvalid:
+ return;
+ case CSSPropertyFontStretch:
+ case CSSPropertyPage:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderline:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTextUnderlineWidth:
+ case CSSPropertyWebkitFontSizeDelta:
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ return;
+
+ // CSS Text Layout Module Level 3: Vertical writing support
+ case CSSPropertyWebkitWritingMode: {
+ HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
+
+ if (primitiveValue)
+ setWritingMode(*primitiveValue);
+
+ // FIXME: It is not ok to modify document state while applying style.
+ if (state.element() && state.element() == state.document().documentElement())
+ state.document().setWritingModeSetOnDocumentElement(true);
+ return;
+ }
+
+ case CSSPropertyWebkitTextOrientation: {
+ HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation);
+
+ if (primitiveValue)
+ setTextOrientation(*primitiveValue);
+
+ return;
+ }
+
+ case CSSPropertyWebkitLineBoxContain: {
+ HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
+ if (primitiveValue && primitiveValue->getValueID() == CSSValueNone) {
+ state.style()->setLineBoxContain(LineBoxContainNone);
+ return;
+ }
+
+ if (!value->isLineBoxContainValue())
+ return;
+
+ state.style()->setLineBoxContain(toCSSLineBoxContainValue(value)->value());
+ return;
+ }
+
+ // CSS Fonts Module Level 3
+ case CSSPropertyWebkitFontFeatureSettings: {
+ if (primitiveValue && primitiveValue->getValueID() == CSSValueNormal) {
+ setFontDescription(state.style()->fontDescription().makeNormalFeatureSettings());
+ return;
+ }
+
+ if (!value->isValueList())
+ return;
+
+ FontDescription fontDescription = state.style()->fontDescription();
+ CSSValueList* list = toCSSValueList(value);
+ RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
+ int len = list->length();
+ for (int i = 0; i < len; ++i) {
+ CSSValue* item = list->itemWithoutBoundsCheck(i);
+ if (!item->isFontFeatureValue())
+ continue;
+ CSSFontFeatureValue* feature = toCSSFontFeatureValue(item);
+ settings->append(FontFeature(feature->tag(), feature->value()));
+ }
+ fontDescription.setFeatureSettings(settings.release());
+ setFontDescription(fontDescription);
+ return;
+ }
+
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter: {
+ HANDLE_INHERIT_AND_INITIAL(filter, Filter);
+ FilterOperations operations;
+ if (createFilterOperations(value, operations))
+ state.style()->setFilter(operations);
+ return;
+ }
+#endif
+ case CSSPropertyWebkitGridAutoColumns: {
+ HANDLE_INHERIT_AND_INITIAL(gridAutoColumns, GridAutoColumns);
+ GridTrackSize trackSize;
+ if (!createGridTrackSize(value, trackSize, state))
+ return;
+ state.style()->setGridAutoColumns(trackSize);
+ return;
+ }
+ case CSSPropertyWebkitGridAutoRows: {
+ HANDLE_INHERIT_AND_INITIAL(gridAutoRows, GridAutoRows);
+ GridTrackSize trackSize;
+ if (!createGridTrackSize(value, trackSize, state))
+ return;
+ state.style()->setGridAutoRows(trackSize);
+ return;
+ }
+ case CSSPropertyWebkitGridDefinitionColumns: {
if (isInherit) {
- RefPtr<CSSValue> customVal = state.parentStyle()->getCustomPropertyValue(customProperty->name());
- if (!customVal)
- customVal = CSSCustomPropertyValue::createInvalid();
- state.style()->setCustomPropertyValue(customProperty->name(), customVal);
- } else if (isInitial)
- state.style()->setCustomPropertyValue(customProperty->name(), CSSCustomPropertyValue::createInvalid());
- else
- state.style()->setCustomPropertyValue(customProperty->name(), customProperty->value());
+ m_state.style()->setGridColumns(m_state.parentStyle()->gridColumns());
+ m_state.style()->setNamedGridColumnLines(m_state.parentStyle()->namedGridColumnLines());
+ return;
+ }
+ if (isInitial) {
+ m_state.style()->setGridColumns(RenderStyle::initialGridColumns());
+ m_state.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines());
+ return;
+ }
+ Vector<GridTrackSize> trackSizes;
+ NamedGridLinesMap namedGridLines;
+ if (!createGridTrackList(value, trackSizes, namedGridLines, state))
+ return;
+ state.style()->setGridColumns(trackSizes);
+ state.style()->setNamedGridColumnLines(namedGridLines);
+ return;
+ }
+ case CSSPropertyWebkitGridDefinitionRows: {
+ if (isInherit) {
+ m_state.style()->setGridRows(m_state.parentStyle()->gridRows());
+ m_state.style()->setNamedGridRowLines(m_state.parentStyle()->namedGridRowLines());
+ return;
+ }
+ if (isInitial) {
+ m_state.style()->setGridRows(RenderStyle::initialGridRows());
+ m_state.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines());
+ return;
+ }
+ Vector<GridTrackSize> trackSizes;
+ NamedGridLinesMap namedGridLines;
+ if (!createGridTrackList(value, trackSizes, namedGridLines, state))
+ return;
+ state.style()->setGridRows(trackSizes);
+ state.style()->setNamedGridRowLines(namedGridLines);
return;
}
- // Use the generated StyleBuilder.
- StyleBuilder::applyProperty(id, *this, *valueToApply, isInitial, isInherit);
-}
+ case CSSPropertyWebkitGridColumnStart: {
+ HANDLE_INHERIT_AND_INITIAL(gridItemColumnStart, GridItemColumnStart);
+ GridPosition columnStartPosition;
+ if (!createGridPosition(value, columnStartPosition))
+ return;
+ state.style()->setGridItemColumnStart(columnStartPosition);
+ return;
+ }
+ case CSSPropertyWebkitGridColumnEnd: {
+ HANDLE_INHERIT_AND_INITIAL(gridItemColumnEnd, GridItemColumnEnd);
+ GridPosition columnEndPosition;
+ if (!createGridPosition(value, columnEndPosition))
+ return;
+ state.style()->setGridItemColumnEnd(columnEndPosition);
+ return;
+ }
-RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSVariableDependentValue& value)
-{
- CSSParser parser(m_state.document());
- return parser.parseVariableDependentValue(propID, value, m_state.style()->customProperties());
+ case CSSPropertyWebkitGridRowStart: {
+ HANDLE_INHERIT_AND_INITIAL(gridItemRowStart, GridItemRowStart);
+ GridPosition rowStartPosition;
+ if (!createGridPosition(value, rowStartPosition))
+ return;
+ state.style()->setGridItemRowStart(rowStartPosition);
+ return;
+ }
+ case CSSPropertyWebkitGridRowEnd: {
+ HANDLE_INHERIT_AND_INITIAL(gridItemRowEnd, GridItemRowEnd);
+ GridPosition rowEndPosition;
+ if (!createGridPosition(value, rowEndPosition))
+ return;
+ state.style()->setGridItemRowEnd(rowEndPosition);
+ return;
+ }
+ case CSSPropertyWebkitGridTemplate: {
+ if (isInherit) {
+ state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
+ state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
+ state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
+ return;
+ }
+ if (isInitial) {
+ state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
+ state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
+ state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
+ return;
+ }
+
+ if (value->isPrimitiveValue()) {
+ ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
+ return;
+ }
+
+ CSSGridTemplateValue* gridTemplateValue = toCSSGridTemplateValue(value);
+ state.style()->setNamedGridArea(gridTemplateValue->gridAreaMap());
+ state.style()->setNamedGridAreaRowCount(gridTemplateValue->rowCount());
+ state.style()->setNamedGridAreaColumnCount(gridTemplateValue->columnCount());
+ return;
+ }
+
+ // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version.
+ case CSSPropertyTransitionDelay:
+ case CSSPropertyTransitionDuration:
+ case CSSPropertyTransitionProperty:
+ case CSSPropertyTransitionTimingFunction:
+ return;
+ // These properties are implemented in the DeprecatedStyleBuilder lookup table.
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderBottomLeftRadius:
+ case CSSPropertyBorderBottomRightRadius:
+ case CSSPropertyBorderBottomStyle:
+ case CSSPropertyBorderBottomWidth:
+ case CSSPropertyBorderCollapse:
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyBorderLeftWidth:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderRightStyle:
+ case CSSPropertyBorderRightWidth:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyBorderTopLeftRadius:
+ case CSSPropertyBorderTopRightRadius:
+ case CSSPropertyBorderTopStyle:
+ case CSSPropertyBorderTopWidth:
+ case CSSPropertyBottom:
+ case CSSPropertyBoxSizing:
+ case CSSPropertyCaptionSide:
+ case CSSPropertyClear:
+ case CSSPropertyClip:
+ case CSSPropertyColor:
+ case CSSPropertyCounterIncrement:
+ case CSSPropertyCounterReset:
+ case CSSPropertyCursor:
+ case CSSPropertyDirection:
+ case CSSPropertyDisplay:
+ case CSSPropertyEmptyCells:
+ case CSSPropertyFloat:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontVariant:
+ case CSSPropertyFontWeight:
+ case CSSPropertyHeight:
+#if ENABLE(CSS_IMAGE_ORIENTATION)
+ case CSSPropertyImageOrientation:
+#endif
+ case CSSPropertyImageRendering:
+#if ENABLE(CSS_IMAGE_RESOLUTION)
+ case CSSPropertyImageResolution:
+#endif
+ case CSSPropertyLeft:
+ case CSSPropertyLetterSpacing:
+ case CSSPropertyLineHeight:
+ case CSSPropertyListStyleImage:
+ case CSSPropertyListStylePosition:
+ case CSSPropertyListStyleType:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginTop:
+ case CSSPropertyMaxHeight:
+ case CSSPropertyMaxWidth:
+ case CSSPropertyMinHeight:
+ case CSSPropertyMinWidth:
+ case CSSPropertyObjectFit:
+ case CSSPropertyOpacity:
+ case CSSPropertyOrphans:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyOutlineOffset:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOutlineWidth:
+ case CSSPropertyOverflowWrap:
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyPageBreakAfter:
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyPageBreakInside:
+ case CSSPropertyPointerEvents:
+ case CSSPropertyPosition:
+ case CSSPropertyResize:
+ case CSSPropertyRight:
+ case CSSPropertySize:
+ case CSSPropertySpeak:
+ case CSSPropertyTabSize:
+ case CSSPropertyTableLayout:
+ case CSSPropertyTextAlign:
+ case CSSPropertyTextDecoration:
+ case CSSPropertyTextIndent:
+ case CSSPropertyTextOverflow:
+ case CSSPropertyTextRendering:
+ case CSSPropertyTextTransform:
+ case CSSPropertyTop:
+ case CSSPropertyUnicodeBidi:
+ case CSSPropertyVerticalAlign:
+ case CSSPropertyVisibility:
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitAppearance:
+ case CSSPropertyWebkitAspectRatio:
+ case CSSPropertyWebkitBackfaceVisibility:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitBorderFit:
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ case CSSPropertyWebkitBoxAlign:
+#if ENABLE(CSS_BOX_DECORATION_BREAK)
+ case CSSPropertyWebkitBoxDecorationBreak:
+#endif
+ case CSSPropertyWebkitBoxDirection:
+ case CSSPropertyWebkitBoxFlex:
+ case CSSPropertyWebkitBoxFlexGroup:
+ case CSSPropertyWebkitBoxLines:
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ case CSSPropertyWebkitBoxOrient:
+ case CSSPropertyWebkitBoxPack:
+ case CSSPropertyWebkitColorCorrection:
+ case CSSPropertyWebkitColumnAxis:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ case CSSPropertyWebkitColumnBreakInside:
+ case CSSPropertyWebkitColumnCount:
+ case CSSPropertyWebkitColumnGap:
+ case CSSPropertyWebkitColumnProgression:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitColumnRuleStyle:
+ case CSSPropertyWebkitColumnRuleWidth:
+ case CSSPropertyWebkitColumnSpan:
+ case CSSPropertyWebkitColumnWidth:
+#if ENABLE(CURSOR_VISIBILITY)
+ case CSSPropertyWebkitCursorVisibility:
+#endif
+ case CSSPropertyWebkitAlignContent:
+ case CSSPropertyWebkitAlignItems:
+ case CSSPropertyWebkitAlignSelf:
+ case CSSPropertyWebkitFlexBasis:
+ case CSSPropertyWebkitFlexDirection:
+ case CSSPropertyWebkitFlexGrow:
+ case CSSPropertyWebkitFlexShrink:
+ case CSSPropertyWebkitFlexWrap:
+ case CSSPropertyWebkitJustifyContent:
+ case CSSPropertyWebkitOrder:
+#if ENABLE(CSS_REGIONS)
+ case CSSPropertyWebkitFlowFrom:
+ case CSSPropertyWebkitFlowInto:
+#endif
+ case CSSPropertyWebkitFontKerning:
+ case CSSPropertyWebkitFontSmoothing:
+ case CSSPropertyWebkitFontVariantLigatures:
+ case CSSPropertyWebkitHighlight:
+ case CSSPropertyWebkitHyphenateCharacter:
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ case CSSPropertyWebkitHyphenateLimitLines:
+ case CSSPropertyWebkitHyphens:
+ case CSSPropertyWebkitLineAlign:
+ case CSSPropertyWebkitLineBreak:
+ case CSSPropertyWebkitLineClamp:
+ case CSSPropertyWebkitLineGrid:
+ case CSSPropertyWebkitLineSnap:
+ case CSSPropertyWebkitMarqueeDirection:
+ case CSSPropertyWebkitMarqueeIncrement:
+ case CSSPropertyWebkitMarqueeRepetition:
+ case CSSPropertyWebkitMarqueeSpeed:
+ case CSSPropertyWebkitMarqueeStyle:
+ case CSSPropertyWebkitMaskBoxImage:
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ case CSSPropertyWebkitMaskBoxImageRepeat:
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ case CSSPropertyWebkitMaskBoxImageSource:
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskComposite:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskOrigin:
+ case CSSPropertyWebkitMaskPositionX:
+ case CSSPropertyWebkitMaskPositionY:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY:
+ case CSSPropertyWebkitMaskSize:
+ case CSSPropertyWebkitMaskSourceType:
+ case CSSPropertyWebkitNbspMode:
+ case CSSPropertyWebkitPerspectiveOrigin:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitPrintColorAdjust:
+#if ENABLE(CSS_REGIONS)
+ case CSSPropertyWebkitRegionBreakAfter:
+ case CSSPropertyWebkitRegionBreakBefore:
+ case CSSPropertyWebkitRegionBreakInside:
+ case CSSPropertyWebkitRegionFragment:
+#endif
+ case CSSPropertyWebkitRtlOrdering:
+ case CSSPropertyWebkitRubyPosition:
+ case CSSPropertyWebkitTextCombine:
+#if ENABLE(CSS3_TEXT)
+ case CSSPropertyWebkitTextAlignLast:
+ case CSSPropertyWebkitTextJustify:
+#endif // CSS3_TEXT
+ case CSSPropertyWebkitTextDecorationLine:
+ case CSSPropertyWebkitTextDecorationStyle:
+ case CSSPropertyWebkitTextDecorationColor:
+ case CSSPropertyWebkitTextDecorationSkip:
+ case CSSPropertyWebkitTextUnderlinePosition:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextEmphasisPosition:
+ case CSSPropertyWebkitTextEmphasisStyle:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextSecurity:
+ case CSSPropertyWebkitTextStrokeColor:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyWebkitTransformStyle:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionProperty:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ case CSSPropertyWebkitUserDrag:
+ case CSSPropertyWebkitUserModify:
+ case CSSPropertyWebkitUserSelect:
+ case CSSPropertyWebkitClipPath:
+#if ENABLE(CSS_SHAPES)
+ case CSSPropertyWebkitShapeMargin:
+ case CSSPropertyWebkitShapePadding:
+ case CSSPropertyWebkitShapeImageThreshold:
+ case CSSPropertyWebkitShapeInside:
+ case CSSPropertyWebkitShapeOutside:
+#endif
+#if ENABLE(CSS_EXCLUSIONS)
+ case CSSPropertyWebkitWrapFlow:
+ case CSSPropertyWebkitWrapThrough:
+#endif
+ case CSSPropertyWhiteSpace:
+ case CSSPropertyWidows:
+ case CSSPropertyWidth:
+ case CSSPropertyWordBreak:
+ case CSSPropertyWordSpacing:
+ case CSSPropertyWordWrap:
+ case CSSPropertyZIndex:
+ case CSSPropertyZoom:
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+ case CSSPropertyMaxZoom:
+ case CSSPropertyMinZoom:
+ case CSSPropertyOrientation:
+ case CSSPropertyUserZoom:
+#endif
+ ASSERT_NOT_REACHED();
+ return;
+ default:
+#if ENABLE(SVG)
+ // Try the SVG properties
+ applySVGProperty(id, value);
+#endif
+ return;
+ }
}
-PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue& value)
+PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value)
{
- if (is<CSSImageValue>(value))
- return cachedOrPendingFromValue(property, downcast<CSSImageValue>(value));
+ if (value->isImageValue())
+ return cachedOrPendingFromValue(property, toCSSImageValue(value));
- if (is<CSSImageGeneratorValue>(value)) {
- if (is<CSSGradientValue>(value))
- return generatedOrPendingFromValue(property, *downcast<CSSGradientValue>(value).gradientWithStylesResolved(this));
- return generatedOrPendingFromValue(property, downcast<CSSImageGeneratorValue>(value));
+ if (value->isImageGeneratorValue()) {
+ if (value->isGradientValue())
+ return generatedOrPendingFromValue(property, *toCSSGradientValue(value)->gradientWithStylesResolved(this));
+ return generatedOrPendingFromValue(property, toCSSImageGeneratorValue(*value));
}
#if ENABLE(CSS_IMAGE_SET)
- if (is<CSSImageSetValue>(value))
- return setOrPendingFromValue(property, downcast<CSSImageSetValue>(value));
+ if (value->isImageSetValue())
+ return setOrPendingFromValue(property, toCSSImageSetValue(value));
#endif
- if (is<CSSCursorImageValue>(value))
- return cursorOrPendingFromValue(property, downcast<CSSCursorImageValue>(value));
+ if (value->isCursorImageValue())
+ return cursorOrPendingFromValue(property, toCSSCursorImageValue(value));
- return nullptr;
+ return 0;
}
-PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue& value)
+PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
{
- RefPtr<StyleImage> image = value.cachedOrPendingImage();
+ RefPtr<StyleImage> image = value->cachedOrPendingImage();
if (image && image->isPendingImage())
- m_state.pendingImageProperties().set(property, &value);
+ m_state.pendingImageProperties().set(property, value);
return image.release();
}
PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
{
- if (is<CSSFilterImageValue>(value)) {
+#if ENABLE(CSS_FILTERS)
+ if (value.isFilterImageValue()) {
// FilterImage needs to calculate FilterOperations.
- downcast<CSSFilterImageValue>(value).createFilterOperations(this);
+ toCSSFilterImageValue(value).createFilterOperations(this);
}
-
+#endif
if (value.isPending()) {
m_state.pendingImageProperties().set(property, &value);
return StylePendingImage::create(&value);
@@ -1663,20 +3144,20 @@ PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID
}
#if ENABLE(CSS_IMAGE_SET)
-PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue& value)
+PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value)
{
- RefPtr<StyleImage> image = value.cachedOrPendingImageSet(document());
+ RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document());
if (image && image->isPendingImage())
- m_state.pendingImageProperties().set(property, &value);
+ m_state.pendingImageProperties().set(property, value);
return image.release();
}
#endif
-PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue& value)
+PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue* value)
{
- RefPtr<StyleImage> image = value.cachedOrPendingImage(document());
+ RefPtr<StyleImage> image = value->cachedOrPendingImage(document());
if (image && image->isPendingImage())
- m_state.pendingImageProperties().set(property, &value);
+ m_state.pendingImageProperties().set(property, value);
return image.release();
}
@@ -1686,7 +3167,7 @@ void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
if (style->textSizeAdjust().isAuto())
return;
- auto newFontDescription = style->fontDescription();
+ FontDescription newFontDescription(style->fontDescription());
if (!style->textSizeAdjust().isNone())
newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier());
else
@@ -1697,35 +3178,38 @@ void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
{
- if (!parentStyle)
- return;
-
- if (style->effectiveZoom() == parentStyle->effectiveZoom() && style->textZoom() == parentStyle->textZoom())
+ if (style->effectiveZoom() == parentStyle->effectiveZoom())
return;
- const auto& childFont = style->fontDescription();
- auto newFontDescription = childFont;
+ const FontDescription& childFont = style->fontDescription();
+ FontDescription newFontDescription(childFont);
setFontSize(newFontDescription, childFont.specifiedSize());
style->setFontDescription(newFontDescription);
}
void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
{
- const auto& childFont = style->fontDescription();
+ const FontDescription& childFont = style->fontDescription();
if (childFont.isAbsoluteSize() || !parentStyle)
return;
- const auto& parentFont = parentStyle->fontDescription();
+ const FontDescription& parentFont = parentStyle->fontDescription();
if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
return;
+
+ // For now, lump all families but monospace together.
+ if (childFont.genericFamily() != FontDescription::MonospaceFamily
+ && parentFont.genericFamily() != FontDescription::MonospaceFamily)
+ return;
+
// We know the parent is monospace or the child is monospace, and that font
// size was unspecified. We want to scale our font size as appropriate.
// If the font uses a keyword size, then we refetch from the table rather than
// multiplying by our scale factor.
float size;
- if (CSSValueID sizeIdentifier = childFont.keywordSizeAsIdentifier())
- size = Style::fontSizeForKeyword(sizeIdentifier, childFont.useFixedDefaultSize(), document());
+ if (childFont.keywordSize())
+ size = Style::fontSizeForKeyword(CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize(), document());
else {
Settings* settings = documentSettings();
float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
@@ -1736,23 +3220,28 @@ void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle*
childFont.specifiedSize() * fixedScaleFactor;
}
- auto newFontDescription = childFont;
+ FontDescription newFontDescription(childFont);
setFontSize(newFontDescription, size);
style->setFontDescription(newFontDescription);
}
void StyleResolver::initializeFontStyle(Settings* settings)
{
- FontCascadeDescription fontDescription;
- if (settings)
- fontDescription.setRenderingMode(settings->fontRenderingMode());
- fontDescription.setOneFamily(standardFamily);
- fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
+ FontDescription fontDescription;
+ fontDescription.setGenericFamily(FontDescription::StandardFamily);
+ fontDescription.setRenderingMode(settings->fontRenderingMode());
+ fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
+ const AtomicString& standardFontFamily = documentSettings()->standardFontFamily();
+ if (!standardFontFamily.isEmpty())
+ fontDescription.setOneFamily(standardFontFamily);
+ fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
+ m_state.style()->setLineHeight(RenderStyle::initialLineHeight());
+ m_state.setLineHeightValue(0);
setFontDescription(fontDescription);
}
-void StyleResolver::setFontSize(FontCascadeDescription& fontDescription, float size)
+void StyleResolver::setFontSize(FontDescription& fontDescription, float size)
{
fontDescription.setSpecifiedSize(size);
fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
@@ -1795,9 +3284,9 @@ static Color colorForCSSValue(CSSValueID cssValueId)
return RenderTheme::defaultTheme()->systemColor(cssValueId);
}
-bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimitiveValue& value)
+bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue* value)
{
- int ident = value.getValueID();
+ int ident = value->getValueID();
switch (ident) {
case CSSValueWebkitText:
case CSSValueWebkitLink:
@@ -1809,13 +3298,13 @@ bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimiti
}
}
-Color StyleResolver::colorFromPrimitiveValue(const CSSPrimitiveValue& value, bool forVisitedLink) const
+Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const
{
- if (value.isRGBColor())
- return Color(value.getRGBA32Value());
+ if (value->isRGBColor())
+ return Color(value->getRGBA32Value());
const State& state = m_state;
- CSSValueID ident = value.getValueID();
+ CSSValueID ident = value->getValueID();
switch (ident) {
case 0:
return Color();
@@ -1839,7 +3328,7 @@ void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* ex
m_viewportDependentMediaQueryResults.append(std::make_unique<MediaQueryResult>(*expr, result));
}
-bool StyleResolver::hasMediaQueriesAffectedByViewportChange() const
+bool StyleResolver::affectedByViewportChange() const
{
unsigned s = m_viewportDependentMediaQueryResults.size();
for (unsigned i = 0; i < s; i++) {
@@ -1849,6 +3338,7 @@ bool StyleResolver::hasMediaQueriesAffectedByViewportChange() const
return false;
}
+#if ENABLE(CSS_FILTERS)
static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
{
switch (type) {
@@ -1880,6 +3370,7 @@ static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValu
return FilterOperation::NONE;
}
+#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
void StyleResolver::loadPendingSVGDocuments()
{
State& state = m_state;
@@ -1891,82 +3382,88 @@ void StyleResolver::loadPendingSVGDocuments()
if (!state.style() || !state.style()->hasFilter() || state.filtersWithPendingSVGDocuments().isEmpty())
return;
- ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
- options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
-
- CachedResourceLoader& cachedResourceLoader = state.document().cachedResourceLoader();
-
- for (auto& filterOperation : state.filtersWithPendingSVGDocuments())
- filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader, options);
+ CachedResourceLoader* cachedResourceLoader = state.document().cachedResourceLoader();
+ for (auto filterOperation : state.filtersWithPendingSVGDocuments())
+ filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader);
state.filtersWithPendingSVGDocuments().clear();
}
+#endif
-bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations)
+bool StyleResolver::createFilterOperations(CSSValue* inValue, FilterOperations& outOperations)
{
State& state = m_state;
+ RenderStyle* style = state.style();
+ RenderStyle* rootStyle = state.rootElementStyle();
ASSERT(outOperations.isEmpty());
- if (is<CSSPrimitiveValue>(inValue)) {
- auto& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
- if (primitiveValue.getValueID() == CSSValueNone)
+ if (!inValue)
+ return false;
+
+ if (inValue->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue);
+ if (primitiveValue->getValueID() == CSSValueNone)
return true;
}
- if (!is<CSSValueList>(inValue))
+ if (!inValue->isValueList())
return false;
+ float zoomFactor = style ? style->effectiveZoom() : 1;
FilterOperations operations;
- for (auto& currentValue : downcast<CSSValueList>(inValue)) {
- if (!is<WebKitCSSFilterValue>(currentValue.get()))
+ for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isWebKitCSSFilterValue())
continue;
- auto& filterValue = downcast<WebKitCSSFilterValue>(currentValue.get());
- FilterOperation::OperationType operationType = filterOperationForType(filterValue.operationType());
+ WebKitCSSFilterValue* filterValue = toWebKitCSSFilterValue(i.value());
+ FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType());
if (operationType == FilterOperation::REFERENCE) {
- if (filterValue.length() != 1)
+#if ENABLE(SVG)
+ if (filterValue->length() != 1)
continue;
- auto& argument = *filterValue.itemWithoutBoundsCheck(0);
+ CSSValue* argument = filterValue->itemWithoutBoundsCheck(0);
- if (!is<CSSPrimitiveValue>(argument))
+ if (!argument->isPrimitiveValue())
continue;
- auto& primitiveValue = downcast<CSSPrimitiveValue>(argument);
+ CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(*argument);
String cssUrl = primitiveValue.getStringValue();
URL url = m_state.document().completeURL(cssUrl);
- RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
+ RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier(), operationType);
if (SVGURIReference::isExternalURIReference(cssUrl, m_state.document()))
state.filtersWithPendingSVGDocuments().append(operation);
operations.operations().append(operation);
+#endif
continue;
}
// Check that all parameters are primitive values, with the
// exception of drop shadow which has a CSSShadowValue parameter.
- const CSSPrimitiveValue* firstValue = nullptr;
+ CSSPrimitiveValue* firstValue = nullptr;
if (operationType != FilterOperation::DROP_SHADOW) {
bool haveNonPrimitiveValue = false;
- for (unsigned j = 0; j < filterValue.length(); ++j) {
- if (!is<CSSPrimitiveValue>(*filterValue.itemWithoutBoundsCheck(j))) {
+ for (unsigned j = 0; j < filterValue->length(); ++j) {
+ if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
haveNonPrimitiveValue = true;
break;
}
}
if (haveNonPrimitiveValue)
continue;
- if (filterValue.length())
- firstValue = downcast<CSSPrimitiveValue>(filterValue.itemWithoutBoundsCheck(0));
+ if (filterValue->length())
+ firstValue = toCSSPrimitiveValue(filterValue->itemWithoutBoundsCheck(0));
}
- switch (filterValue.operationType()) {
+ switch (filterValue->operationType()) {
case WebKitCSSFilterValue::GrayscaleFilterOperation:
case WebKitCSSFilterValue::SepiaFilterOperation:
case WebKitCSSFilterValue::SaturateFilterOperation: {
double amount = 1;
- if (filterValue.length() == 1) {
+ if (filterValue->length() == 1) {
amount = firstValue->getDoubleValue();
if (firstValue->isPercentage())
amount /= 100;
@@ -1977,7 +3474,7 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
}
case WebKitCSSFilterValue::HueRotateFilterOperation: {
double angle = 0;
- if (filterValue.length() == 1)
+ if (filterValue->length() == 1)
angle = firstValue->computeDegrees();
operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
@@ -1987,8 +3484,8 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
case WebKitCSSFilterValue::BrightnessFilterOperation:
case WebKitCSSFilterValue::ContrastFilterOperation:
case WebKitCSSFilterValue::OpacityFilterOperation: {
- double amount = (filterValue.operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
- if (filterValue.length() == 1) {
+ double amount = (filterValue->operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
+ if (filterValue->length() == 1) {
amount = firstValue->getDoubleValue();
if (firstValue->isPercentage())
amount /= 100;
@@ -1999,32 +3496,38 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
}
case WebKitCSSFilterValue::BlurFilterOperation: {
Length stdDeviation = Length(0, Fixed);
- if (filterValue.length() >= 1)
- stdDeviation = convertToFloatLength(firstValue, state.cssToLengthConversionData());
+ if (filterValue->length() >= 1)
+ stdDeviation = convertToFloatLength(firstValue, style, rootStyle, zoomFactor);
if (stdDeviation.isUndefined())
return false;
- operations.operations().append(BlurFilterOperation::create(stdDeviation));
+ operations.operations().append(BlurFilterOperation::create(stdDeviation, operationType));
break;
}
case WebKitCSSFilterValue::DropShadowFilterOperation: {
- if (filterValue.length() != 1)
+ if (filterValue->length() != 1)
return false;
- auto& cssValue = *filterValue.itemWithoutBoundsCheck(0);
- if (!is<CSSShadowValue>(cssValue))
+ CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0);
+ if (!cssValue->isShadowValue())
continue;
- auto& item = downcast<CSSShadowValue>(cssValue);
- int x = item.x->computeLength<int>(state.cssToLengthConversionData());
- int y = item.y->computeLength<int>(state.cssToLengthConversionData());
+ CSSShadowValue* item = toCSSShadowValue(cssValue);
+ int x = item->x->computeLength<int>(style, rootStyle, zoomFactor);
+ if (item->x->isViewportPercentageLength())
+ x = viewportPercentageValue(*item->x, x);
+ int y = item->y->computeLength<int>(style, rootStyle, zoomFactor);
+ if (item->y->isViewportPercentageLength())
+ y = viewportPercentageValue(*item->y, y);
IntPoint location(x, y);
- int blur = item.blur ? item.blur->computeLength<int>(state.cssToLengthConversionData()) : 0;
+ int blur = item->blur ? item->blur->computeLength<int>(style, rootStyle, zoomFactor) : 0;
+ if (item->blur && item->blur->isViewportPercentageLength())
+ blur = viewportPercentageValue(*item->blur, blur);
Color color;
- if (item.color)
- color = colorFromPrimitiveValue(*item.color);
+ if (item->color)
+ color = colorFromPrimitiveValue(item->color.get());
- operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent));
+ operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent, operationType));
break;
}
case WebKitCSSFilterValue::UnknownFilterOperation:
@@ -2038,32 +3541,32 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
return true;
}
-PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options)
+#endif
+
+PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendingImage, const ResourceLoaderOptions& options)
{
- if (auto imageValue = pendingImage.cssImageValue())
+ if (auto imageValue = pendingImage->cssImageValue())
return imageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
- if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
- imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader(), options);
+ if (auto imageGeneratorValue = pendingImage->cssImageGeneratorValue()) {
+ imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader());
return StyleGeneratedImage::create(*imageGeneratorValue);
}
- if (auto cursorImageValue = pendingImage.cssCursorImageValue())
- return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
+ if (auto cursorImageValue = pendingImage->cssCursorImageValue())
+ return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader());
#if ENABLE(CSS_IMAGE_SET)
- if (auto imageSetValue = pendingImage.cssImageSetValue())
+ if (CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue())
return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader(), options);
#endif
return nullptr;
}
-PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage)
+PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendingImage)
{
- ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
- options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
- return loadPendingImage(pendingImage, options);
+ return loadPendingImage(pendingImage, CachedResourceLoader::defaultCachedResourceOptions());
}
#if ENABLE(CSS_SHAPES)
@@ -2073,15 +3576,14 @@ void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
return;
StyleImage* image = shapeValue->image();
- if (!is<StylePendingImage>(image))
+ if (!image || !image->isPendingImage())
return;
- auto& pendingImage = downcast<StylePendingImage>(*image);
+ StylePendingImage* pendingImage = static_cast<StylePendingImage*>(image);
ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
- options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled);
- options.setAllowCredentials(DoNotAllowStoredCredentials);
- options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
+ options.requestOriginPolicy = PotentiallyCrossOriginEnabled;
+ options.allowCredentials = DoNotAllowStoredCredentials;
shapeValue->setImage(loadPendingImage(pendingImage, options));
}
@@ -2089,9 +3591,6 @@ void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
void StyleResolver::loadPendingImages()
{
- RELEASE_ASSERT(!m_inLoadPendingImages);
- TemporaryChange<bool> changeInLoadPendingImages(m_inLoadPendingImages, true);
-
if (m_state.pendingImageProperties().isEmpty())
return;
@@ -2101,20 +3600,20 @@ void StyleResolver::loadPendingImages()
switch (currentProperty) {
case CSSPropertyBackgroundImage: {
- for (FillLayer* backgroundLayer = &m_state.style()->ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
- auto* styleImage = backgroundLayer->image();
- if (is<StylePendingImage>(styleImage))
- backgroundLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ for (FillLayer* backgroundLayer = m_state.style()->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
+ if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
+ backgroundLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(backgroundLayer->image())));
}
break;
}
case CSSPropertyContent: {
for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
- if (is<ImageContentData>(*contentData)) {
- auto& styleImage = downcast<ImageContentData>(*contentData).image();
- if (is<StylePendingImage>(styleImage)) {
- if (RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(styleImage)))
- downcast<ImageContentData>(*contentData).setImage(loadedImage.release());
+ if (contentData->isImage()) {
+ StyleImage* image = static_cast<ImageContentData*>(contentData)->image();
+ if (image->isPendingImage()) {
+ RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(image));
+ if (loadedImage)
+ static_cast<ImageContentData*>(contentData)->setImage(loadedImage.release());
}
}
}
@@ -2124,51 +3623,50 @@ void StyleResolver::loadPendingImages()
if (CursorList* cursorList = m_state.style()->cursors()) {
for (size_t i = 0; i < cursorList->size(); ++i) {
CursorData& currentCursor = cursorList->at(i);
- auto* styleImage = currentCursor.image();
- if (is<StylePendingImage>(styleImage))
- currentCursor.setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ if (StyleImage* image = currentCursor.image()) {
+ if (image->isPendingImage())
+ currentCursor.setImage(loadPendingImage(static_cast<StylePendingImage*>(image)));
+ }
}
}
break;
}
case CSSPropertyListStyleImage: {
- auto* styleImage = m_state.style()->listStyleImage();
- if (is<StylePendingImage>(styleImage))
- m_state.style()->setListStyleImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ if (m_state.style()->listStyleImage() && m_state.style()->listStyleImage()->isPendingImage())
+ m_state.style()->setListStyleImage(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->listStyleImage())));
break;
}
case CSSPropertyBorderImageSource: {
- auto* styleImage = m_state.style()->borderImageSource();
- if (is<StylePendingImage>(styleImage))
- m_state.style()->setBorderImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ if (m_state.style()->borderImageSource() && m_state.style()->borderImageSource()->isPendingImage())
+ m_state.style()->setBorderImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->borderImageSource())));
break;
}
case CSSPropertyWebkitBoxReflect: {
if (StyleReflection* reflection = m_state.style()->boxReflect()) {
const NinePieceImage& maskImage = reflection->mask();
- auto* styleImage = maskImage.image();
- if (is<StylePendingImage>(styleImage)) {
- RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(*styleImage));
+ if (maskImage.image() && maskImage.image()->isPendingImage()) {
+ RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(maskImage.image()));
reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
}
}
break;
}
case CSSPropertyWebkitMaskBoxImageSource: {
- auto* styleImage = m_state.style()->maskBoxImageSource();
- if (is<StylePendingImage>(styleImage))
- m_state.style()->setMaskBoxImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ if (m_state.style()->maskBoxImageSource() && m_state.style()->maskBoxImageSource()->isPendingImage())
+ m_state.style()->setMaskBoxImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->maskBoxImageSource())));
break;
}
case CSSPropertyWebkitMaskImage: {
- for (FillLayer* maskLayer = &m_state.style()->ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
- auto* styleImage = maskLayer->image();
- if (is<StylePendingImage>(styleImage))
- maskLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
+ for (FillLayer* maskLayer = m_state.style()->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+ if (maskLayer->image() && maskLayer->image()->isPendingImage())
+ maskLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(maskLayer->image())));
}
break;
}
#if ENABLE(CSS_SHAPES)
+ case CSSPropertyWebkitShapeInside:
+ loadPendingShapeImage(m_state.style()->shapeInside());
+ break;
case CSSPropertyWebkitShapeOutside:
loadPendingShapeImage(m_state.style()->shapeOutside());
break;
@@ -2203,8 +3701,10 @@ void StyleResolver::loadPendingResources()
// Start loading images referenced by this style.
loadPendingImages();
+#if ENABLE(CSS_FILTERS) && ENABLE(SVG)
// Start loading the SVG Documents referenced by this style.
loadPendingSVGDocuments();
+#endif
#ifndef NDEBUG
inLoadPendingResources = false;
@@ -2212,46 +3712,47 @@ void StyleResolver::loadPendingResources()
}
inline StyleResolver::MatchedProperties::MatchedProperties()
- : possiblyPaddedMember(nullptr)
+ : possiblyPaddedMember(0)
{
}
-StyleResolver::MatchedProperties::~MatchedProperties()
+inline StyleResolver::MatchedProperties::~MatchedProperties()
{
}
-StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
- : m_direction(direction)
- , m_writingMode(writingMode)
+int StyleResolver::viewportPercentageValue(CSSPrimitiveValue& unit, int percentage)
{
-}
+ int viewPortHeight = document().renderView()->viewportSize().height() * percentage / 100.0f;
+ int viewPortWidth = document().renderView()->viewportSize().width() * percentage / 100.0f;
-inline bool StyleResolver::CascadedProperties::hasProperty(CSSPropertyID id) const
-{
- ASSERT(id < m_propertyIsPresent.size());
- return m_propertyIsPresent[id];
-}
+ if (unit.isViewportPercentageHeight())
+ return viewPortHeight;
+ if (unit.isViewportPercentageWidth())
+ return viewPortWidth;
+ if (unit.isViewportPercentageMax())
+ return std::max(viewPortWidth, viewPortHeight);
+ if (unit.isViewportPercentageMin())
+ return std::min(viewPortWidth, viewPortHeight);
-inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id)
-{
- return m_properties[id];
+ ASSERT_NOT_REACHED();
+ return 0;
}
-inline bool StyleResolver::CascadedProperties::hasCustomProperty(const String& name) const
+StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
+ : m_direction(direction)
+ , m_writingMode(writingMode)
{
- return m_customProperties.contains(name);
}
-inline StyleResolver::CascadedProperties::Property StyleResolver::CascadedProperties::customProperty(const String& name) const
+inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id)
{
- return m_customProperties.get(name);
+ return m_properties[id];
}
-void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
+void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
{
ASSERT(linkMatchType <= SelectorChecker::MatchAll);
property.id = id;
- property.level = cascadeLevel;
if (linkMatchType == SelectorChecker::MatchAll) {
property.cssValue[0] = &cssValue;
property.cssValue[SelectorChecker::MatchLink] = &cssValue;
@@ -2260,7 +3761,7 @@ void StyleResolver::CascadedProperties::setPropertyInternal(Property& property,
property.cssValue[linkMatchType] = &cssValue;
}
-void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
+void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
{
if (CSSProperty::isDirectionAwareProperty(id))
id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
@@ -2268,52 +3769,35 @@ void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue
ASSERT(!shouldApplyPropertyInParseOrder(id));
auto& property = m_properties[id];
- ASSERT(id < m_propertyIsPresent.size());
- if (id == CSSPropertyCustom) {
- m_propertyIsPresent.set(id);
- const auto& customValue = downcast<CSSCustomPropertyValue>(cssValue);
- bool hasValue = customProperties().contains(customValue.name());
- if (!hasValue) {
- Property property;
- property.id = id;
- memset(property.cssValue, 0, sizeof(property.cssValue));
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
- customProperties().set(customValue.name(), property);
- } else {
- Property property = customProperties().get(customValue.name());
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
- customProperties().set(customValue.name(), property);
- }
- return;
- }
-
- if (!m_propertyIsPresent[id])
+ if (!m_propertyIsPresent.test(id))
memset(property.cssValue, 0, sizeof(property.cssValue));
m_propertyIsPresent.set(id);
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
+ setPropertyInternal(property, id, cssValue, linkMatchType);
}
-void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
+void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
{
ASSERT(!CSSProperty::isDirectionAwareProperty(id));
ASSERT(shouldApplyPropertyInParseOrder(id));
Property property;
memset(property.cssValue, 0, sizeof(property.cssValue));
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
+ setPropertyInternal(property, id, cssValue, linkMatchType);
m_deferredProperties.append(property);
}
-void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType, CascadeLevel cascadeLevel)
+bool StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType)
{
for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
auto current = properties.propertyAt(i);
if (isImportant != current.isImportant())
continue;
if (inheritedOnly && !current.isInherited()) {
- // We apply the inherited properties only when using the property cache.
- // A match with a value that is explicitely inherited should never have been cached.
- ASSERT(!current.value()->isInheritedValue());
+ // If the property value is explicitly inherited, we need to apply further non-inherited properties
+ // as they might override the value inherited here. For this reason we don't allow declarations with
+ // explicitly inherited properties to be cached.
+ if (current.value()->isInheritedValue())
+ return false;
continue;
}
CSSPropertyID propertyID = current.id();
@@ -2326,48 +3810,47 @@ void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties
#endif
if (shouldApplyPropertyInParseOrder(propertyID))
- setDeferred(propertyID, *current.value(), linkMatchType, cascadeLevel);
+ setDeferred(propertyID, *current.value(), linkMatchType);
else
- set(propertyID, *current.value(), linkMatchType, cascadeLevel);
+ set(propertyID, *current.value(), linkMatchType);
}
+ return true;
}
-static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult& matchResult, int index)
-{
- if (index >= matchResult.ranges.firstUARule && index <= matchResult.ranges.lastUARule)
- return UserAgentLevel;
- if (index >= matchResult.ranges.firstUserRule && index <= matchResult.ranges.lastUserRule)
- return UserLevel;
- return AuthorLevel;
-}
-
-void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly)
+bool StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly)
{
if (startIndex == -1)
- return;
+ return true;
for (int i = startIndex; i <= endIndex; ++i) {
- const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i];
- addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType,
- cascadeLevelForIndex(matchResult, i));
+ const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
+ if (!addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType))
+ return false;
}
+ return true;
}
-void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, const MatchResult* matchResult)
+void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver)
{
for (auto& property : m_deferredProperties)
- property.apply(resolver, matchResult);
+ property.apply(resolver);
}
-void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, const MatchResult* matchResult)
+void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver)
{
State& state = resolver.state();
- state.setCascadeLevel(level);
- if (cssValue[SelectorChecker::MatchDefault]) {
+ // FIXME: It would be nice if line-height were less of a special snowflake.
+ if (id == CSSPropertyLineHeight) {
+ if (auto value = state.style()->insideLink() == NotInsideLink ? cssValue[0] : cssValue[SelectorChecker::MatchLink])
+ state.setLineHeightValue(value);
+ return;
+ }
+
+ if (cssValue[0]) {
state.setApplyPropertyToRegularStyle(true);
state.setApplyPropertyToVisitedLinkStyle(false);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], SelectorChecker::MatchDefault, matchResult);
+ resolver.applyProperty(id, cssValue[0]);
}
if (state.style()->insideLink() == NotInsideLink)
@@ -2376,38 +3859,29 @@ void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver,
if (cssValue[SelectorChecker::MatchLink]) {
state.setApplyPropertyToRegularStyle(true);
state.setApplyPropertyToVisitedLinkStyle(false);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], SelectorChecker::MatchLink, matchResult);
+ resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink]);
}
if (cssValue[SelectorChecker::MatchVisited]) {
state.setApplyPropertyToRegularStyle(false);
state.setApplyPropertyToVisitedLinkStyle(true);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], SelectorChecker::MatchVisited, matchResult);
+ resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited]);
}
state.setApplyPropertyToRegularStyle(true);
state.setApplyPropertyToVisitedLinkStyle(false);
}
-void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty, const MatchResult* matchResult)
+void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty)
{
for (int id = firstProperty; id <= lastProperty; ++id) {
CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
if (!cascade.hasProperty(propertyID))
continue;
- if (propertyID == CSSPropertyCustom) {
- HashMap<AtomicString, CascadedProperties::Property>::iterator end = cascade.customProperties().end();
- for (HashMap<AtomicString, CascadedProperties::Property>::iterator it = cascade.customProperties().begin(); it != end; ++it)
- it->value.apply(*this, matchResult);
- continue;
- }
auto& property = cascade.property(propertyID);
ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
- property.apply(*this, matchResult);
+ property.apply(*this);
}
-
- if (firstProperty == CSSPropertyCustom)
- m_state.style()->checkVariablesInCustomProperties();
}
} // namespace WebCore