Commit e031dd02 authored by hyatt's avatar 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):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@13366 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f8fa72ec
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.
......@@ -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());
......
......@@ -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;
......
......@@ -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);
}
}
}
}
......@@ -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()); }
......
......@@ -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);
}
}
}
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment