Move style recalculation out from Element
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2013 12:02:04 +0000 (12:02 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2013 12:02:04 +0000 (12:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=119497

Reviewed by Andreas Kling.

Element currently does too much. Element::recalcStyle() and the related functions can be turned into
standalone functions that operate on DOM tree. This will also give more freedom for future refactoring,
for example making style recalculation non-recursive.

* WebCore.xcodeproj/project.pbxproj:
* css/StyleResolveTree.cpp: Added.
(WebCore::Style::determineChange):

    - moved and renamed from Node::diff
    - factored to use early return style
    - simplifield the null input logic

(WebCore::Style::pseudoStyleCacheIsInvalid):

    - moved from Element::pseudoStyleCacheIsInvalid
    - narrowed to take RenderObject rather than operate on Element

(WebCore::Style::resolveLocal):

    - split from Element::recalcStyle
    - factored to use early return style

(WebCore::Style::resolveTree):

    - moved and renamed from Element::recalcStyle

* css/StyleResolveTree.h: Added.

    - introcuduce Style namespace for style related classes and functions
    - move and rename Node::StyleChange -> Style::Change

* css/StyleResolver.h:
(WebCore::StyleResolverParentPusher::StyleResolverParentPusher):
(WebCore::StyleResolverParentPusher::push):
(WebCore::StyleResolverParentPusher::~StyleResolverParentPusher):

    Moved this stack helper to StyleResolver.h for now since it is needed by both
    StyleRecalculation and Element.

* dom/Document.cpp:
(WebCore::Document::recalcStyle):
(WebCore::Document::updateStyleIfNeeded):
(WebCore::Document::updateLayoutIgnorePendingStylesheets):
(WebCore::Document::attach):
(WebCore::Document::styleResolverChanged):
(WebCore::Document::webkitWillEnterFullScreenForElement):
* dom/Document.h:
* dom/Element.cpp:
(WebCore::shouldIgnoreAttributeCase):
(WebCore::Element::updatePseudoElement):
(WebCore::Element::resetComputedStyle):
(WebCore::Element::willRecalcStyle):
(WebCore::Element::didRecalcStyle):
* dom/Element.h:

    - remove Element::recalcStyle
    - make a few private functions needed by StyleRecalculation public

* dom/ElementShadow.cpp:
(WebCore::ElementShadow::recalcStyle):
* dom/ElementShadow.h:
* dom/Node.cpp:
* dom/Node.h:

    - remove Node::StyleChange
    - remove Node::diff

* dom/PseudoElement.cpp:
(WebCore::PseudoElement::didRecalcStyle):
* dom/PseudoElement.h:
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::recalcStyle):
(WebCore::ShadowRoot::setResetStyleInheritance):
* dom/ShadowRoot.h:
* dom/Text.cpp:
(WebCore::Text::recalcTextStyle):
* dom/Text.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::didRecalcStyle):
* html/HTMLFormControlElement.h:
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::willRecalcStyle):
* html/HTMLFrameSetElement.h:
* html/HTMLIFrameElement.cpp:
(WebCore::HTMLIFrameElement::didRecalcStyle):
* html/HTMLIFrameElement.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didRecalcStyle):
* html/HTMLMediaElement.h:
* html/HTMLOptionElement.cpp:
(WebCore::HTMLOptionElement::didRecalcStyle):
* html/HTMLOptionElement.h:
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::willRecalcStyle):
(WebCore::HTMLPlugInImageElement::documentWillSuspendForPageCache):
(WebCore::HTMLPlugInImageElement::documentDidResumeFromPageCache):
* html/HTMLPlugInImageElement.h:
* inspector/InspectorOverlay.cpp:
(WebCore::InspectorOverlay::update):
* loader/DocumentWriter.cpp:
(WebCore::DocumentWriter::reportDataReceived):
* page/Frame.cpp:
(WebCore::Frame::setPageAndTextZoomFactors):
* page/Page.cpp:
(WebCore::Page::setPageScaleFactor):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::updateFirstLetterStyle):
* svg/SVGElement.cpp:
(WebCore::SVGElement::willRecalcStyle):
* svg/SVGElement.h:
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::willRecalcStyle):
* svg/SVGUseElement.h:

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

44 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/StyleResolveTree.cpp [new file with mode: 0644]
Source/WebCore/css/StyleResolveTree.h [new file with mode: 0644]
Source/WebCore/css/StyleResolver.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementShadow.cpp
Source/WebCore/dom/ElementShadow.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/PseudoElement.cpp
Source/WebCore/dom/PseudoElement.h
Source/WebCore/dom/ShadowRoot.cpp
Source/WebCore/dom/ShadowRoot.h
Source/WebCore/dom/Text.cpp
Source/WebCore/dom/Text.h
Source/WebCore/html/HTMLFormControlElement.cpp
Source/WebCore/html/HTMLFormControlElement.h
Source/WebCore/html/HTMLFrameSetElement.cpp
Source/WebCore/html/HTMLFrameSetElement.h
Source/WebCore/html/HTMLIFrameElement.cpp
Source/WebCore/html/HTMLIFrameElement.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/HTMLOptionElement.cpp
Source/WebCore/html/HTMLOptionElement.h
Source/WebCore/html/HTMLPlugInImageElement.cpp
Source/WebCore/html/HTMLPlugInImageElement.h
Source/WebCore/inspector/InspectorOverlay.cpp
Source/WebCore/loader/DocumentWriter.cpp
Source/WebCore/page/Frame.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/SVGUseElement.h

index 4f465d7..47ca82d 100644 (file)
@@ -1091,6 +1091,7 @@ set(WebCore_SOURCES
     css/StylePropertySet.cpp
     css/StylePropertyShorthand.cpp
     css/StyleResolver.cpp
+    css/StyleResolveTree.cpp
     css/StyleRule.cpp
     css/StyleRuleImport.cpp
     css/StyleScopeResolver.cpp
index 5115fbe..671a135 100644 (file)
@@ -1,3 +1,124 @@
+2013-08-07  Antti Koivisto  <antti@apple.com>
+
+        Move style recalculation out from Element
+        https://bugs.webkit.org/show_bug.cgi?id=119497
+
+        Reviewed by Andreas Kling.
+
+        Element currently does too much. Element::recalcStyle() and the related functions can be turned into
+        standalone functions that operate on DOM tree. This will also give more freedom for future refactoring,
+        for example making style recalculation non-recursive.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/StyleResolveTree.cpp: Added.
+        (WebCore::Style::determineChange):
+                
+            - moved and renamed from Node::diff
+            - factored to use early return style
+            - simplifield the null input logic
+
+        (WebCore::Style::pseudoStyleCacheIsInvalid):
+        
+            - moved from Element::pseudoStyleCacheIsInvalid
+            - narrowed to take RenderObject rather than operate on Element
+
+        (WebCore::Style::resolveLocal):
+        
+            - split from Element::recalcStyle
+            - factored to use early return style
+
+        (WebCore::Style::resolveTree):
+        
+            - moved and renamed from Element::recalcStyle
+
+        * css/StyleResolveTree.h: Added.
+        
+            - introcuduce Style namespace for style related classes and functions
+            - move and rename Node::StyleChange -> Style::Change
+
+        * css/StyleResolver.h:
+        (WebCore::StyleResolverParentPusher::StyleResolverParentPusher):
+        (WebCore::StyleResolverParentPusher::push):
+        (WebCore::StyleResolverParentPusher::~StyleResolverParentPusher):
+        
+            Moved this stack helper to StyleResolver.h for now since it is needed by both
+            StyleRecalculation and Element.
+
+        * dom/Document.cpp:
+        (WebCore::Document::recalcStyle):
+        (WebCore::Document::updateStyleIfNeeded):
+        (WebCore::Document::updateLayoutIgnorePendingStylesheets):
+        (WebCore::Document::attach):
+        (WebCore::Document::styleResolverChanged):
+        (WebCore::Document::webkitWillEnterFullScreenForElement):
+        * dom/Document.h:
+        * dom/Element.cpp:
+        (WebCore::shouldIgnoreAttributeCase):
+        (WebCore::Element::updatePseudoElement):
+        (WebCore::Element::resetComputedStyle):
+        (WebCore::Element::willRecalcStyle):
+        (WebCore::Element::didRecalcStyle):
+        * dom/Element.h:
+        
+            - remove Element::recalcStyle
+            - make a few private functions needed by StyleRecalculation public
+
+        * dom/ElementShadow.cpp:
+        (WebCore::ElementShadow::recalcStyle):
+        * dom/ElementShadow.h:
+        * dom/Node.cpp:
+        * dom/Node.h:
+
+            - remove Node::StyleChange
+            - remove Node::diff
+
+        * dom/PseudoElement.cpp:
+        (WebCore::PseudoElement::didRecalcStyle):
+        * dom/PseudoElement.h:
+        * dom/ShadowRoot.cpp:
+        (WebCore::ShadowRoot::recalcStyle):
+        (WebCore::ShadowRoot::setResetStyleInheritance):
+        * dom/ShadowRoot.h:
+        * dom/Text.cpp:
+        (WebCore::Text::recalcTextStyle):
+        * dom/Text.h:
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::didRecalcStyle):
+        * html/HTMLFormControlElement.h:
+        * html/HTMLFrameSetElement.cpp:
+        (WebCore::HTMLFrameSetElement::willRecalcStyle):
+        * html/HTMLFrameSetElement.h:
+        * html/HTMLIFrameElement.cpp:
+        (WebCore::HTMLIFrameElement::didRecalcStyle):
+        * html/HTMLIFrameElement.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::didRecalcStyle):
+        * html/HTMLMediaElement.h:
+        * html/HTMLOptionElement.cpp:
+        (WebCore::HTMLOptionElement::didRecalcStyle):
+        * html/HTMLOptionElement.h:
+        * html/HTMLPlugInImageElement.cpp:
+        (WebCore::HTMLPlugInImageElement::willRecalcStyle):
+        (WebCore::HTMLPlugInImageElement::documentWillSuspendForPageCache):
+        (WebCore::HTMLPlugInImageElement::documentDidResumeFromPageCache):
+        * html/HTMLPlugInImageElement.h:
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::InspectorOverlay::update):
+        * loader/DocumentWriter.cpp:
+        (WebCore::DocumentWriter::reportDataReceived):
+        * page/Frame.cpp:
+        (WebCore::Frame::setPageAndTextZoomFactors):
+        * page/Page.cpp:
+        (WebCore::Page::setPageScaleFactor):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::updateFirstLetterStyle):
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::willRecalcStyle):
+        * svg/SVGElement.h:
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::willRecalcStyle):
+        * svg/SVGUseElement.h:
+
 2013-08-07  Mihnea Ovidenie  <mihnea@adobe.com>
 
         [CSSRegions] Wrong auto-height region computation for nested named flows
index 6342026..b481c03 100644 (file)
@@ -2751,6 +2751,8 @@ webcore_sources += \
        Source/WebCore/css/StylePropertyShorthand.h \
        Source/WebCore/css/StyleResolver.cpp \
        Source/WebCore/css/StyleResolver.h \
+       Source/WebCore/css/StyleResolveTree.cpp \
+       Source/WebCore/css/StyleResolveTree.h \
        Source/WebCore/css/StyleRule.cpp \
        Source/WebCore/css/StyleRule.h \
        Source/WebCore/css/StyleRuleImport.cpp \
index 7112aaf..d1d57e1 100644 (file)
@@ -333,6 +333,7 @@ SOURCES += \
     css/StylePropertySet.cpp \
     css/StylePropertyShorthand.cpp \
     css/StyleResolver.cpp \
+    css/StyleResolveTree.cpp \
     css/StyleRule.cpp \
     css/StyleRuleImport.cpp \
     css/StyleScopeResolver.cpp \
@@ -1542,6 +1543,7 @@ HEADERS += \
     css/StylePropertySet.h \
     css/StylePropertyShorthand.h \
     css/StyleResolver.h \
+    css/StyleResolveTree.h \
     css/StyleRule.h \
     css/StyleRuleImport.h \
     css/StyleSheet.h \
index d7087c2..678a8b7 100644 (file)
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\css\StyleResolveTree.cpp" />
     <ClCompile Include="..\css\StyleRule.cpp" />
     <ClCompile Include="..\css\StyleRuleImport.cpp" />
     <ClCompile Include="..\css\StyleSheet.cpp" />
     <ClInclude Include="..\css\StylePropertySet.h" />
     <ClInclude Include="..\css\StylePropertyShorthand.h" />
     <ClInclude Include="..\css\StyleResolver.h" />
+    <ClInclude Include="..\css\StyleResolveTree.h" />
     <ClInclude Include="..\css\StyleRule.h" />
     <ClInclude Include="..\css\StyleRuleImport.h" />
     <ClInclude Include="..\css\StyleSheet.h" />
index 3d1b8d0..53ec43a 100644 (file)
                E4C279590CF9741900E97B98 /* RenderMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C279570CF9741900E97B98 /* RenderMedia.h */; };
                E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */; };
                E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */; };
+               E4DEAA1717A93DC3000E0430 /* StyleResolveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */; };
+               E4DEAA1817A93DC3000E0430 /* StyleResolveTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E4DEAA1617A93DC3000E0430 /* StyleResolveTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4F9EEF2156D9FFA00D23E7E /* StyleSheetContents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */; };
                E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */; };
                E51A81DF17298D7700BFCA61 /* JSPerformance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E51A81DE17298D7700BFCA61 /* JSPerformance.cpp */; };
                E4C279570CF9741900E97B98 /* RenderMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMedia.h; sourceTree = "<group>"; };
                E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PurgeableBufferMac.cpp; sourceTree = "<group>"; };
                E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgeableBuffer.h; sourceTree = "<group>"; };
+               E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveTree.cpp; sourceTree = "<group>"; };
+               E4DEAA1617A93DC3000E0430 /* StyleResolveTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleResolveTree.h; sourceTree = "<group>"; };
                E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleSheetContents.cpp; sourceTree = "<group>"; };
                E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheetContents.h; sourceTree = "<group>"; };
                E51A81DE17298D7700BFCA61 /* JSPerformance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformance.cpp; sourceTree = "<group>"; };
                                E1B25105152A0BAF0069B779 /* StylePropertyShorthand.h */,
                                E139866115478474001E3F65 /* StyleResolver.cpp */,
                                E139866215478474001E3F65 /* StyleResolver.h */,
+                               E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */,
+                               E4DEAA1617A93DC3000E0430 /* StyleResolveTree.h */,
                                E4BBED4A14FCDBA1003F0B98 /* StyleRule.cpp */,
                                E4BBED4B14FCDBA1003F0B98 /* StyleRule.h */,
                                E4946EAC156E64DD00D3297F /* StyleRuleImport.cpp */,
                                85E711970AC5D5350053270F /* DOMDOMImplementationInternal.h in Headers */,
                                52CCA9E815E3F64C0053C77F /* DOMDOMNamedFlowCollection.h in Headers */,
                                52CCA9EA15E3F64C0053C77F /* DOMDOMNamedFlowCollectionInternal.h in Headers */,
+                               E4DEAA1817A93DC3000E0430 /* StyleResolveTree.h in Headers */,
                                2D9A247415B9C2E300D34527 /* DOMDOMSecurityPolicy.h in Headers */,
                                2D9A247515B9C2E300D34527 /* DOMDOMSecurityPolicyInternal.h in Headers */,
                                9B3A8872145632F9003AE8F5 /* DOMDOMSettableTokenList.h in Headers */,
                                49484FCD102CF23C00187DD3 /* CanvasStyle.cpp in Sources */,
                                072CA86116CB4DC3008AE131 /* CaptionUserPreferences.cpp in Sources */,
                                079D086C162F21F900DB8658 /* CaptionUserPreferencesMediaAF.cpp in Sources */,
+                               E4DEAA1717A93DC3000E0430 /* StyleResolveTree.cpp in Sources */,
                                6550B69D099DF0270090D781 /* CDATASection.cpp in Sources */,
                                CDA98E0B1603CD6000FEA3B1 /* CDM.cpp in Sources */,
                                CD47B3FC16CC34F800A21EC8 /* CDMPrivateAVFoundation.mm in Sources */,
diff --git a/Source/WebCore/css/StyleResolveTree.cpp b/Source/WebCore/css/StyleResolveTree.cpp
new file mode 100644 (file)
index 0000000..6a32079
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Peter Kelly (pmk@post.com)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2007 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
+ *           (C) 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "StyleResolveTree.h"
+
+#include "Element.h"
+#include "ElementRareData.h"
+#include "NodeRenderStyle.h"
+#include "NodeTraversal.h"
+#include "RenderObject.h"
+#include "Settings.h"
+#include "ShadowRoot.h"
+#include "StyleResolver.h"
+#include "Text.h"
+
+namespace WebCore {
+
+namespace Style {
+
+Change determineChange(const RenderStyle* s1, const RenderStyle* s2, Settings* settings)
+{
+    if (!s1 || !s2)
+        return Detach;
+    if (s1->display() != s2->display())
+        return Detach;
+    if (s1->hasPseudoStyle(FIRST_LETTER) != s2->hasPseudoStyle(FIRST_LETTER))
+        return Detach;
+    // We just detach if a renderer acquires or loses a column-span, since spanning elements
+    // typically won't contain much content.
+    if (s1->columnSpan() != s2->columnSpan())
+        return Detach;
+    if (settings->regionBasedColumnsEnabled()) {
+        bool specifiesColumns1 = !s1->hasAutoColumnCount() || !s1->hasAutoColumnWidth();
+        bool specifiesColumns2 = !s2->hasAutoColumnCount() || !s2->hasAutoColumnWidth();
+        if (specifiesColumns1 != specifiesColumns2)
+            return Detach;
+    }
+    if (!s1->contentDataEquivalent(s2))
+        return Detach;
+    // When text-combine property has been changed, we need to prepare a separate renderer object.
+    // When text-combine is on, we use RenderCombineText, otherwise RenderText.
+    // https://bugs.webkit.org/show_bug.cgi?id=55069
+    if (s1->hasTextCombine() != s2->hasTextCombine())
+        return Detach;
+    // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
+    if (s1->flowThread() != s2->flowThread())
+        return Detach;
+    // When the region thread has changed, we need to prepare a separate render region object.
+    if (s1->regionThread() != s2->regionThread())
+        return Detach;
+
+    if (*s1 != *s2) {
+        if (s1->inheritedNotEqual(s2))
+            return Inherit;
+        if (s1->hasExplicitlyInheritedProperties() || s2->hasExplicitlyInheritedProperties())
+            return Inherit;
+
+        return NoInherit;
+    }
+    // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
+    // because setStyle will do the right thing with anything else.
+    if (s1->hasAnyPublicPseudoStyles()) {
+        for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
+            if (s1->hasPseudoStyle(pseudoId)) {
+                RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
+                if (!ps2)
+                    return NoInherit;
+                RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
+                if (!ps1 || *ps1 != *ps2)
+                    return NoInherit;
+            }
+        }
+    }
+
+    return NoChange;
+}
+
+static bool pseudoStyleCacheIsInvalid(RenderObject* renderer, RenderStyle* newStyle)
+{
+    const RenderStyle* currentStyle = renderer->style();
+
+    const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
+    if (!pseudoStyleCache)
+        return false;
+
+    size_t cacheSize = pseudoStyleCache->size();
+    for (size_t i = 0; i < cacheSize; ++i) {
+        RefPtr<RenderStyle> newPseudoStyle;
+        PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
+        if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
+            newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
+        else
+            newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
+        if (!newPseudoStyle)
+            return true;
+        if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
+            if (pseudoId < FIRST_INTERNAL_PSEUDOID)
+                newStyle->setHasPseudoStyle(pseudoId);
+            newStyle->addCachedPseudoStyle(newPseudoStyle);
+            if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
+                // FIXME: We should do an actual diff to determine whether a repaint vs. layout
+                // is needed, but for now just assume a layout will be required. The diff code
+                // in RenderObject::setStyle would need to be factored out so that it could be reused.
+                renderer->setNeedsLayoutAndPrefWidthsRecalc();
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+static Change resolveLocal(Element* current, Change inheritedChange)
+{
+    Change localChange = Detach;
+    RefPtr<RenderStyle> newStyle;
+    RefPtr<RenderStyle> currentStyle = current->renderStyle();
+
+    Document* document = current->document();
+    if (currentStyle) {
+        newStyle = current->styleForRenderer();
+        localChange = determineChange(currentStyle.get(), newStyle.get(), document->settings());
+    }
+    if (localChange == Detach) {
+        Node::AttachContext reattachContext;
+        reattachContext.resolvedStyle = newStyle.get();
+        current->reattach(reattachContext);
+        return Detach;
+    }
+
+    if (RenderObject* renderer = current->renderer()) {
+        if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (inheritedChange == Force && renderer->requiresForcedStyleRecalcPropagation()) || current->styleChangeType() == SyntheticStyleChange)
+            renderer->setAnimatableStyle(newStyle.get());
+        else if (current->needsStyleRecalc()) {
+            // Although no change occurred, we use the new style so that the cousin style sharing code won't get
+            // fooled into believing this style is the same.
+            renderer->setStyleInternal(newStyle.get());
+        }
+    }
+
+    // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
+    // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
+    if (document->styleSheetCollection()->usesRemUnits() && document->documentElement() == current && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
+        // Cached RenderStyles may depend on the re units.
+        if (StyleResolver* styleResolver = document->styleResolverIfExists())
+            styleResolver->invalidateMatchedPropertiesCache();
+        return Force;
+    }
+    if (inheritedChange == Force)
+        return Force;
+    if (current->styleChangeType() >= FullStyleChange)
+        return Force;
+
+    return localChange;
+}
+
+void resolveTree(Element* current, Change change)
+{
+    ASSERT(change != Detach);
+
+    if (current->hasCustomStyleCallbacks()) {
+        if (!current->willRecalcStyle(change))
+            return;
+    }
+
+    bool hasParentStyle = current->parentNodeForRenderingAndStyle() && current->parentNodeForRenderingAndStyle()->renderStyle();
+    bool hasDirectAdjacentRules = current->childrenAffectedByDirectAdjacentRules();
+    bool hasIndirectAdjacentRules = current->childrenAffectedByForwardPositionalRules();
+
+    if (change > NoChange || current->needsStyleRecalc())
+        current->resetComputedStyle();
+
+    if (hasParentStyle && (change >= Inherit || current->needsStyleRecalc()))
+        change = resolveLocal(current, change);
+
+    if (change != Detach) {
+        StyleResolverParentPusher parentPusher(current);
+
+        if (ElementShadow* shadow = current->shadow()) {
+            if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
+                parentPusher.push();
+                shadow->recalcStyle(change);
+            }
+        }
+
+        current->updatePseudoElement(BEFORE, change);
+
+        // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
+        // For now we will just worry about the common case, since it's a lot trickier to get the second case right
+        // without doing way too much re-resolution.
+        bool forceCheckOfNextElementSibling = false;
+        bool forceCheckOfAnyElementSibling = false;
+        for (Node* child = current->firstChild(); child; child = child->nextSibling()) {
+            if (child->isTextNode()) {
+                toText(child)->recalcTextStyle(change);
+                continue;
+            }
+            if (!child->isElementNode())
+                continue;
+            Element* childElement = toElement(child);
+            bool childRulesChanged = childElement->needsStyleRecalc() && childElement->styleChangeType() == FullStyleChange;
+            if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
+                childElement->setNeedsStyleRecalc();
+            if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
+                parentPusher.push();
+                resolveTree(childElement, change);
+            }
+            forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
+            forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
+        }
+
+        current->updatePseudoElement(AFTER, change);
+    }
+
+    current->clearNeedsStyleRecalc();
+    current->clearChildNeedsStyleRecalc();
+    
+    if (current->hasCustomStyleCallbacks())
+        current->didRecalcStyle(change);
+}
+
+}
+
+}
diff --git a/Source/WebCore/css/StyleResolveTree.h b/Source/WebCore/css/StyleResolveTree.h
new file mode 100644 (file)
index 0000000..d06978e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 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. ``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
+ * 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.
+ */
+
+#ifndef StyleResolveTree_h
+#define StyleResolveTree_h
+
+namespace WebCore {
+
+class Element;
+class RenderStyle;
+class Settings;
+
+namespace Style {
+
+enum Change { NoChange, NoInherit, Inherit, Detach, Force };
+
+void resolveTree(Element*, Change);
+
+Change determineChange(const RenderStyle*, const RenderStyle*, Settings*);
+
+}
+
+}
+
+#endif
index 4987824..882864a 100644 (file)
@@ -677,6 +677,36 @@ inline bool checkRegionSelector(const CSSSelector* regionSelector, Element* regi
     return false;
 }
 
+class StyleResolverParentPusher {
+public:
+    StyleResolverParentPusher(Element* parent)
+        : m_parent(parent)
+        , m_pushedStyleResolver(0)
+    { }
+    void push()
+    {
+        if (m_pushedStyleResolver)
+            return;
+        m_pushedStyleResolver = m_parent->document()->ensureStyleResolver();
+        m_pushedStyleResolver->pushParentElement(m_parent);
+    }
+    ~StyleResolverParentPusher()
+    {
+        if (!m_pushedStyleResolver)
+            return;
+        // This tells us that our pushed style selector is in a bad state,
+        // so we should just bail out in that scenario.
+        ASSERT(m_pushedStyleResolver == m_parent->document()->ensureStyleResolver());
+        if (m_pushedStyleResolver != m_parent->document()->ensureStyleResolver())
+            return;
+        m_pushedStyleResolver->popParentElement(m_parent);
+    }
+    
+private:
+    Element* m_parent;
+    StyleResolver* m_pushedStyleResolver;
+};
+
 } // namespace WebCore
 
 #endif // StyleResolver_h
index b62424b..03aed7a 100644 (file)
@@ -1742,7 +1742,7 @@ bool Document::childNeedsAndNotInStyleRecalc()
     return childNeedsStyleRecalc() && !m_inStyleRecalc;
 }
 
-void Document::recalcStyle(StyleChange change)
+void Document::recalcStyle(Style::Change change)
 {
     // we should not enter style recalc while painting
     ASSERT(!view() || !view()->isPainting());
@@ -1783,16 +1783,16 @@ void Document::recalcStyle(StyleChange change)
             goto bailOut;
 
         if (m_pendingStyleRecalcShouldForce)
-            change = Force;
+            change = Style::Force;
 
         // Recalculating the root style (on the document) is not needed in the common case.
-        if ((change == Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Inherit))) {
+        if ((change == Style::Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Style::Inherit))) {
             // style selector may set this again during recalc
             m_hasNodesWithPlaceholderStyle = false;
             
             RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(this, m_styleResolver ? m_styleResolver->fontSelector() : 0);
-            StyleChange ch = Node::diff(documentStyle.get(), renderer()->style(), this);
-            if (ch != NoChange)
+            Style::Change documentChange = Style::determineChange(documentStyle.get(), renderer()->style(), settings());
+            if (documentChange != Style::NoChange)
                 renderer()->setStyle(documentStyle.release());
         }
 
@@ -1800,8 +1800,8 @@ void Document::recalcStyle(StyleChange change)
             if (!n->isElementNode())
                 continue;
             Element* element = toElement(n);
-            if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc())
-                element->recalcStyle(change);
+            if (change >= Style::Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc())
+                Style::resolveTree(element, change);
         }
 
 #if USE(ACCELERATED_COMPOSITING)
@@ -1850,7 +1850,7 @@ void Document::updateStyleIfNeeded()
         return;
 
     AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
-    recalcStyle(NoChange);
+    recalcStyle(Style::NoChange);
 }
 
 void Document::updateStyleForAllDocuments()
@@ -1916,7 +1916,7 @@ void Document::updateLayoutIgnorePendingStylesheets()
             // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes 
             // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive 
             // but here we need up-to-date style immediately.
-            recalcStyle(Force);
+            recalcStyle(Style::Force);
     }
 
     updateLayout();
@@ -2024,7 +2024,7 @@ void Document::attach(const AttachContext& context)
     renderView()->setIsInWindow(true);
 #endif
 
-    recalcStyle(Force);
+    recalcStyle(Style::Force);
 
     RenderObject* render = renderer();
     setRenderer(0);
@@ -3179,7 +3179,7 @@ void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
     // make sure animations get the correct update time
     {
         AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
-        recalcStyle(Force);
+        recalcStyle(Style::Force);
     }
 
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
@@ -5209,7 +5209,7 @@ void Document::webkitWillEnterFullScreenForElement(Element* element)
 
     m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
     
-    recalcStyle(Force);
+    recalcStyle(Style::Force);
 }
 
 void Document::webkitDidEnterFullScreenForElement(Element*)
index 46ae313..4548b1e 100644 (file)
@@ -44,6 +44,7 @@
 #include "ReferrerPolicy.h"
 #include "ScriptExecutionContext.h"
 #include "StringWithDirection.h"
+#include "StyleResolveTree.h"
 #include "Timer.h"
 #include "TreeScope.h"
 #include "UserActionElementSet.h"
@@ -505,7 +506,7 @@ public:
     PassRefPtr<CSSStyleDeclaration> createCSSStyleDeclaration();
     PassRefPtr<Text> createEditingTextNode(const String&);
 
-    void recalcStyle(StyleChange = NoChange);
+    void recalcStyle(Style::Change = Style::NoChange);
     bool childNeedsAndNotInStyleRecalc();
     void updateStyleIfNeeded();
     void updateLayout();
index f2bd35f..eb821f4 100644 (file)
@@ -107,40 +107,6 @@ static inline bool shouldIgnoreAttributeCase(const Element* e)
 {
     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
 }
-    
-class StyleResolverParentPusher {
-public:
-    StyleResolverParentPusher(Element* parent)
-        : m_parent(parent)
-        , m_pushedStyleResolver(0)
-    {
-    }
-    void push()
-    {
-        if (m_pushedStyleResolver)
-            return;
-        m_pushedStyleResolver = m_parent->document()->ensureStyleResolver();
-        m_pushedStyleResolver->pushParentElement(m_parent);
-    }
-    ~StyleResolverParentPusher()
-    {
-
-        if (!m_pushedStyleResolver)
-            return;
-
-        // This tells us that our pushed style selector is in a bad state,
-        // so we should just bail out in that scenario.
-        ASSERT(m_pushedStyleResolver == m_parent->document()->ensureStyleResolver());
-        if (m_pushedStyleResolver != m_parent->document()->ensureStyleResolver())
-            return;
-
-        m_pushedStyleResolver->popParentElement(m_parent);
-    }
-
-private:
-    Element* m_parent;
-    StyleResolver* m_pushedStyleResolver;
-};
 
 typedef Vector<RefPtr<Attr> > AttrNodeList;
 typedef HashMap<Element*, OwnPtr<AttrNodeList> > AttrNodeListMap;
@@ -1497,44 +1463,6 @@ void Element::detach(const AttachContext& context)
     ContainerNode::detach(context);
 }
 
-bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
-{
-    ASSERT(currentStyle == renderStyle());
-    ASSERT(renderer());
-
-    if (!currentStyle)
-        return false;
-
-    const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
-    if (!pseudoStyleCache)
-        return false;
-
-    size_t cacheSize = pseudoStyleCache->size();
-    for (size_t i = 0; i < cacheSize; ++i) {
-        RefPtr<RenderStyle> newPseudoStyle;
-        PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
-        if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
-            newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
-        else
-            newPseudoStyle = renderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
-        if (!newPseudoStyle)
-            return true;
-        if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
-            if (pseudoId < FIRST_INTERNAL_PSEUDOID)
-                newStyle->setHasPseudoStyle(pseudoId);
-            newStyle->addCachedPseudoStyle(newPseudoStyle);
-            if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
-                // FIXME: We should do an actual diff to determine whether a repaint vs. layout
-                // is needed, but for now just assume a layout will be required.  The diff code
-                // in RenderObject::setStyle would need to be factored out so that it could be reused.
-                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
 PassRefPtr<RenderStyle> Element::styleForRenderer()
 {
     if (hasCustomStyleCallbacks()) {
@@ -1545,115 +1473,6 @@ PassRefPtr<RenderStyle> Element::styleForRenderer()
     return document()->ensureStyleResolver()->styleForElement(this);
 }
 
-void Element::recalcStyle(StyleChange change)
-{
-    if (hasCustomStyleCallbacks()) {
-        if (!willRecalcStyle(change))
-            return;
-    }
-
-    // Ref currentStyle in case it would otherwise be deleted when setting the new style in the renderer.
-    RefPtr<RenderStyle> currentStyle(renderStyle());
-    bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
-    bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
-    bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
-
-    if ((change > NoChange || needsStyleRecalc())) {
-        if (hasRareData())
-            elementRareData()->resetComputedStyle();
-    }
-    if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
-        StyleChange localChange = Detach;
-        RefPtr<RenderStyle> newStyle;
-        if (currentStyle) {
-            newStyle = styleForRenderer();
-            localChange = Node::diff(currentStyle.get(), newStyle.get(), document());
-        }
-        if (localChange == Detach) {
-            AttachContext reattachContext;
-            reattachContext.resolvedStyle = newStyle.get();
-            reattach(reattachContext);
-
-            // attach recalculates the style for all children. No need to do it twice.
-            clearNeedsStyleRecalc();
-            clearChildNeedsStyleRecalc();
-
-            if (hasCustomStyleCallbacks())
-                didRecalcStyle(change);
-            return;
-        }
-
-        if (RenderObject* renderer = this->renderer()) {
-            if (localChange != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer->requiresForcedStyleRecalcPropagation()) || styleChangeType() == SyntheticStyleChange)
-                renderer->setAnimatableStyle(newStyle.get());
-            else if (needsStyleRecalc()) {
-                // Although no change occurred, we use the new style so that the cousin style sharing code won't get
-                // fooled into believing this style is the same.
-                renderer->setStyleInternal(newStyle.get());
-            }
-        }
-
-        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
-        // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
-        if (document()->styleSheetCollection()->usesRemUnits() && document()->documentElement() == this && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
-            // Cached RenderStyles may depend on the re units.
-            if (StyleResolver* styleResolver = document()->styleResolverIfExists())
-                styleResolver->invalidateMatchedPropertiesCache();
-            change = Force;
-        }
-
-        if (change != Force) {
-            if (styleChangeType() >= FullStyleChange)
-                change = Force;
-            else
-                change = localChange;
-        }
-    }
-    StyleResolverParentPusher parentPusher(this);
-
-    // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
-    if (ElementShadow* shadow = this->shadow()) {
-        if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
-            parentPusher.push();
-            shadow->recalcStyle(change);
-        }
-    }
-
-    updatePseudoElement(BEFORE, change);
-
-    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
-    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
-    // without doing way too much re-resolution.
-    bool forceCheckOfNextElementSibling = false;
-    bool forceCheckOfAnyElementSibling = false;
-    for (Node *n = firstChild(); n; n = n->nextSibling()) {
-        if (n->isTextNode()) {
-            toText(n)->recalcTextStyle(change);
-            continue;
-        } 
-        if (!n->isElementNode()) 
-            continue;
-        Element* element = toElement(n);
-        bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
-        if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
-            element->setNeedsStyleRecalc();
-        if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) {
-            parentPusher.push();
-            element->recalcStyle(change);
-        }
-        forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
-        forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
-    }
-
-    updatePseudoElement(AFTER, change);
-
-    clearNeedsStyleRecalc();
-    clearChildNeedsStyleRecalc();
-    
-    if (hasCustomStyleCallbacks())
-        didRecalcStyle(change);
-}
-
 ElementShadow* Element::shadow() const
 {
     return hasRareData() ? elementRareData()->shadow() : 0;
@@ -2491,13 +2310,13 @@ void Element::normalizeAttributes()
     }
 }
 
-void Element::updatePseudoElement(PseudoId pseudoId, StyleChange change)
+void Element::updatePseudoElement(PseudoId pseudoId, Style::Change change)
 {
     PseudoElement* existing = pseudoElement(pseudoId);
     if (existing) {
         // PseudoElement styles hang off their parent element's style so if we needed
         // a style recalc we should Force one on the pseudo.
-        existing->recalcStyle(needsStyleRecalc() ? Force : change);
+        Style::resolveTree(existing, needsStyleRecalc() ? Style::Force : change);
 
         // Wait until our parent is not displayed or pseudoElementRendererIsNeeded
         // is false, otherwise we could continously create and destroy PseudoElements
@@ -3127,18 +2946,24 @@ void Element::detachAllAttrNodesFromElement()
     removeAttrNodeListForElement(this);
 }
 
-bool Element::willRecalcStyle(StyleChange)
+void Element::resetComputedStyle()
+{
+    if (!hasRareData())
+        return;
+    elementRareData()->resetComputedStyle();
+}
+
+bool Element::willRecalcStyle(Style::Change)
 {
     ASSERT(hasCustomStyleCallbacks());
     return true;
 }
 
-void Element::didRecalcStyle(StyleChange)
+void Element::didRecalcStyle(Style::Change)
 {
     ASSERT(hasCustomStyleCallbacks());
 }
 
-
 PassRefPtr<RenderStyle> Element::customStyleForRenderer()
 {
     ASSERT(hasCustomStyleCallbacks());
index eed07b1..19b68af 100644 (file)
@@ -32,6 +32,7 @@
 #include "RegionOversetState.h"
 #include "ScrollTypes.h"
 #include "SpaceSplitString.h"
+#include "StyleResolveTree.h"
 
 namespace WebCore {
 
@@ -414,7 +415,6 @@ public:
     virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual bool rendererIsNeeded(const NodeRenderingContext&);
-    void recalcStyle(StyleChange = NoChange);
     void didAffectSelector(AffectedSelectorMask);
 
     ElementShadow* shadow() const;
@@ -657,6 +657,11 @@ public:
     virtual void dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection);
     virtual void dispatchBlurEvent(PassRefPtr<Element> newFocusedElement);
 
+    virtual bool willRecalcStyle(Style::Change);
+    virtual void didRecalcStyle(Style::Change);
+    void updatePseudoElement(PseudoId, Style::Change = Style::NoChange);
+    void resetComputedStyle();
+
 protected:
     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
         : ContainerNode(document, type)
@@ -669,8 +674,6 @@ protected:
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE;
     virtual void removeAllEventListeners() OVERRIDE FINAL;
 
-    virtual bool willRecalcStyle(StyleChange);
-    virtual void didRecalcStyle(StyleChange);
     virtual PassRefPtr<RenderStyle> customStyleForRenderer();
 
     void clearTabIndexExplicitlyIfNeeded();    
@@ -692,7 +695,6 @@ private:
     bool isUserActionElementFocused() const;
     bool isUserActionElementHovered() const;
 
-    void updatePseudoElement(PseudoId, StyleChange = NoChange);
     PassRefPtr<PseudoElement> createPseudoElementIfNeeded(PseudoId);
     void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
 
@@ -737,8 +739,6 @@ private:
     virtual void formatForDebugger(char* buffer, unsigned length) const;
 #endif
 
-    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
-
     void cancelFocusAppearanceUpdate();
 
     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
index 6f8e303..55bb922 100644 (file)
@@ -113,7 +113,7 @@ bool ElementShadow::needsStyleRecalc() const
     return shadowRoot()->needsStyleRecalc();
 }
 
-void ElementShadow::recalcStyle(Node::StyleChange change)
+void ElementShadow::recalcStyle(Style::Change change)
 {
     if (ShadowRoot* root = shadowRoot())
         root->recalcStyle(change);
index de1b1bd..d602f2c 100644 (file)
@@ -61,7 +61,7 @@ public:
 
     bool childNeedsStyleRecalc() const;
     bool needsStyleRecalc() const;
-    void recalcStyle(Node::StyleChange);
+    void recalcStyle(Style::Change);
     void removeAllEventListeners();
 
     void invalidateDistribution() { m_distributor.invalidateDistribution(host()); }
index 29d004a..998c4c4 100644 (file)
@@ -320,68 +320,6 @@ void Node::stopIgnoringLeaks()
 #endif
 }
 
-Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2, Document* doc)
-{
-    StyleChange ch = NoInherit;
-    EDisplay display1 = s1 ? s1->display() : NONE;
-    bool fl1 = s1 && s1->hasPseudoStyle(FIRST_LETTER);
-    EDisplay display2 = s2 ? s2->display() : NONE;
-    bool fl2 = s2 && s2->hasPseudoStyle(FIRST_LETTER);
-    
-    // We just detach if a renderer acquires or loses a column-span, since spanning elements
-    // typically won't contain much content.
-    bool colSpan1 = s1 && s1->columnSpan();
-    bool colSpan2 = s2 && s2->columnSpan();
-    
-    bool specifiesColumns1 = s1 && (!s1->hasAutoColumnCount() || !s1->hasAutoColumnWidth());
-    bool specifiesColumns2 = s2 && (!s2->hasAutoColumnCount() || !s2->hasAutoColumnWidth());
-
-    if (display1 != display2 || fl1 != fl2 || colSpan1 != colSpan2 
-        || (specifiesColumns1 != specifiesColumns2 && doc->settings()->regionBasedColumnsEnabled())
-        || (s1 && s2 && !s1->contentDataEquivalent(s2)))
-        ch = Detach;
-    else if (!s1 || !s2)
-        ch = Inherit;
-    else if (*s1 == *s2)
-        ch = NoChange;
-    else if (s1->inheritedNotEqual(s2))
-        ch = Inherit;
-    else if (s1->hasExplicitlyInheritedProperties() || s2->hasExplicitlyInheritedProperties())
-        ch = Inherit;
-
-    // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
-    // because setStyle will do the right thing with anything else.
-    if (ch == NoChange && s1->hasAnyPublicPseudoStyles()) {
-        for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; ch == NoChange && pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
-            if (s1->hasPseudoStyle(pseudoId)) {
-                RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
-                if (!ps2)
-                    ch = NoInherit;
-                else {
-                    RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
-                    ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
-                }
-            }
-        }
-    }
-
-    // When text-combine property has been changed, we need to prepare a separate renderer object.
-    // When text-combine is on, we use RenderCombineText, otherwise RenderText.
-    // https://bugs.webkit.org/show_bug.cgi?id=55069
-    if ((s1 && s2) && (s1->hasTextCombine() != s2->hasTextCombine()))
-        ch = Detach;
-
-    // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
-    if ((s1 && s2) && (s1->flowThread() != s2->flowThread()))
-        ch = Detach;
-
-    // When the region thread has changed, we need to prepare a separate render region object.
-    if ((s1 && s2) && (s1->regionThread() != s2->regionThread()))
-        ch = Detach;
-
-    return ch;
-}
-
 void Node::trackForDebugging()
 {
 #ifndef NDEBUG
index d0cc88f..5998154 100644 (file)
@@ -168,9 +168,6 @@ public:
 
     static void dumpStatistics();
 
-    enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force };    
-    static StyleChange diff(const RenderStyle*, const RenderStyle*, Document*);
-
     virtual ~Node();
     void willBeDeletedFrom(Document*);
 
index 731f139..3005fad 100644 (file)
@@ -105,7 +105,7 @@ bool PseudoElement::rendererIsNeeded(const NodeRenderingContext& context)
     return pseudoElementRendererIsNeeded(context.style());
 }
 
-void PseudoElement::didRecalcStyle(StyleChange)
+void PseudoElement::didRecalcStyle(Style::Change)
 {
     if (!renderer())
         return;
index 19595ff..3b34b24 100644 (file)
@@ -60,7 +60,7 @@ public:
 private:
     PseudoElement(Element*, PseudoId);
 
-    virtual void didRecalcStyle(StyleChange) OVERRIDE;
+    virtual void didRecalcStyle(Style::Change) OVERRIDE;
     virtual PseudoId customPseudoId() const OVERRIDE { return m_pseudoId; }
 
     PseudoId m_pseudoId;
index aefdc66..4b78e9b 100644 (file)
@@ -122,7 +122,7 @@ bool ShadowRoot::childTypeAllowed(NodeType type) const
     }
 }
 
-void ShadowRoot::recalcStyle(StyleChange change)
+void ShadowRoot::recalcStyle(Style::Change change)
 {
     // ShadowRoot doesn't support custom callbacks.
     ASSERT(!hasCustomStyleCallbacks());
@@ -132,7 +132,7 @@ void ShadowRoot::recalcStyle(StyleChange change)
 
     for (Node* child = firstChild(); child; child = child->nextSibling()) {
         if (child->isElementNode())
-            toElement(child)->recalcStyle(change);
+            Style::resolveTree(toElement(child), change);
         else if (child->isTextNode())
             toText(child)->recalcTextStyle(change);
     }
@@ -161,7 +161,7 @@ void ShadowRoot::setResetStyleInheritance(bool value)
     if (value != m_resetStyleInheritance) {
         m_resetStyleInheritance = value;
         if (attached() && owner())
-            owner()->recalcStyle(Force);
+            owner()->recalcStyle(Style::Force);
     }
 }
 
index 393add7..2033cda 100644 (file)
@@ -56,7 +56,7 @@ public:
 
     virtual ~ShadowRoot();
 
-    void recalcStyle(StyleChange);
+    void recalcStyle(Style::Change);
 
     virtual bool applyAuthorStyles() const OVERRIDE { return m_applyAuthorStyles; }
     void setApplyAuthorStyles(bool);
index 145264d..4379609 100644 (file)
@@ -282,11 +282,11 @@ void Text::attach(const AttachContext& context)
     CharacterData::attach(context);
 }
 
-void Text::recalcTextStyle(StyleChange change)
+void Text::recalcTextStyle(Style::Change change)
 {
     RenderText* renderer = toRenderText(this->renderer());
 
-    if (change != NoChange && renderer)
+    if (change != Style::NoChange && renderer)
         renderer->setStyle(document()->ensureStyleResolver()->styleForText(this));
 
     if (needsStyleRecalc()) {
index 9440084..b733745 100644 (file)
@@ -24,6 +24,7 @@
 #define Text_h
 
 #include "CharacterData.h"
+#include "StyleResolveTree.h"
 
 namespace WebCore {
 
@@ -44,7 +45,7 @@ public:
     String wholeText() const;
     PassRefPtr<Text> replaceWholeText(const String&, ExceptionCode&);
     
-    void recalcTextStyle(StyleChange);
+    void recalcTextStyle(Style::Change);
     void createTextRendererIfNeeded();
     bool textRendererIsNeeded(const NodeRenderingContext&);
     RenderText* createTextRenderer(RenderArena*, RenderStyle*);
index 86d7053..33caa59 100644 (file)
@@ -300,7 +300,7 @@ static void updateFromElementCallback(Node* node, unsigned)
         renderer->updateFromElement();
 }
 
-void HTMLFormControlElement::didRecalcStyle(StyleChange)
+void HTMLFormControlElement::didRecalcStyle(Style::Change)
 {
     // updateFromElement() can cause the selection to change, and in turn
     // trigger synchronous layout, so it must not be called during style recalc.
index 28b2047..31199aa 100644 (file)
@@ -120,7 +120,7 @@ protected:
     virtual bool isKeyboardFocusable(KeyboardEvent*) const OVERRIDE;
     virtual bool isMouseFocusable() const OVERRIDE;
 
-    virtual void didRecalcStyle(StyleChange) OVERRIDE;
+    virtual void didRecalcStyle(Style::Change) OVERRIDE;
 
     virtual void dispatchBlurEvent(PassRefPtr<Element> newFocusedElement) OVERRIDE;
 
index 46144bc..cfdeadc 100644 (file)
@@ -200,7 +200,7 @@ void HTMLFrameSetElement::defaultEventHandler(Event* evt)
     HTMLElement::defaultEventHandler(evt);
 }
 
-bool HTMLFrameSetElement::willRecalcStyle(StyleChange)
+bool HTMLFrameSetElement::willRecalcStyle(Style::Change)
 {
     if (needsStyleRecalc() && renderer()) {
         renderer()->setNeedsLayout(true);
index 25a14a8..0a770bb 100644 (file)
@@ -77,7 +77,7 @@ private:
     
     virtual void defaultEventHandler(Event*);
 
-    virtual bool willRecalcStyle(StyleChange);
+    virtual bool willRecalcStyle(Style::Change) OVERRIDE;
 
     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
     virtual void removedFrom(ContainerNode*) OVERRIDE;
index 9b301e2..6264b97 100644 (file)
@@ -106,12 +106,12 @@ bool HTMLIFrameElement::shouldDisplaySeamlessly() const
     return contentDocument() && contentDocument()->shouldDisplaySeamlesslyWithParent();
 }
 
-void HTMLIFrameElement::didRecalcStyle(StyleChange styleChange)
+void HTMLIFrameElement::didRecalcStyle(Style::Change styleChange)
 {
     if (!shouldDisplaySeamlessly())
         return;
     Document* childDocument = contentDocument();
-    if (styleChange >= Inherit || childDocument->childNeedsStyleRecalc() || childDocument->needsStyleRecalc())
+    if (styleChange >= Style::Inherit || childDocument->childNeedsStyleRecalc() || childDocument->needsStyleRecalc())
         contentDocument()->recalcStyle(styleChange);
 }
 
index c7d1afa..c355c89 100644 (file)
@@ -44,7 +44,7 @@ private:
     virtual bool rendererIsNeeded(const NodeRenderingContext&);
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 
-    virtual void didRecalcStyle(StyleChange) OVERRIDE;
+    virtual void didRecalcStyle(Style::Change) OVERRIDE;
 };
 
 inline HTMLIFrameElement* toHTMLIFrameElement(Node* node)
index e173686..2a698b5 100644 (file)
@@ -651,7 +651,7 @@ void HTMLMediaElement::attach(const AttachContext& context)
 #endif
 }
 
-void HTMLMediaElement::didRecalcStyle(StyleChange)
+void HTMLMediaElement::didRecalcStyle(Style::Change)
 {
     if (renderer())
         renderer()->updateFromElement();
index 11ec040..daa38c6 100644 (file)
@@ -436,8 +436,8 @@ private:
     virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE;
     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
     virtual void removedFrom(ContainerNode*) OVERRIDE;
-    virtual void didRecalcStyle(StyleChange);
-    
+    virtual void didRecalcStyle(Style::Change);
+
     virtual void defaultEventHandler(Event*);
 
     virtual void didBecomeFullscreenElement();
index bfa9a9f..0972f45 100644 (file)
@@ -323,7 +323,7 @@ PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer()
     return m_style;
 }
 
-void HTMLOptionElement::didRecalcStyle(StyleChange)
+void HTMLOptionElement::didRecalcStyle(Style::Change)
 {
     // FIXME: This is nasty, we ask our owner select to repaint even if the new
     // style is exactly the same.
index 47e4a91..5acfa8d 100644 (file)
@@ -86,7 +86,7 @@ private:
     virtual RenderStyle* nonRendererStyle() const OVERRIDE;
     virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
 
-    void didRecalcStyle(StyleChange) OVERRIDE;
+    void didRecalcStyle(Style::Change) OVERRIDE;
 
     String collectOptionInnerText() const;
 
index aa5affb..6cd1f5a 100644 (file)
@@ -224,7 +224,7 @@ RenderObject* HTMLPlugInImageElement::createRenderer(RenderArena* arena, RenderS
     return new (arena) RenderEmbeddedObject(this);
 }
 
-bool HTMLPlugInImageElement::willRecalcStyle(StyleChange)
+bool HTMLPlugInImageElement::willRecalcStyle(Style::Change)
 {
     // FIXME: Why is this necessary?  Manual re-attach is almost always wrong.
     if (!useFallbackContent() && needsWidgetUpdate() && renderer() && !isImageType() && (displayState() != DisplayingSnapshot))
@@ -303,7 +303,7 @@ void HTMLPlugInImageElement::documentWillSuspendForPageCache()
     if (RenderStyle* renderStyle = this->renderStyle()) {
         m_customStyleForPageCache = RenderStyle::clone(renderStyle);
         m_customStyleForPageCache->setDisplay(NONE);
-        recalcStyle(Force);
+        Style::resolveTree(this, Style::Force);
     }
 
     HTMLPlugInElement::documentWillSuspendForPageCache();
@@ -313,7 +313,7 @@ void HTMLPlugInImageElement::documentDidResumeFromPageCache()
 {
     if (m_customStyleForPageCache) {
         m_customStyleForPageCache = 0;
-        recalcStyle(Force);
+        Style::resolveTree(this, Style::Force);
     }
 
     HTMLPlugInElement::documentDidResumeFromPageCache();
index d5e2966..e577ddd 100644 (file)
@@ -126,7 +126,7 @@ protected:
 
 private:
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
-    virtual bool willRecalcStyle(StyleChange) OVERRIDE;
+    virtual bool willRecalcStyle(Style::Change) OVERRIDE;
 
     void didAddUserAgentShadowRoot(ShadowRoot*) OVERRIDE;
 
index 8007e4e..b665dd6 100644 (file)
@@ -301,7 +301,7 @@ void InspectorOverlay::update()
     drawPausedInDebuggerMessage();
 
     // Position DOM elements.
-    overlayPage()->mainFrame()->document()->recalcStyle(Node::Force);
+    overlayPage()->mainFrame()->document()->recalcStyle(Style::Force);
     if (overlayView->needsLayout())
         overlayView->layout();
 
index 749caa4..89e989d 100644 (file)
@@ -208,7 +208,7 @@ void DocumentWriter::reportDataReceived()
     m_hasReceivedSomeData = true;
     if (m_decoder->encoding().usesVisualOrdering())
         m_frame->document()->setVisuallyOrdered();
-    m_frame->document()->recalcStyle(Node::Force);
+    m_frame->document()->recalcStyle(Style::Force);
 }
 
 void DocumentWriter::addData(const char* bytes, size_t length)
index 20f2732..f9e1090 100644 (file)
@@ -929,7 +929,7 @@ void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor
     m_pageZoomFactor = pageZoomFactor;
     m_textZoomFactor = textZoomFactor;
 
-    document->recalcStyle(Node::Force);
+    document->recalcStyle(Style::Force);
 
     for (RefPtr<Frame> child = tree()->firstChild(); child; child = child->tree()->nextSibling())
         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
index ad70238..bb65e7a 100644 (file)
@@ -779,7 +779,7 @@ void Page::setPageScaleFactor(float scale, const IntPoint& origin)
         if (document->renderer())
             document->renderer()->setNeedsLayout(true);
 
-        document->recalcStyle(Node::Force);
+        document->recalcStyle(Style::Force);
 
         // Transform change on RenderView doesn't trigger repaint on non-composited contents.
         mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
index bcb117f..e6a72de 100644 (file)
@@ -6753,7 +6753,7 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO
     RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
     ASSERT(firstLetter->isFloating() || firstLetter->isInline());
 
-    if (Node::diff(firstLetter->style(), pseudoStyle, document()) == Node::Detach) {
+    if (Style::determineChange(firstLetter->style(), pseudoStyle, document()->settings()) == Style::Detach) {
         // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
         RenderBoxModelObject* newFirstLetter;
         if (pseudoStyle->display() == INLINE)
index d9f7916..ef5c576 100644 (file)
@@ -88,13 +88,13 @@ SVGElement::~SVGElement()
     document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
 }
 
-bool SVGElement::willRecalcStyle(StyleChange change)
+bool SVGElement::willRecalcStyle(Style::Change change)
 {
     if (!hasSVGRareData() || styleChangeType() == SyntheticStyleChange)
         return true;
     // If the style changes because of a regular property change (not induced by SMIL animations themselves)
     // reset the "computed style without SMIL style properties", so the base value change gets reflected.
-    if (change > NoChange || needsStyleRecalc())
+    if (change > Style::NoChange || needsStyleRecalc())
         svgRareData()->setNeedsOverrideComputedStyleUpdate();
     return true;
 }
index 3bb6da8..6c362bd 100644 (file)
@@ -149,7 +149,7 @@ private:
 
     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
-    virtual bool willRecalcStyle(StyleChange);
+    virtual bool willRecalcStyle(Style::Change);
 
     virtual bool rendererIsNeeded(const NodeRenderingContext&) { return false; }
 
index 3037215..315953b 100644 (file)
@@ -269,7 +269,7 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
     ASSERT_NOT_REACHED();
 }
 
-bool SVGUseElement::willRecalcStyle(StyleChange)
+bool SVGUseElement::willRecalcStyle(Style::Change)
 {
     if (!m_wasInsertedByParser && m_needsShadowTreeRecreation && renderer() && needsStyleRecalc())
         buildPendingResource();
index 70b1633..5e1dabd 100644 (file)
@@ -30,6 +30,7 @@
 #include "SVGGraphicsElement.h"
 #include "SVGNames.h"
 #include "SVGURIReference.h"
+#include "StyleResolveTree.h"
 
 namespace WebCore {
 
@@ -66,7 +67,7 @@ private:
     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
     virtual void svgAttributeChanged(const QualifiedName&);
 
-    virtual bool willRecalcStyle(StyleChange);
+    virtual bool willRecalcStyle(Style::Change);
 
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual void toClipPath(Path&);