Fix for 7837, make opacity work with table rows. Make transparent backgrounds
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Mar 2006 01:01:06 +0000 (01:01 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Mar 2006 01:01:06 +0000 (01:01 +0000)
        stack properly in cells (so that the layers behind can show through like they
        should).

        Reviewed by beth

        * rendering/RenderTableCell.cpp:
        (WebCore::RenderTableCell::requiresLayer):
        (WebCore::RenderTableCell::paintBackgroundsBehindCell):
        (WebCore::RenderTableCell::paintBoxDecorations):
        * rendering/RenderTableCell.h:
        * rendering/RenderTableRow.cpp:
        (WebCore::RenderTableRow::paint):
        * rendering/RenderTableRow.h:
        (WebCore::RenderTableRow::requiresLayer):
        * rendering/RenderTableSection.cpp:
        (WebCore::RenderTableSection::paint):
        * rendering/render_layer.cpp:
        (WebCore::RenderLayer::updateLayerPosition):
        (WebCore::RenderLayer::isTransparent):
        (WebCore::RenderLayer::transparentAncestor):
        (WebCore::RenderLayer::beginTransparencyLayers):
        (WebCore::RenderLayer::paintLayer):
        (WebCore::RenderLayer::absoluteBoundingBox):
        * rendering/render_object.cpp:
        (WebCore::RenderObject::requiresLayer):
        * rendering/render_object.h:
        (WebCore::RenderObject::isTransparent):
        (WebCore::RenderObject::opacity):

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

WebCore/ChangeLog
WebCore/rendering/RenderTableCell.cpp
WebCore/rendering/RenderTableCell.h
WebCore/rendering/RenderTableRow.cpp
WebCore/rendering/RenderTableRow.h
WebCore/rendering/RenderTableSection.cpp
WebCore/rendering/render_layer.cpp
WebCore/rendering/render_object.cpp
WebCore/rendering/render_object.h

index 5b7366d..4006d14 100644 (file)
@@ -1,3 +1,35 @@
+2006-03-17  David Hyatt  <hyatt@apple.com>
+
+        Fix for 7837, make opacity work with table rows.  Make transparent backgrounds
+        stack properly in cells (so that the layers behind can show through like they
+        should).
+
+        Reviewed by beth
+
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::requiresLayer):
+        (WebCore::RenderTableCell::paintBackgroundsBehindCell):
+        (WebCore::RenderTableCell::paintBoxDecorations):
+        * rendering/RenderTableCell.h:
+        * rendering/RenderTableRow.cpp:
+        (WebCore::RenderTableRow::paint):
+        * rendering/RenderTableRow.h:
+        (WebCore::RenderTableRow::requiresLayer):
+        * rendering/RenderTableSection.cpp:
+        (WebCore::RenderTableSection::paint):
+        * rendering/render_layer.cpp:
+        (WebCore::RenderLayer::updateLayerPosition):
+        (WebCore::RenderLayer::isTransparent):
+        (WebCore::RenderLayer::transparentAncestor):
+        (WebCore::RenderLayer::beginTransparencyLayers):
+        (WebCore::RenderLayer::paintLayer):
+        (WebCore::RenderLayer::absoluteBoundingBox):
+        * rendering/render_object.cpp:
+        (WebCore::RenderObject::requiresLayer):
+        * rendering/render_object.h:
+        (WebCore::RenderObject::isTransparent):
+        (WebCore::RenderObject::opacity):
+
 2006-03-17  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by Adele.
index 9fce140..8aaf403 100644 (file)
@@ -172,8 +172,9 @@ void RenderTableCell::setStyle(RenderStyle *style)
     setShouldPaintBackgroundOrBorder(true);
 }
 
-bool RenderTableCell::requiresLayer() {
-    return isPositioned() || style()->opacity() < 1.0f || hasOverflowClip();
+bool RenderTableCell::requiresLayer()
+{
+    return isPositioned() || isTransparent() || hasOverflowClip();
 }
 
 // The following rules apply for resolving conflicts and figuring out which border
@@ -693,74 +694,59 @@ IntRect RenderTableCell::getAbsoluteRepaintRect()
     return r;
 }
 
-void RenderTableCell::paintBoxDecorations(PaintInfo& i, int _tx, int _ty)
+void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& i, int _tx, int _ty, RenderObject* backgroundObject)
 {
+    if (!backgroundObject)
+        return;
+
     RenderTable* tableElt = table();
     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
         return;
-    
-    int w = width();
-    int h = height() + borderTopExtra() + borderBottomExtra();
-    _ty -= borderTopExtra();
-
-    Color c = style()->backgroundColor();
-    if (!c.isValid() && parent()) // take from row
-        c = parent()->style()->backgroundColor();
-    if (!c.isValid() && parent() && parent()->parent()) // take from rowgroup
-        c = parent()->parent()->style()->backgroundColor();
-    if (!c.isValid()) {
-       // see if we have a col or colgroup for this
-       RenderTableCol *col = table()->colElement(_col);
-       if (col) {
-           c = col->style()->backgroundColor();
-           if (!c.isValid()) {
-               // try column group
-               RenderStyle *style = col->parent()->style();
-               if (style->display() == TABLE_COLUMN_GROUP)
-                   c = style->backgroundColor();
-           }
-       }
-    }
 
-    // FIXME: This code is just plain wrong.  Rows and columns should paint their backgrounds
-    // independent from the cell.
-    // ### get offsets right in case the bgimage is inherited.
-    const BackgroundLayer* bgLayer = style()->backgroundLayers();
-    if (!bgLayer->hasImage() && parent())
-        bgLayer = parent()->style()->backgroundLayers();
-    if (!bgLayer->hasImage() && parent() && parent()->parent())
-        bgLayer = parent()->parent()->style()->backgroundLayers();
-    if (!bgLayer->hasImage()) {
-       // see if we have a col or colgroup for this
-       RenderTableCol* col = table()->colElement(_col);
-       if (col) {
-           bgLayer = col->style()->backgroundLayers();
-           if (!bgLayer->hasImage()) {
-               // try column group
-               RenderStyle *style = col->parent()->style();
-               if (style->display() == TABLE_COLUMN_GROUP)
-                   bgLayer = style->backgroundLayers();
-           }
-       }
+    if (backgroundObject != this) {
+        _tx += m_x;
+        _ty += m_y + _topExtra;
     }
 
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    _ty -= borderTopExtra();
+    
     int my = kMax(_ty, i.r.y());
     int end = kMin(i.r.bottom(), _ty + h);
     int mh = end - my;
+    
+    Color c = backgroundObject->style()->backgroundColor();
+    const BackgroundLayer* bgLayer = backgroundObject->style()->backgroundLayers();
 
     if (bgLayer->hasImage() || c.isValid()) {
-       // We have to clip here because the backround would paint
-        // on top of the borders otherwise.
-        if (m_layer && tableElt->collapseBorders()) {
+       // We have to clip here because the background would paint
+        // on top of the borders otherwise.  This only matters for cells and rows.
+        bool hasLayer = backgroundObject->layer() && (backgroundObject == this || backgroundObject == parent());
+        if (hasLayer && tableElt->collapseBorders()) {
             IntRect clipRect(_tx + borderLeft(), _ty + borderTop(),
                 w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
             i.p->save();
             i.p->addClip(clipRect);
         }
         paintBackground(i.p, c, bgLayer, my, mh, _tx, _ty, w, h);
-        if (m_layer && tableElt->collapseBorders())
+        if (hasLayer && tableElt->collapseBorders())
             i.p->restore();
     }
+}
+
+void RenderTableCell::paintBoxDecorations(PaintInfo& i, int _tx, int _ty)
+{
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+    // Paint our cell background.
+    paintBackgroundsBehindCell(i, _tx, _ty, this);
+
+    int w = width();
+    int h = height() + borderTopExtra() + borderBottomExtra();
+    _ty -= borderTopExtra();
 
     if (style()->hasBorder() && !tableElt->collapseBorders())
         paintBorder(i.p, _tx, _ty, w, h, style());
index 0781459..4fe2567 100644 (file)
@@ -60,6 +60,7 @@ public:
     Length styleOrColWidth();
 
     virtual bool requiresLayer();
+
     virtual void calcMinMaxWidth();
     virtual void calcWidth();
     virtual void setWidth(int);
@@ -107,9 +108,11 @@ public:
 
     virtual IntRect getAbsoluteRepaintRect();
     
+    void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject);
+
 protected:
     virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
-    
+
     int _row;
     int _col;
     int rSpan;
index 8d2b6e6..cc1c70d 100644 (file)
@@ -150,4 +150,23 @@ bool RenderTableRow::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, H
     return false;
 }
 
+void RenderTableRow::paint(PaintInfo& i, int tx, int ty)
+{
+    assert(m_layer);
+    if (!m_layer)
+        return;
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableCell()) {
+            // Paint the row background behind the cell.
+            if (i.phase == PaintActionBlockBackground || i.phase == PaintActionChildBlockBackground) {
+                RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+                cell->paintBackgroundsBehindCell(i, tx, ty, this);
+            }
+            if (!child->layer())
+                child->paint(i, tx, ty);
+        }
+    }
+}
+
 }
index cfc1487..d9d12d3 100644 (file)
@@ -47,9 +47,10 @@ public:
     virtual IntRect getAbsoluteRepaintRect();
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action);
 
-    // FIXME: We can't support things like opacity on table rows because they have no dimensions.  This can be removed when
-    // table rows really work right.
-    virtual bool requiresLayer() { return false; }
+    // The only time rows get a layer is when they have transparency.
+    virtual bool requiresLayer() { return isTransparent(); }
+
+    virtual void paint(PaintInfo& i, int tx, int ty);
 
     RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
     RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
index 98e3c57..ee377fe 100644 (file)
@@ -29,6 +29,7 @@
 #include "RenderTableSection.h"
 #include "RenderTableCell.h"
 #include "RenderTableRow.h"
+#include "RenderTableCol.h"
 #include "DocumentImpl.h"
 #include "htmlnames.h"
 #include <qtextstream.h>
@@ -649,17 +650,44 @@ void RenderTableSection::paint(PaintInfo& i, int tx, int ty)
             for (; c < endcol; c++) {
                 CellStruct current = cellAt(r, c);
                 RenderTableCell *cell = current.cell;
-                
-                if (!cell || (cell->layer() && i.phase != PaintActionCollapsedTableBorders)) 
-                    continue;
-                
+                    
                 // Cells must always paint in the order in which they appear taking into account
                 // their upper left originating row/column.  For cells with rowspans, avoid repainting
                 // if we've already seen the cell.
-                if (r > startrow && (cellAt(r-1, c).cell == cell))
+                if (!cell || (r > startrow && (cellAt(r-1, c).cell == cell)))
                     continue;
 
-                cell->paint(i, tx, ty);
+                if (paintAction == PaintActionBlockBackground || paintAction == PaintActionChildBlockBackground) {
+                    // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
+                    // the column group, column, row group, row, and then the cell.
+                    RenderObject* col = table()->colElement(c);
+                    RenderObject* colGroup = 0;
+                    if (col) {
+                        RenderStyle *style = col->parent()->style();
+                        if (style->display() == TABLE_COLUMN_GROUP)
+                            colGroup = col->parent();
+                    }
+                    RenderObject* row = cell->parent();
+                    
+                    // Column groups and columns first.
+                    // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
+                    // the stack, since we have already opened a transparency layer (potentially) for the table row group.
+                    // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
+                    // cell.
+                    cell->paintBackgroundsBehindCell(i, tx, ty, colGroup);
+                    cell->paintBackgroundsBehindCell(i, tx, ty, col);
+                    
+                    // Paint the row group next.
+                    cell->paintBackgroundsBehindCell(i, tx, ty, this);
+                    
+                    // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
+                    // painting the row background for the cell.
+                    if (!row->layer())
+                        cell->paintBackgroundsBehindCell(i, tx, ty, row);
+                }
+
+                if ((!cell->layer() && !cell->parent()->layer()) || i.phase == PaintActionCollapsedTableBorders)
+                    cell->paint(i, tx, ty);
             }
         }
     }
index 13c8eec..5dd9ff2 100644 (file)
@@ -237,6 +237,11 @@ void RenderLayer::updateLayerPosition()
             curr = curr->parent();
         }
         y += curr->borderTopExtra();
+        if (curr->isTableRow()) {
+            // Put ourselves into the row coordinate space.
+            x -= curr->xPos();
+            y -= curr->yPos();
+        }
     }
 
     m_relX = m_relY = 0;
@@ -327,14 +332,14 @@ RenderLayer::isTransparent() const
     if (m_object->node()->namespaceURI() == KSVG::SVGNames::svgNamespaceURI)
         return false;
 #endif
-    return m_object->style()->opacity() < 1.0f;
+    return m_object->isTransparent();
 }
 
 RenderLayer*
 RenderLayer::transparentAncestor()
 {
     RenderLayer* curr = parent();
-    for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
+    for ( ; curr && !curr->isTransparent(); curr = curr->parent());
     return curr;
 }
 
@@ -371,7 +376,7 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const IntRect& pai
         clipRect.intersect(paintDirtyRect);
         p->save();
         p->addClip(clipRect);
-        p->beginTransparencyLayer(renderer()->style()->opacity());
+        p->beginTransparencyLayer(renderer()->opacity());
     }
 }
 
@@ -1083,9 +1088,8 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
     // so it will be tested against as we decend through the renderers.
     RenderObject *paintingRootForRenderer = 0;
-    if (paintingRoot && !m_object->hasAncestor(paintingRoot)) {
+    if (paintingRoot && !m_object->hasAncestor(paintingRoot))
         paintingRootForRenderer = paintingRoot;
-    }
     
     // We want to paint our layer, but only if we intersect the damage rect.
     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
@@ -1401,6 +1405,20 @@ IntRect RenderLayer::absoluteBoundingBox() const
         for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
             left = kMin(left, curr->xPos());
         result = IntRect(m_x + left, m_y + (top - renderer()->yPos()), width(), bottom - top);
+    } else if (renderer()->isTableRow()) {
+        // Our bounding box is just the union of all of our cells' border/overflow rects.
+        for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+            if (child->isTableCell()) {
+                IntRect bbox = child->borderBox();
+                bbox.move(0, child->borderTopExtra());
+                result.unite(bbox);
+                IntRect overflowRect = renderer()->overflowRect(false);
+                overflowRect.move(0, child->borderTopExtra());
+                if (bbox != overflowRect)
+                    result.unite(overflowRect);
+            }
+        }
+        result.move(m_x, m_y);
     } else {
         IntRect bbox = renderer()->borderBox();
         result = bbox;
index 3205cc5..915dd62 100644 (file)
@@ -528,8 +528,7 @@ RenderLayer* RenderObject::enclosingLayer()
 
 bool RenderObject::requiresLayer()
 {
-    return isRoot() || isPositioned() || isRelPositioned() || style()->opacity() < 1.0f ||
-           hasOverflowClip();
+    return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip();
 }
 
 RenderBlock* RenderObject::firstLineBlock() const
index be08ca2..68cf37b 100644 (file)
@@ -747,6 +747,9 @@ public:
     // positioning of inline children (bidi)
     virtual void position(InlineBox*, int, int, bool, bool) {}
 
+    bool isTransparent() const { return style()->opacity() < 1.0f; }
+    float opacity() const { return style()->opacity(); }
+
     // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
     int maximalOutlineSize(PaintAction p) const;