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
+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.
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
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());
Length styleOrColWidth();
virtual bool requiresLayer();
+
virtual void calcMinMaxWidth();
virtual void calcWidth();
virtual void setWidth(int);
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;
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);
+ }
+ }
+}
+
}
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()); }
#include "RenderTableSection.h"
#include "RenderTableCell.h"
#include "RenderTableRow.h"
+#include "RenderTableCol.h"
#include "DocumentImpl.h"
#include "htmlnames.h"
#include <qtextstream.h>
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);
}
}
}
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;
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;
}
clipRect.intersect(paintDirtyRect);
p->save();
p->addClip(clipRect);
- p->beginTransparencyLayer(renderer()->style()->opacity());
+ p->beginTransparencyLayer(renderer()->opacity());
}
}
// 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);
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;
bool RenderObject::requiresLayer()
{
- return isRoot() || isPositioned() || isRelPositioned() || style()->opacity() < 1.0f ||
- hasOverflowClip();
+ return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip();
}
RenderBlock* RenderObject::firstLineBlock() const
// 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;