[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/khtml/rendering
From:       Germain Garand <germain () ebooksfrance ! org>
Date:       2007-10-24 11:44:50
Message-ID: 1193226290.091844.24657.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 728822 by ggarand:

adapt patch by Antti Koivisto <koivisto@iki.fi>

WC/r16988/#4377/ "Respect css visibility semantics for layers too"
WC/r18616/#12109/ "layer visibility incorrect in some cases"


 M  +36 -6     render_container.cpp  
 M  +112 -19   render_layer.cpp  
 M  +14 -1     render_layer.h  
 M  +9 -0      render_object.cpp  


--- trunk/KDE/kdelibs/khtml/rendering/render_container.cpp #728821:728822
@@ -33,6 +33,7 @@
 #include "rendering/render_canvas.h"
 #include "rendering/render_generated.h"
 #include "rendering/render_inline.h"
+#include "rendering/render_layer.h"
 #include "xml/dom_docimpl.h"
 #include "css/css_valueimpl.h"
 
@@ -171,8 +172,18 @@
         // disappears gets repainted properly.
         oldChild->repaint();
 
-        // Keep our layer hierarchy updated.
-        oldChild->removeLayers(enclosingLayer());
+        // if we remove visible child from an invisible parent, we don't know the \
layer visibility any more +        RenderLayer* layer = 0;
+        if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == \
VISIBLE && !oldChild->layer()) { +            layer = enclosingLayer();
+            layer->dirtyVisibleContentStatus();
+        }
+
+         // Keep our layer hierarchy updated.
+        if (oldChild->firstChild() || oldChild->layer()) {
+            if (!layer) layer = enclosingLayer();            
+            oldChild->removeLayers(layer);
+        }
         // remove the child from any special layout lists
         oldChild->removeFromObjectLists();
         
@@ -484,11 +495,19 @@
 
     // Keep our layer hierarchy updated.  Optimize for the common case where we \
don't have any children  // and don't have a layer attached to ourselves.
+    RenderLayer* layer = 0;
     if (newChild->firstChild() || newChild->layer()) {
-        RenderLayer* layer = enclosingLayer();
+        layer = enclosingLayer();
         newChild->addLayers(layer, newChild);
     }
 
+    // if the new child is visible but this object was not, tell the layer it has \
some visible content +    // that needs to be drawn and layer visibility optimization \
can't be used +    if (style()->visibility() != VISIBLE && \
newChild->style()->visibility() == VISIBLE && !newChild->layer()) { +        if \
(!layer) layer = enclosingLayer(); +        layer->setHasVisibleContent(true);
+    }
+
     if (!newChild->isFloatingOrPositioned() && childrenInline())
         dirtyLinesFromChangedChild(newChild);
 
@@ -527,10 +546,21 @@
     child->setPreviousSibling(prev);
     child->setParent(this);
 
-    // Keep our layer hierarchy updated.
-    RenderLayer* layer = enclosingLayer();
-    child->addLayers(layer, child);
+    // Keep our layer hierarchy updated.  Optimize for the common case where we \
don't have any children +    // and don't have a layer attached to ourselves.
+    RenderLayer* layer = 0;
+    if (child->firstChild() || child->layer()) {
+        layer = enclosingLayer();
+        child->addLayers(layer, child);
+    }
 
+    // if the new child is visible but this object was not, tell the layer it has \
some visible content +    // that needs to be drawn and layer visibility optimization \
can't be used +    if (style()->visibility() != VISIBLE && \
child->style()->visibility() == VISIBLE && !child->layer()) { +        if (!layer) \
layer = enclosingLayer(); +        layer->setHasVisibleContent(true);
+    }
+
     if (!child->isFloating() && childrenInline())
         dirtyLinesFromChangedChild(child);
 
--- trunk/KDE/kdelibs/khtml/rendering/render_layer.cpp #728821:728822
@@ -102,8 +102,16 @@
 m_isOverflowOnly( shouldBeOverflowOnly() ),
 m_markedForRepaint( false ),
 m_hasOverlaidWidgets( false ),
+m_visibleContentStatusDirty( true ),
+m_hasVisibleContent( false ),
+m_visibleDescendantStatusDirty( false ),
+m_hasVisibleDescendant( false ),
 m_marquee( 0 )
 {
+    if (!object->firstChild() && object->style()) {
+        m_visibleContentStatusDirty = false;
+        m_hasVisibleContent = object->style()->visibility() == VISIBLE;
+    }
 }
 
 RenderLayer::~RenderLayer()
@@ -164,7 +172,7 @@
 {
     updateZOrderLists();
     QRegion r;
-    if (m_negZOrderList) {
+    if (m_negZOrderList && m_hasVisibleDescendant) {
         uint count = m_negZOrderList->count();
         for (uint i = 0; i < count; i++) {
             RenderLayer* child = m_negZOrderList->at(i);
@@ -172,19 +180,19 @@
         }
     }
     const RenderStyle *s= renderer()->style();
-    if (s->visibility() == VISIBLE) {
+    if (m_hasVisibleContent) {
         int x = 0; int y = 0;
         convertToLayerCoords(rootLayer,x,y);
         QRect cr(x,y,width(),height());
-        if ( s->backgroundImage() || s->backgroundColor().isValid() || \
                s->hasBorder() || 
-             renderer()->scrollsOverflow() || renderer()->isReplaced() ) {
+        if (s->visibility() == VISIBLE && (s->backgroundImage() || \
s->backgroundColor().isValid() || s->hasBorder() ||  +             \
renderer()->scrollsOverflow() || renderer()->isReplaced()) ) {  r += cr;
         } else {
             r += renderer()->visibleFlowRegion(x, y);
         }
     }
     
-    if (m_posZOrderList) {
+    if (m_posZOrderList && m_hasVisibleDescendant) {
         uint count = m_posZOrderList->count();
         for (uint i = 0; i < count; i++) {
             RenderLayer* child = m_posZOrderList->at(i);
@@ -229,12 +237,9 @@
         positionScrollbars(layerBounds);
     }
 
-#ifdef APPLE_CHANGES
-    // FIXME: Child object could override visibility.
-    if (checkForRepaint && (m_object->style()->visibility() == VISIBLE))
-        m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_fullRepaintRect);
-#else    
-    if (checkForRepaint && m_markedForRepaint) {
+    updateVisibilityStatus();
+
+    if (m_hasVisibleContent && checkForRepaint && m_markedForRepaint) {
         QRect layerBounds, damageRect, fgrect;
         calculateRects(rootLayer, renderer()->viewRect(), layerBounds, damageRect, \
fgrect);  QRect vr = damageRect.intersect( layerBounds );
@@ -244,7 +249,6 @@
         }
     }
     m_markedForRepaint = false;   
-#endif
     
     for	(RenderLayer* child = firstChild(); child; child = child->nextSibling())
         child->updateLayerPositions(rootLayer, doFullRepaint, checkForRepaint);
@@ -254,6 +258,92 @@
         m_marquee->updateMarqueePosition();
 }
 
+ 
+void RenderLayer::setHasVisibleContent(bool b) 
+{ 
+    if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
+        return;
+    m_visibleContentStatusDirty = false; 
+    m_hasVisibleContent = b;
+    if (parent())
+        parent()->childVisibilityChanged(m_hasVisibleContent);
+}
+
+void RenderLayer::dirtyVisibleContentStatus() 
+{ 
+    m_visibleContentStatusDirty = true; 
+    if (parent())
+        parent()->dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::childVisibilityChanged(bool newVisibility) 
+{ 
+    if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
+        return;
+    if (newVisibility) {
+        RenderLayer* l = this;
+        while (l && !l->m_visibleDescendantStatusDirty && \
!l->m_hasVisibleDescendant) { +            l->m_hasVisibleDescendant = true;
+            l = l->parent();
+        }
+    } else 
+        dirtyVisibleDescendantStatus();
+}
+
+void RenderLayer::dirtyVisibleDescendantStatus()
+{
+    RenderLayer* l = this;
+    while (l && !l->m_visibleDescendantStatusDirty) {
+        l->m_visibleDescendantStatusDirty = true;
+        l = l->parent();
+    }
+}
+
+void RenderLayer::updateVisibilityStatus()
+{
+    if (m_visibleDescendantStatusDirty) {
+        m_hasVisibleDescendant = false;
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) \
{ +            child->updateVisibilityStatus();        
+            if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
+                m_hasVisibleDescendant = true;
+                break;
+            }
+        }
+        m_visibleDescendantStatusDirty = false;
+    }
+
+    if (m_visibleContentStatusDirty) {
+        if (m_object->style()->visibility() == VISIBLE)
+            m_hasVisibleContent = true;
+        else {
+            // layer may be hidden but still have some visible content, check for \
this +            m_hasVisibleContent = false;
+            RenderObject* r = m_object->firstChild();
+            while (r) {
+                if (r->style()->visibility() == VISIBLE && !r->layer()) {
+                    m_hasVisibleContent = true;
+                    break;
+                }
+                if (r->firstChild() && !r->layer())
+                    r = r->firstChild();
+                else if (r->nextSibling())
+                    r = r->nextSibling();
+                else {
+                    do {
+                        r = r->parent();
+                        if (r==m_object)
+                            r = 0;
+                    } while (r && !r->nextSibling());
+                    if (r)
+                        r = r->nextSibling();
+                }
+            }
+        }    
+        m_visibleContentStatusDirty = false; 
+    }
+}
+
 void RenderLayer::updateWidgetMasks(RenderLayer* rootLayer) 
 {
     if (hasOverlaidWidgets() && !renderer()->canvas()->pagedMode()) {
@@ -384,6 +474,9 @@
         if (stackingContext)
             stackingContext->dirtyZOrderLists();
     }
+    child->updateVisibilityStatus();
+    if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
+        childVisibilityChanged(true);
 }
 
 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
@@ -414,6 +507,10 @@
     oldChild->setNextSibling(0);
     oldChild->setParent(0);
 
+    oldChild->updateVisibilityStatus();
+    if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
+        childVisibilityChanged(false);
+
     return oldChild;
 }
 
@@ -1367,14 +1464,10 @@
 
 void RenderLayer::collectLayers(QVector<RenderLayer*>*& posBuffer, \
QVector<RenderLayer*>*& negBuffer)  {
-    // FIXME: A child render object or layer could override visibility.  Don't \
                remove this
-    // optimization though until RenderObject's nodeAtPoint is patched to understand \
                what to do
-    // when visibility is overridden by a child.
-    if (renderer()->style()->visibility() != VISIBLE)
-        return;
+    updateVisibilityStatus();
 
     // Overflow layers are just painted by their enclosing layers, so they don't get \
                put in zorder lists.
-    if (!isOverflowOnly()) {
+    if (m_hasVisibleContent && !isOverflowOnly()) {
         // Determine which buffer the child should be in.
         QVector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
 
@@ -1388,7 +1481,7 @@
 
     // Recur into our children to collect more layers, but only if we don't \
establish  // a stacking context.
-    if (!isStackingContext()) {
+    if (m_hasVisibleDescendant && !isStackingContext()) {
         for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
             child->collectLayers(posBuffer, negBuffer);
     }
--- trunk/KDE/kdelibs/khtml/rendering/render_layer.h #728821:728822
@@ -214,6 +214,11 @@
     void updateOverflowList();
     QVector<RenderLayer*>* overflowList() const { return m_overflowList; }
 
+    bool hasVisibleContent() const { return m_hasVisibleContent; }
+    void setHasVisibleContent(bool b);
+    void dirtyVisibleContentStatus();
+    
+
     void setHasOverlaidWidgets(bool b=true) { m_hasOverlaidWidgets = b; }
     bool hasOverlaidWidgets() const { return m_hasOverlaidWidgets; }
     QRegion getMask() const { return m_region; }
@@ -280,6 +285,10 @@
                                      int x, int y, const QRect& hitTestRect);
     bool shouldBeOverflowOnly() const;
 
+    void childVisibilityChanged(bool newVisibility);
+    void dirtyVisibleDescendantStatus();
+    void updateVisibilityStatus();
+
 protected:
     RenderObject* m_object;
 
@@ -321,7 +330,11 @@
     bool m_overflowListDirty: 1;
     bool m_isOverflowOnly: 1;
     bool m_markedForRepaint: 1;
-    bool m_hasOverlaidWidgets: 1; 
+    bool m_hasOverlaidWidgets: 1;
+    bool m_visibleContentStatusDirty : 1;
+    bool m_hasVisibleContent : 1;
+    bool m_visibleDescendantStatusDirty : 1;
+    bool m_hasVisibleDescendant : 1;
 
     QRect m_visibleRect;
 
--- trunk/KDE/kdelibs/khtml/rendering/render_object.cpp #728821:728822
@@ -1316,6 +1316,15 @@
                 layer()->stackingContext()->dirtyZOrderLists();
                 layer()->dirtyZOrderLists();
             }
+            // keep layer hierarchy visibility bits up to date if visibility changes
+            if (m_style->visibility() != style->visibility()) {
+                RenderLayer* l = enclosingLayer(); 
+                if (style->visibility() == VISIBLE && l)
+                    l->setHasVisibleContent(true);
+                else if (l && l->hasVisibleContent() && 
+                    (this == l->renderer() || l->renderer()->style()->visibility() \
!= VISIBLE)) +                    l->dirtyVisibleContentStatus();
+            }            
         }
 
         // reset style flags


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic