[LFC] Set the invalidation root as the result of style change.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 May 2018 16:30:27 +0000 (16:30 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 May 2018 16:30:27 +0000 (16:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185301

Reviewed by Antti Koivisto.

Compute/propagate the update type on the ancestor chain and return the invalidation root
so that LayoutContext could use it as the entry point for the next layout frame.

* layout/LayoutContext.cpp:
(WebCore::Layout::LayoutContext::updateLayout):
(WebCore::Layout::LayoutContext::styleChanged):
* layout/LayoutContext.h: order is not important.
* layout/blockformatting/BlockInvalidation.cpp:
(WebCore::Layout::invalidationStopsAtFormattingContextBoundary):
(WebCore::Layout::computeUpdateType):
(WebCore::Layout::computeUpdateTypeForAncestor):
(WebCore::Layout::BlockInvalidation::invalidate):
* layout/blockformatting/BlockInvalidation.h:
* layout/inlineformatting/InlineInvalidation.cpp:
(WebCore::Layout::InlineInvalidation::invalidate):
* layout/inlineformatting/InlineInvalidation.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231355 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/layout/Invalidation.h [new file with mode: 0644]
Source/WebCore/layout/LayoutContext.cpp
Source/WebCore/layout/LayoutContext.h
Source/WebCore/layout/blockformatting/BlockInvalidation.cpp
Source/WebCore/layout/blockformatting/BlockInvalidation.h
Source/WebCore/layout/inlineformatting/InlineInvalidation.cpp
Source/WebCore/layout/inlineformatting/InlineInvalidation.h

index 9283c97..01554fd 100644 (file)
@@ -1,3 +1,27 @@
+2018-05-04  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC] Set the invalidation root as the result of style change.
+        https://bugs.webkit.org/show_bug.cgi?id=185301
+
+        Reviewed by Antti Koivisto.
+
+        Compute/propagate the update type on the ancestor chain and return the invalidation root
+        so that LayoutContext could use it as the entry point for the next layout frame.
+
+        * layout/LayoutContext.cpp:
+        (WebCore::Layout::LayoutContext::updateLayout):
+        (WebCore::Layout::LayoutContext::styleChanged):
+        * layout/LayoutContext.h: order is not important.
+        * layout/blockformatting/BlockInvalidation.cpp:
+        (WebCore::Layout::invalidationStopsAtFormattingContextBoundary):
+        (WebCore::Layout::computeUpdateType):
+        (WebCore::Layout::computeUpdateTypeForAncestor):
+        (WebCore::Layout::BlockInvalidation::invalidate):
+        * layout/blockformatting/BlockInvalidation.h:
+        * layout/inlineformatting/InlineInvalidation.cpp:
+        (WebCore::Layout::InlineInvalidation::invalidate):
+        * layout/inlineformatting/InlineInvalidation.h:
+
 2018-05-04  Youenn Fablet  <youenn@apple.com>
 
         PeerConnection should have its connectionState closed even if doing gathering
index bf68d47..82efaea 100644 (file)
                115CFA89208B921A001E6991 /* BlockMarginCollapse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockMarginCollapse.cpp; sourceTree = "<group>"; };
                115CFA95208B952B001E6991 /* LayoutBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutBox.h; sourceTree = "<group>"; };
                115CFA96208B952B001E6991 /* LayoutBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutBox.cpp; sourceTree = "<group>"; };
+               115F7805209CBCBD00739C13 /* Invalidation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Invalidation.h; sourceTree = "<group>"; };
                119340761FE8B92300935F1E /* RenderTreeBuilderTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderTable.cpp; sourceTree = "<group>"; };
                119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderTable.h; sourceTree = "<group>"; };
                119340871FEB355D00935F1E /* RenderTreeBuilderRuby.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderRuby.cpp; sourceTree = "<group>"; };
                                115CFA68208AF7D0001E6991 /* FormattingContext.h */,
                                115CFA75208AFE30001E6991 /* FormattingState.cpp */,
                                115CFA74208AFE30001E6991 /* FormattingState.h */,
+                               115F7805209CBCBD00739C13 /* Invalidation.h */,
                                6F7CA3C5208C2956002F29AB /* LayoutContext.cpp */,
                                6F7CA3C4208C2956002F29AB /* LayoutContext.h */,
                        );
diff --git a/Source/WebCore/layout/Invalidation.h b/Source/WebCore/layout/Invalidation.h
new file mode 100644 (file)
index 0000000..e0dbf78
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+class Container;
+
+struct InvalidationResult {
+    const Container* root;
+};
+
+}
+}
+#endif
index 32d89ce..6089494 100644 (file)
@@ -35,6 +35,7 @@
 #include "InlineFormattingContext.h"
 #include "InlineFormattingState.h"
 #include "InlineInvalidation.h"
+#include "Invalidation.h"
 #include "LayoutBox.h"
 #include "LayoutContainer.h"
 #include <wtf/IsoMallocInlines.h>
@@ -52,8 +53,7 @@ LayoutContext::LayoutContext(const Box& root)
 void LayoutContext::updateLayout()
 {
     ASSERT(!m_formattingContextRootListForLayout.isEmpty());
-    for (auto layoutRoot : m_formattingContextRootListForLayout) {
-        RELEASE_ASSERT(layoutRoot.get());
+    for (auto* layoutRoot : m_formattingContextRootListForLayout) {
         RELEASE_ASSERT(layoutRoot->establishesFormattingContext());
         auto context = formattingContext(*layoutRoot);
         auto& state = establishedFormattingState(*layoutRoot, *context);
@@ -73,12 +73,15 @@ Display::Box& LayoutContext::createDisplayBox(const Box& layoutBox)
 void LayoutContext::styleChanged(const Box& layoutBox, StyleDiff styleDiff)
 {
     auto& formattingState = formattingStateForBox(layoutBox);
+    const Container* invalidationRoot = nullptr;
     if (is<BlockFormattingState>(formattingState))
-        BlockInvalidation::invalidate(layoutBox, styleDiff, *this, downcast<BlockFormattingState>(formattingState));
+        invalidationRoot = BlockInvalidation::invalidate(layoutBox, styleDiff, *this, downcast<BlockFormattingState>(formattingState)).root;
     else if (is<InlineFormattingState>(formattingState))
-        InlineInvalidation::invalidate(layoutBox, styleDiff, *this, downcast<InlineFormattingState>(formattingState));
+        invalidationRoot = InlineInvalidation::invalidate(layoutBox, styleDiff, *this, downcast<InlineFormattingState>(formattingState)).root;
     else
         ASSERT_NOT_REACHED();
+    ASSERT(invalidationRoot);
+    m_formattingContextRootListForLayout.addVoid(invalidationRoot);
 }
 
 void LayoutContext::markNeedsUpdate(const Box&, OptionSet<UpdateType>)
index fe23062..01d92da 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "FormattingContext.h"
 #include "FormattingState.h"
-#include "LayoutBox.h"
+#include <wtf/HashSet.h>
 #include <wtf/IsoMalloc.h>
 #include <wtf/OptionSet.h>
 
@@ -42,6 +42,8 @@ class Box;
 namespace Layout {
 
 enum class StyleDiff;
+class Box;
+class Container;
 
 // LayoutContext is the entry point for layout. It takes a (formatting root)container which acts as the root of the layout context.
 // LayoutContext::layout() generates the display tree for the root container's subtree (it does not run layout on the root though).
@@ -76,7 +78,7 @@ public:
 
 private:
     WeakPtr<Box> m_root;
-    Vector<WeakPtr<Box>> m_formattingContextRootListForLayout;
+    HashSet<const Container*> m_formattingContextRootListForLayout;
     HashMap<const Box*, std::unique_ptr<FormattingState>> m_formattingStates;
     HashMap<const Box*, std::unique_ptr<Display::Box>> m_layoutToDisplayBox;
 };
index 652afab..7e151a1 100644 (file)
@@ -29,7 +29,9 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "BlockFormattingState.h"
+#include "Invalidation.h"
 #include "LayoutBox.h"
+#include "LayoutContainer.h"
 #include "LayoutContext.h"
 #include <wtf/IsoMallocInlines.h>
 
@@ -38,9 +40,35 @@ namespace Layout {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(BlockInvalidation);
 
-void BlockInvalidation::invalidate(const Box& layoutBox, StyleDiff, LayoutContext& layoutContext, BlockFormattingState&)
+static bool invalidationStopsAtFormattingContextBoundary(const Container& formattingContextRoot, const Box&, StyleDiff)
 {
-    layoutContext.markNeedsUpdate(layoutBox, LayoutContext::UpdateType::All);
+    ASSERT(formattingContextRoot.establishesFormattingContext());
+    return true;
+}
+
+static LayoutContext::UpdateType computeUpdateType(const Box&, StyleDiff, BlockFormattingState&)
+{
+    return LayoutContext::UpdateType::All;
+}
+
+static LayoutContext::UpdateType computeUpdateTypeForAncestor(const Container&, StyleDiff, BlockFormattingState&)
+{
+    return LayoutContext::UpdateType::All;
+}
+
+InvalidationResult BlockInvalidation::invalidate(const Box& layoutBox, StyleDiff styleDiff, LayoutContext& layoutContext,
+    BlockFormattingState& formattingState)
+{
+    // Invalidate this box and the containing block chain all the way up to the formatting context root (and beyond if needed).
+    layoutContext.markNeedsUpdate(layoutBox, computeUpdateType(layoutBox, styleDiff, formattingState));
+    for (auto* containingBlock = layoutBox.containingBlock(); containingBlock; containingBlock = containingBlock->containingBlock()) {
+        if (containingBlock->establishesFormattingContext() && invalidationStopsAtFormattingContextBoundary(*containingBlock, layoutBox, styleDiff))
+            return { containingBlock };
+        layoutContext.markNeedsUpdate(*containingBlock, computeUpdateTypeForAncestor(*containingBlock, styleDiff, formattingState));
+    }
+    // Invalidation always stops at the initial containing block.
+    ASSERT_NOT_REACHED();
+    return { nullptr };
 }
 
 }
index 5ef1436..aed44e0 100644 (file)
@@ -35,6 +35,8 @@ namespace Layout {
 
 class Box;
 class BlockFormattingState;
+class Container;
+struct InvalidationResult;
 class LayoutContext;
 enum class StyleDiff;
 
@@ -42,7 +44,7 @@ enum class StyleDiff;
 class BlockInvalidation {
     WTF_MAKE_ISO_ALLOCATED(BlockInvalidation);
 public:
-    static void invalidate(const Box&, StyleDiff, LayoutContext&, BlockFormattingState&);
+    static InvalidationResult invalidate(const Box&, StyleDiff, LayoutContext&, BlockFormattingState&);
 };
 
 }
index b18826f..645b54d 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "InlineFormattingState.h"
+#include "Invalidation.h"
 #include "LayoutBox.h"
 #include "LayoutContext.h"
 #include <wtf/IsoMallocInlines.h>
@@ -38,9 +39,10 @@ namespace Layout {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(InlineInvalidation);
 
-void InlineInvalidation::invalidate(const Box& layoutBox, StyleDiff, LayoutContext& layoutContext, InlineFormattingState&)
+InvalidationResult InlineInvalidation::invalidate(const Box& layoutBox, StyleDiff, LayoutContext& layoutContext, InlineFormattingState&)
 {
     layoutContext.markNeedsUpdate(layoutBox, LayoutContext::UpdateType::All);
+    return { nullptr };
 }
 
 }
index 257c367..d755565 100644 (file)
@@ -34,7 +34,9 @@ namespace WebCore {
 namespace Layout {
 
 class Box;
+class Container;
 class InlineFormattingState;
+struct InvalidationResult;
 class LayoutContext;
 enum class StyleDiff;
 
@@ -42,7 +44,7 @@ enum class StyleDiff;
 class InlineInvalidation {
     WTF_MAKE_ISO_ALLOCATED(InlineInvalidation);
 public:
-    static void invalidate(const Box&, StyleDiff, LayoutContext&, InlineFormattingState&);
+    static InvalidationResult invalidate(const Box&, StyleDiff, LayoutContext&, InlineFormattingState&);
 };
 
 }