[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