Fix for 10682, refine the FOUC paint suppression logic so that it
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Sep 2006 01:43:36 +0000 (01:43 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Sep 2006 01:43:36 +0000 (01:43 +0000)
        is only triggered when FOUC would really have occurred.

        Reviewed by aroben

        * css/cssstyleselector.cpp:
        (WebCore::CSSStyleSelector::styleForElement):
        * dom/Document.cpp:
        (WebCore::Document::Document):
        (WebCore::Document::updateLayoutIgnorePendingStylesheets):
        (WebCore::Document::updateStyleSelector):
        * dom/Document.h:
        (WebCore::Document::haveStylesheetsLoaded):
        (WebCore::Document::):
        (WebCore::Document::didLayoutWithPendingStylesheets):
        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::paintChildren):
        * rendering/RenderLayer.cpp:
        (WebCore::RenderLayer::paintLayer):

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

WebCore/ChangeLog
WebCore/css/cssstyleselector.cpp
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderLayer.cpp

index 408f7a5004397e99cbdc4a54df395958b4cf1f65..ecb5c5542df11939fa41446d8f8cbdfef52bc59d 100644 (file)
@@ -1,3 +1,25 @@
+2006-09-01  David Hyatt  <hyatt@apple.com>
+
+        Fix for 10682, refine the FOUC paint suppression logic so that it
+        is only triggered when FOUC would really have occurred.
+
+        Reviewed by aroben
+
+        * css/cssstyleselector.cpp:
+        (WebCore::CSSStyleSelector::styleForElement):
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+        (WebCore::Document::updateLayoutIgnorePendingStylesheets):
+        (WebCore::Document::updateStyleSelector):
+        * dom/Document.h:
+        (WebCore::Document::haveStylesheetsLoaded):
+        (WebCore::Document::):
+        (WebCore::Document::didLayoutWithPendingStylesheets):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintChildren):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintLayer):
+
 2006-09-01  MorganL  <morlmor@yahoo.com>
 
         Reviewed by Darin. Updated/landed by Adam.
index 12832f99772b81e11543d427bbce4a558754ee89..966809f509cabdb3281e94d331b6951e24dda31f 100644 (file)
@@ -767,7 +767,9 @@ void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
 
 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
 {
-    if (allowSharing && !e->document()->haveStylesheetsLoaded()) {
+    // 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 (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
         if (!styleNotYetAvailable) {
             styleNotYetAvailable = ::new RenderStyle();
             styleNotYetAvailable->setDisplay(NONE);
index bd39b83d95b90ffaca1fc2e10aff42582c4dc7f9..f2a2e31d07334ea92eb54f878573c75ea57262ad 100644 (file)
@@ -265,7 +265,7 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     m_styleSelector = new CSSStyleSelector(this, m_usersheet, m_styleSheets.get(), !inCompatMode());
     m_pendingStylesheets = 0;
     m_ignorePendingStylesheets = false;
-    m_didLayoutWithPendingStylesheets = false;
+    m_pendingSheetLayout = NoLayoutWithPendingSheets;
 
     m_cssTarget = 0;
 
@@ -930,7 +930,14 @@ void Document::updateLayoutIgnorePendingStylesheets()
     
     if (!haveStylesheetsLoaded()) {
         m_ignorePendingStylesheets = true;
-        m_didLayoutWithPendingStylesheets = true;
+        // FIXME: We are willing to attempt to suppress painting with outdated style info only once.  Our assumption is that it would be
+        // dangerous to try to stop it a second time, after page content has already been loaded and displayed
+        // with accurate style information.  (Our suppression involves blanking the whole page at the
+        // moment.  If it were more refined, we might be able to do something better.)
+        // It's worth noting though that this entire method is a hack, since what we really want to do is
+        // suspend JS instead of doing a layout with inaccurate information.
+        if (m_pendingSheetLayout == NoLayoutWithPendingSheets)
+            m_pendingSheetLayout = DidLayoutWithPendingSheets;
         updateStyleSelector();    
     }
 
@@ -1775,8 +1782,8 @@ void Document::updateStyleSelector()
     if (!haveStylesheetsLoaded())
         return;
 
-    if (m_didLayoutWithPendingStylesheets) {
-        m_didLayoutWithPendingStylesheets = false;
+    if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) {
+        m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
         if (renderer())
             renderer()->repaint();
     }
index 9adced8871217e480e02b3cb901858a8a6f12949..3cc02b32faf6fbbfda5375e8f8d417b57ea6363c 100644 (file)
@@ -240,7 +240,7 @@ public:
      * This method returns true if all top-level stylesheets have loaded (including
      * any @imports that they may be loading).
      */
-    bool haveStylesheetsLoaded(bool checkIgnoreFlag = true) const { return m_pendingStylesheets <= 0 || (checkIgnoreFlag && m_ignorePendingStylesheets); }
+    bool haveStylesheetsLoaded() const { return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets; }
 
     /**
      * Increments the number of pending sheets.  The <link> elements
@@ -597,6 +597,10 @@ public:
                                      ExceptionCode& ec);
 #endif // XPATH_SUPPORT
     
+    enum PendingSheetLayout { NoLayoutWithPendingSheets, DidLayoutWithPendingSheets, IgnoreLayoutWithPendingSheets };
+
+    bool didLayoutWithPendingStylesheets() const { return m_pendingSheetLayout == DidLayoutWithPendingSheets; }
+
 protected:
     CSSStyleSelector* m_styleSelector;
     FrameView* m_view;
@@ -628,7 +632,7 @@ protected:
     // If we do ignore the pending stylesheet count, then we need to add a boolean
     // to track that this happened so that we can do a full repaint when the stylesheets
     // do eventually load.
-    bool m_didLayoutWithPendingStylesheets;
+    PendingSheetLayout m_pendingSheetLayout;
 
     RefPtr<CSSStyleSheet> m_elemSheet;
 
index 377b729e08865be4167a479ab4030239fcf7e831..60b14d7bb87680755ea4db256ca2bf4eb5a70e36 100644 (file)
@@ -1258,7 +1258,7 @@ void RenderBlock::paintChildren(PaintInfo& i, int _tx, int _ty)
     // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
     // will do a full repaint().
-    if (!document()->haveStylesheetsLoaded(false))
+    if (document()->didLayoutWithPendingStylesheets())
         return;
     
     PaintPhase newPhase = (i.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : i.phase;
index 33c730e153815484f9bc32bbba985f089dcc64ee..f0d528d630d67e496c58efdc52743bb63ae908c6 100644 (file)
@@ -1273,7 +1273,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
     // will do a full repaint().
-    if (!renderer()->document()->haveStylesheetsLoaded(false) && !renderer()->isRenderView() && !renderer()->isRoot())
+    if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
         return;
     
     // Calculate the clip rects we should use.