a78b2138235156cee74cfcc7b8b93c01b70e27d0
[WebKit-https.git] / Source / WebCore / rendering / updating / RenderTreeBuilderTable.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RenderTreeBuilderTable.h"
28
29 #include "RenderTableCaption.h"
30 #include "RenderTableCell.h"
31 #include "RenderTableCol.h"
32 #include "RenderTableRow.h"
33 #include "RenderTreeBuilder.h"
34
35 namespace WebCore {
36
37 RenderTreeBuilder::Table::Table(RenderTreeBuilder& builder)
38     : m_builder(builder)
39 {
40 }
41
42 RenderElement& RenderTreeBuilder::Table::findOrCreateParentForChild(RenderTableRow& parent, const RenderObject& child, RenderObject*& beforeChild)
43 {
44     if (is<RenderTableCell>(child))
45         return parent;
46
47     if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == &parent) {
48         auto* previousSibling = beforeChild->previousSibling();
49         if (is<RenderTableCell>(previousSibling) && previousSibling->isAnonymous()) {
50             beforeChild = nullptr;
51             return downcast<RenderElement>(*previousSibling);
52         }
53     }
54
55     auto* lastChild = beforeChild ? beforeChild : parent.lastCell();
56     if (lastChild) {
57         if (is<RenderTableCell>(*lastChild) && lastChild->isAnonymous() && !lastChild->isBeforeOrAfterContent()) {
58             if (beforeChild == lastChild)
59                 beforeChild = downcast<RenderElement>(*lastChild).firstChild();
60             return downcast<RenderElement>(*lastChild);
61         }
62
63         // Try to find an anonymous container for the child.
64         if (auto* lastChildParent = lastChild->parent()) {
65             if (lastChildParent->isAnonymous() && !lastChildParent->isBeforeOrAfterContent()) {
66                 // If beforeChild is inside an anonymous cell, insert into the cell.
67                 if (!is<RenderTableCell>(*lastChild))
68                     return *lastChildParent;
69                 // If beforeChild is inside an anonymous row, insert into the row.
70                 if (is<RenderTableRow>(*lastChildParent)) {
71                     auto newCell = RenderTableCell::createAnonymousWithParentRenderer(parent);
72                     auto& cell = *newCell;
73                     m_builder.insertChild(*lastChildParent, WTFMove(newCell), beforeChild);
74                     beforeChild = nullptr;
75                     return cell;
76                 }
77             }
78         }
79     }
80     auto newCell = RenderTableCell::createAnonymousWithParentRenderer(parent);
81     auto& cell = *newCell;
82     m_builder.insertChild(parent, WTFMove(newCell), beforeChild);
83     beforeChild = nullptr;
84     return cell;
85 }
86
87 RenderElement& RenderTreeBuilder::Table::findOrCreateParentForChild(RenderTableSection& parent, const RenderObject& child, RenderObject*& beforeChild)
88 {
89     if (is<RenderTableRow>(child))
90         return parent;
91
92     auto* lastChild = beforeChild ? beforeChild : parent.lastRow();
93     if (is<RenderTableRow>(lastChild) && lastChild->isAnonymous() && !lastChild->isBeforeOrAfterContent()) {
94         if (beforeChild == lastChild)
95             beforeChild = downcast<RenderTableRow>(*lastChild).firstCell();
96         return downcast<RenderElement>(*lastChild);
97     }
98
99     if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == &parent) {
100         auto* row = beforeChild->previousSibling();
101         if (is<RenderTableRow>(row) && row->isAnonymous()) {
102             beforeChild = nullptr;
103             return downcast<RenderElement>(*row);
104         }
105     }
106
107     // If beforeChild is inside an anonymous cell/row, insert into the cell or into
108     // the anonymous row containing it, if there is one.
109     auto* parentCandidate = lastChild;
110     while (parentCandidate && parentCandidate->parent()->isAnonymous() && !is<RenderTableRow>(*parentCandidate))
111         parentCandidate = parentCandidate->parent();
112     if (is<RenderTableRow>(parentCandidate) && parentCandidate->isAnonymous() && !parentCandidate->isBeforeOrAfterContent())
113         return downcast<RenderElement>(*parentCandidate);
114
115     auto newRow = RenderTableRow::createAnonymousWithParentRenderer(parent);
116     auto& row = *newRow;
117     m_builder.insertChild(parent, WTFMove(newRow), beforeChild);
118     beforeChild = nullptr;
119     return row;
120 }
121
122 RenderElement& RenderTreeBuilder::Table::findOrCreateParentForChild(RenderTable& parent, const RenderObject& child, RenderObject*& beforeChild)
123 {
124     if (is<RenderTableCaption>(child) || is<RenderTableCol>(child) || is<RenderTableSection>(child))
125         return parent;
126
127     auto* lastChild = parent.lastChild();
128     if (!beforeChild && is<RenderTableSection>(lastChild) && lastChild->isAnonymous() && !lastChild->isBeforeContent())
129         return downcast<RenderElement>(*lastChild);
130
131     if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == &parent) {
132         auto* section = beforeChild->previousSibling();
133         if (is<RenderTableSection>(section) && section->isAnonymous()) {
134             beforeChild = nullptr;
135             return downcast<RenderElement>(*section);
136         }
137     }
138
139     auto* parentCandidate = beforeChild;
140     while (parentCandidate && parentCandidate->parent()->isAnonymous()
141         && !is<RenderTableSection>(*parentCandidate)
142         && parentCandidate->style().display() != TABLE_CAPTION
143         && parentCandidate->style().display() != TABLE_COLUMN_GROUP)
144         parentCandidate = parentCandidate->parent();
145
146     if (parentCandidate && is<RenderTableSection>(*parentCandidate) && parentCandidate->isAnonymous() && !parent.isAfterContent(parentCandidate)) {
147         if (beforeChild == parentCandidate)
148             beforeChild = downcast<RenderTableSection>(*parentCandidate).firstRow();
149         return downcast<RenderElement>(*parentCandidate);
150     }
151
152     if (beforeChild && !is<RenderTableSection>(*beforeChild)
153         && beforeChild->style().display() != TABLE_CAPTION
154         && beforeChild->style().display() != TABLE_COLUMN_GROUP)
155         beforeChild = nullptr;
156
157     auto newSection = RenderTableSection::createAnonymousWithParentRenderer(parent);
158     auto& section = *newSection;
159     m_builder.insertChild(parent, WTFMove(newSection), beforeChild);
160     beforeChild = nullptr;
161     return section;
162 }
163
164 void RenderTreeBuilder::Table::insertChild(RenderTableRow& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
165 {
166     if (beforeChild && beforeChild->parent() != &parent)
167         beforeChild = m_builder.splitAnonymousBoxesAroundChild(parent, beforeChild);
168
169     ASSERT(!beforeChild || is<RenderTableCell>(*beforeChild));
170     parent.RenderBox::addChild(m_builder, WTFMove(child), beforeChild);
171 }
172
173 void RenderTreeBuilder::Table::insertChild(RenderTableSection& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
174 {
175     if (beforeChild && beforeChild->parent() != &parent)
176         beforeChild = m_builder.splitAnonymousBoxesAroundChild(parent, beforeChild);
177
178     ASSERT(!beforeChild || is<RenderTableRow>(*beforeChild));
179     parent.RenderBox::addChild(m_builder, WTFMove(child), beforeChild);
180 }
181
182 void RenderTreeBuilder::Table::insertChild(RenderTable& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
183 {
184     if (beforeChild && beforeChild->parent() != &parent)
185         beforeChild = m_builder.splitAnonymousBoxesAroundChild(parent, beforeChild);
186
187     parent.RenderBox::addChild(m_builder, WTFMove(child), beforeChild);
188 }
189
190 bool RenderTreeBuilder::Table::childRequiresTable(const RenderElement& parent, const RenderObject& child)
191 {
192     if (is<RenderTableCol>(child)) {
193         const RenderTableCol& newTableColumn = downcast<RenderTableCol>(child);
194         bool isColumnInColumnGroup = newTableColumn.isTableColumn() && is<RenderTableCol>(parent);
195         return !is<RenderTable>(parent) && !isColumnInColumnGroup;
196     }
197     if (is<RenderTableCaption>(child))
198         return !is<RenderTable>(parent);
199
200     if (is<RenderTableSection>(child))
201         return !is<RenderTable>(parent);
202
203     if (is<RenderTableRow>(child))
204         return !is<RenderTableSection>(parent);
205
206     if (is<RenderTableCell>(child))
207         return !is<RenderTableRow>(parent);
208
209     return false;
210 }
211
212 void RenderTreeBuilder::Table::collapseAndDestroyAnonymousSiblingRows(RenderTableRow& row)
213 {
214     auto* section = row.section();
215     if (!section)
216         return;
217
218     // All siblings generated?
219     for (auto* current = section->firstRow(); current; current = current->nextRow()) {
220         if (current == &row)
221             continue;
222         if (!current->isAnonymous())
223             return;
224     }
225
226     RenderTableRow* rowToInsertInto = nullptr;
227     auto* currentRow = section->firstRow();
228     while (currentRow) {
229         if (currentRow == &row) {
230             currentRow = currentRow->nextRow();
231             continue;
232         }
233         if (!rowToInsertInto) {
234             rowToInsertInto = currentRow;
235             currentRow = currentRow->nextRow();
236             continue;
237         }
238         currentRow->moveAllChildrenTo(m_builder, rowToInsertInto, RenderBoxModelObject::NormalizeAfterInsertion::No);
239         auto toDestroy = section->takeChild(m_builder, *currentRow);
240         currentRow = currentRow->nextRow();
241     }
242     if (rowToInsertInto)
243         rowToInsertInto->setNeedsLayout();
244 }
245
246 }