Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(663)

Unified Diff: Source/core/css/invalidation/StyleInvalidator.cpp

Issue 204873003: Factor the style invalidation tree walk out of RuleFeatureSet, and make it generic. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added explicit. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/css/invalidation/StyleInvalidator.h ('k') | Source/core/dom/Document.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/invalidation/StyleInvalidator.cpp
diff --git a/Source/core/css/invalidation/StyleInvalidator.cpp b/Source/core/css/invalidation/StyleInvalidator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..710993a51aa685350679ffb4a04e75f74d696234
--- /dev/null
+++ b/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -0,0 +1,128 @@
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "core/css/invalidation/StyleInvalidator.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementTraversal.h"
+#include "core/dom/shadow/ElementShadow.h"
+#include "core/dom/shadow/ShadowRoot.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+void StyleInvalidator::invalidate()
+{
+ if (Element* documentElement = m_document.documentElement()) {
+ if (documentElement->childNeedsStyleInvalidation())
+ invalidate(*documentElement);
+ }
+ m_document.clearChildNeedsStyleInvalidation();
+ m_document.clearNeedsStyleInvalidation();
+ m_pendingInvalidationMap.clear();
+}
+
+StyleInvalidator::StyleInvalidator(Document& document)
+ : m_document(document)
+ , m_pendingInvalidationMap(document.styleResolver()->ruleFeatureSet().pendingInvalidationMap())
+{ }
+
+void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvalidationSet& invalidationSet)
+{
+ invalidationSet.getClasses(m_invalidationClasses);
+ m_foundInvalidationSet = true;
+}
+
+bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& element)
+{
+ if (!element.hasClass())
+ return false;
+
+ const SpaceSplitString& classNames = element.classNames();
+ for (Vector<AtomicString>::const_iterator it = m_invalidationClasses.begin(); it != m_invalidationClasses.end(); ++it) {
+ if (classNames.contains(*it))
+ return true;
+ }
+
+ return false;
+}
+
+bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element)
+{
+ bool thisElementNeedsStyleRecalc = false;
+ if (element.needsStyleInvalidation()) {
+ if (RuleFeatureSet::InvalidationList* invalidationList = m_pendingInvalidationMap.get(&element)) {
+ // FIXME: it's really only necessary to clone the render style for this element, not full style recalc.
+ thisElementNeedsStyleRecalc = true;
+ for (RuleFeatureSet::InvalidationList::const_iterator it = invalidationList->begin(); it != invalidationList->end(); ++it) {
+ m_recursionData.pushInvalidationSet(**it);
+ if ((*it)->wholeSubtreeInvalid()) {
+ element.setNeedsStyleRecalc(SubtreeStyleChange);
+ // Even though we have set needsStyleRecalc on the whole subtree, we need to keep walking over the subtree
+ // in order to clear the invalidation dirty bits on all elements.
+ // FIXME: we can optimize this by having a dedicated function that just traverses the tree and removes the dirty bits,
+ // without checking classes etc.
+ break;
+ }
+ }
+ }
+ }
+ if (!thisElementNeedsStyleRecalc)
+ thisElementNeedsStyleRecalc = m_recursionData.matchesCurrentInvalidationSets(element);
+ return thisElementNeedsStyleRecalc;
+}
+
+bool StyleInvalidator::invalidateChildren(Element& element)
+{
+ bool someChildrenNeedStyleRecalc = false;
+ for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+ for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) {
+ bool childRecalced = invalidate(*child);
+ someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
+ }
+ root->clearChildNeedsStyleInvalidation();
+ root->clearNeedsStyleInvalidation();
+ }
+ for (Element* child = ElementTraversal::firstWithin(element); child; child = ElementTraversal::nextSibling(*child)) {
+ bool childRecalced = invalidate(*child);
+ someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
+ }
+ return someChildrenNeedStyleRecalc;
+}
+
+bool StyleInvalidator::invalidate(Element& element)
+{
+ RecursionCheckpoint checkpoint(&m_recursionData);
+
+ bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(element);
+
+ bool someChildrenNeedStyleRecalc = false;
+ // foundInvalidationSet() will be true if we are in a subtree of a node with a DescendantInvalidationSet on it.
+ // We need to check all nodes in the subtree of such a node.
+ if (m_recursionData.foundInvalidationSet() || element.childNeedsStyleInvalidation())
+ someChildrenNeedStyleRecalc = invalidateChildren(element);
+
+ if (thisElementNeedsStyleRecalc) {
+ element.setNeedsStyleRecalc(LocalStyleChange);
+ } else if (m_recursionData.foundInvalidationSet() && someChildrenNeedStyleRecalc) {
+ // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style.
+ if (RenderObject* renderer = element.renderer()) {
+ ASSERT(renderer->style());
+ renderer->setStyleInternal(RenderStyle::clone(renderer->style()));
+ } else {
+ element.setNeedsStyleRecalc(LocalStyleChange);
+ }
+ }
+
+ element.clearChildNeedsStyleInvalidation();
+ element.clearNeedsStyleInvalidation();
+
+ return thisElementNeedsStyleRecalc;
+}
+
+} // namespace WebCore
« no previous file with comments | « Source/core/css/invalidation/StyleInvalidator.h ('k') | Source/core/dom/Document.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698