From 18b3c27c3bf42ad4b1e8fe12037a49f996dcab08 Mon Sep 17 00:00:00 2001 From: hyatt Date: Sat, 18 Mar 2006 01:01:06 +0000 Subject: [PATCH] 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): git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13366 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- WebCore/ChangeLog | 32 ++++++++++++ WebCore/rendering/RenderTableCell.cpp | 86 +++++++++++++------------------- WebCore/rendering/RenderTableCell.h | 5 +- WebCore/rendering/RenderTableRow.cpp | 19 +++++++ WebCore/rendering/RenderTableRow.h | 7 +-- WebCore/rendering/RenderTableSection.cpp | 40 ++++++++++++--- WebCore/rendering/render_layer.cpp | 28 +++++++++-- WebCore/rendering/render_object.cpp | 3 +- WebCore/rendering/render_object.h | 3 ++ 9 files changed, 156 insertions(+), 67 deletions(-) diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 5b7366d..4006d14 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,35 @@ +2006-03-17 David Hyatt + + 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 Reviewed by Adele. diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 9fce140..8aaf403 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -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()); diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 0781459..4fe2567 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -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; diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index 8d2b6e6..cc1c70d 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -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(child); + cell->paintBackgroundsBehindCell(i, tx, ty, this); + } + if (!child->layer()) + child->paint(i, tx, ty); + } + } +} + } diff --git a/WebCore/rendering/RenderTableRow.h b/WebCore/rendering/RenderTableRow.h index cfc1487..d9d12d3 100644 --- a/WebCore/rendering/RenderTableRow.h +++ b/WebCore/rendering/RenderTableRow.h @@ -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(parent()->parent()); } RenderTableSection* section() const { return static_cast(parent()); } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 98e3c57..ee377fe 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -29,6 +29,7 @@ #include "RenderTableSection.h" #include "RenderTableCell.h" #include "RenderTableRow.h" +#include "RenderTableCol.h" #include "DocumentImpl.h" #include "htmlnames.h" #include @@ -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); } } } diff --git a/WebCore/rendering/render_layer.cpp b/WebCore/rendering/render_layer.cpp index 13c8eec..5dd9ff2 100644 --- a/WebCore/rendering/render_layer.cpp +++ b/WebCore/rendering/render_layer.cpp @@ -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; diff --git a/WebCore/rendering/render_object.cpp b/WebCore/rendering/render_object.cpp index 3205cc5..915dd62 100644 --- a/WebCore/rendering/render_object.cpp +++ b/WebCore/rendering/render_object.cpp @@ -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 diff --git a/WebCore/rendering/render_object.h b/WebCore/rendering/render_object.h index be08ca2..68cf37b 100644 --- a/WebCore/rendering/render_object.h +++ b/WebCore/rendering/render_object.h @@ -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; -- 1.8.3.1