Fix for 7837, make opacity work with table rows. Make transparent backgrounds
[WebKit-https.git] / WebCore / rendering / RenderTableRow.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
5  *           (C) 1997 Torben Weis (weis@kde.org)
6  *           (C) 1998 Waldo Bastian (bastian@kde.org)
7  *           (C) 1999 Lars Knoll (knoll@kde.org)
8  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
9  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include "config.h"
28 #include "RenderTableRow.h"
29 #include "RenderTableCell.h"
30 #include "DocumentImpl.h"
31 #include "htmlnames.h"
32
33 namespace WebCore {
34
35 using namespace HTMLNames;
36
37 RenderTableRow::RenderTableRow(NodeImpl* node)
38     : RenderContainer(node)
39 {
40     // init RenderObject attributes
41     setInline(false);   // our object is not Inline
42 }
43
44 void RenderTableRow::destroy()
45 {
46     RenderTableSection *s = section();
47     if (s)
48         s->setNeedCellRecalc();
49     
50     RenderContainer::destroy();
51 }
52
53 void RenderTableRow::setStyle(RenderStyle* style)
54 {
55     style->setDisplay(TABLE_ROW);
56     RenderContainer::setStyle(style);
57 }
58
59 void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
60 {
61     bool isTableRow = element() && element()->hasTagName(trTag);
62     
63     if (!child->isTableCell()) {
64         if (isTableRow && child->element() && child->element()->hasTagName(formTag)) {
65             RenderContainer::addChild(child, beforeChild);
66             return;
67         }
68
69         RenderObject* last = beforeChild;
70         if (!last)
71             last = lastChild();
72         if (last && last->isAnonymous() && last->isTableCell()) {
73             last->addChild(child);
74             return;
75         }
76
77         // If beforeChild is inside an anonymous cell, insert into the cell.
78         if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
79             last->parent()->addChild(child, beforeChild);
80             return;
81         }
82
83         RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
84         RenderStyle* newStyle = new (renderArena()) RenderStyle();
85         newStyle->inheritFrom(style());
86         newStyle->setDisplay(TABLE_CELL);
87         cell->setStyle(newStyle);
88         addChild(cell, beforeChild);
89         cell->addChild(child);
90         return;
91     }
92
93     RenderTableCell* cell = static_cast<RenderTableCell*>(child);
94
95     section()->addCell(cell, this);
96     
97     RenderContainer::addChild(cell, beforeChild);
98
99     if (beforeChild || nextSibling())
100         section()->setNeedCellRecalc();
101 }
102
103 void RenderTableRow::layout()
104 {
105     KHTMLAssert(needsLayout());
106     KHTMLAssert(minMaxKnown());
107
108     for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
109         if (child->isTableCell()) {
110             RenderTableCell *cell = static_cast<RenderTableCell *>(child);
111             if (child->needsLayout()) {
112                 cell->calcVerticalMargins();
113                 cell->layout();
114                 cell->setCellTopExtra(0);
115                 cell->setCellBottomExtra(0);
116             }
117         }
118     }
119     setNeedsLayout(false);
120 }
121
122 IntRect RenderTableRow::getAbsoluteRepaintRect()
123 {
124     // For now, just repaint the whole table.
125     // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
126     // might have propagated a background color into.
127     RenderTable* parentTable = table();
128     if (parentTable)
129         return parentTable->getAbsoluteRepaintRect();
130     else
131         return IntRect();
132 }
133
134 // Hit Testing
135 bool RenderTableRow::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action)
136 {
137     // Table rows cannot ever be hit tested.  Effectively they do not exist.
138     // Just forward to our children always.
139     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
140         // FIXME: We have to skip over inline flows, since they can show up inside table rows
141         // at the moment (a demoted inline <form> for example). If we ever implement a
142         // table-specific hit-test method (which we should do for performance reasons anyway),
143         // then we can remove this check.
144         if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(info, x, y, tx, ty, action)) {
145             setInnerNode(info);
146             return true;
147         }
148     }
149     
150     return false;
151 }
152
153 void RenderTableRow::paint(PaintInfo& i, int tx, int ty)
154 {
155     assert(m_layer);
156     if (!m_layer)
157         return;
158
159     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
160         if (child->isTableCell()) {
161             // Paint the row background behind the cell.
162             if (i.phase == PaintActionBlockBackground || i.phase == PaintActionChildBlockBackground) {
163                 RenderTableCell* cell = static_cast<RenderTableCell*>(child);
164                 cell->paintBackgroundsBehindCell(i, tx, ty, this);
165             }
166             if (!child->layer())
167                 child->paint(i, tx, ty);
168         }
169     }
170 }
171
172 }