OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 LayoutBox* firstBox = flowThread.firstMultiColumnBox(); | 115 LayoutBox* firstBox = flowThread.firstMultiColumnBox(); |
116 return firstBox && (firstBox != flowThread.lastMultiColumnBox() || | 116 return firstBox && (firstBox != flowThread.lastMultiColumnBox() || |
117 firstBox->isLayoutMultiColumnSpannerPlaceholder()); | 117 firstBox->isLayoutMultiColumnSpannerPlaceholder()); |
118 } | 118 } |
119 | 119 |
120 // Find the next layout object that has the multicol container in its containing | 120 // Find the next layout object that has the multicol container in its containing |
121 // block chain, skipping nested multicol containers. | 121 // block chain, skipping nested multicol containers. |
122 static LayoutObject* nextInPreOrderAfterChildrenSkippingOutOfFlow( | 122 static LayoutObject* nextInPreOrderAfterChildrenSkippingOutOfFlow( |
123 LayoutMultiColumnFlowThread* flowThread, | 123 LayoutMultiColumnFlowThread* flowThread, |
124 LayoutObject* descendant) { | 124 LayoutObject* descendant) { |
125 ASSERT(descendant->isDescendantOf(flowThread)); | 125 DCHECK(descendant->isDescendantOf(flowThread)); |
126 LayoutObject* object = descendant->nextInPreOrderAfterChildren(flowThread); | 126 LayoutObject* object = descendant->nextInPreOrderAfterChildren(flowThread); |
127 while (object) { | 127 while (object) { |
128 // Walk through the siblings and find the first one which is either in-flow | 128 // Walk through the siblings and find the first one which is either in-flow |
129 // or has this flow thread as its containing block flow thread. | 129 // or has this flow thread as its containing block flow thread. |
130 if (!object->isOutOfFlowPositioned()) | 130 if (!object->isOutOfFlowPositioned()) |
131 break; | 131 break; |
132 if (object->containingBlock()->flowThreadContainingBlock() == flowThread) { | 132 if (object->containingBlock()->flowThreadContainingBlock() == flowThread) { |
133 // This out-of-flow object is still part of the flow thread, because its | 133 // This out-of-flow object is still part of the flow thread, because its |
134 // containing block (probably relatively positioned) is part of the flow | 134 // containing block (probably relatively positioned) is part of the flow |
135 // thread. | 135 // thread. |
136 break; | 136 break; |
137 } | 137 } |
138 object = object->nextInPreOrderAfterChildren(flowThread); | 138 object = object->nextInPreOrderAfterChildren(flowThread); |
139 } | 139 } |
140 if (!object) | 140 if (!object) |
141 return nullptr; | 141 return nullptr; |
142 #if DCHECK_IS_ON() | 142 #if DCHECK_IS_ON() |
143 // Make sure that we didn't stumble into an inner multicol container. | 143 // Make sure that we didn't stumble into an inner multicol container. |
144 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; | 144 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; |
145 walker = walker->parent()) | 145 walker = walker->parent()) |
146 ASSERT(!isMultiColumnContainer(*walker)); | 146 DCHECK(!isMultiColumnContainer(*walker)); |
147 #endif | 147 #endif |
148 return object; | 148 return object; |
149 } | 149 } |
150 | 150 |
151 // Find the previous layout object that has the multicol container in its | 151 // Find the previous layout object that has the multicol container in its |
152 // containing block chain, skipping nested multicol containers. | 152 // containing block chain, skipping nested multicol containers. |
153 static LayoutObject* previousInPreOrderSkippingOutOfFlow( | 153 static LayoutObject* previousInPreOrderSkippingOutOfFlow( |
154 LayoutMultiColumnFlowThread* flowThread, | 154 LayoutMultiColumnFlowThread* flowThread, |
155 LayoutObject* descendant) { | 155 LayoutObject* descendant) { |
156 ASSERT(descendant->isDescendantOf(flowThread)); | 156 DCHECK(descendant->isDescendantOf(flowThread)); |
157 LayoutObject* object = descendant->previousInPreOrder(flowThread); | 157 LayoutObject* object = descendant->previousInPreOrder(flowThread); |
158 while (object && object != flowThread) { | 158 while (object && object != flowThread) { |
159 if (object->isColumnSpanAll()) { | 159 if (object->isColumnSpanAll()) { |
160 LayoutMultiColumnFlowThread* placeholderFlowThread = | 160 LayoutMultiColumnFlowThread* placeholderFlowThread = |
161 toLayoutBox(object)->spannerPlaceholder()->flowThread(); | 161 toLayoutBox(object)->spannerPlaceholder()->flowThread(); |
162 if (placeholderFlowThread == flowThread) | 162 if (placeholderFlowThread == flowThread) |
163 break; | 163 break; |
164 // We're inside an inner multicol container. We have no business there. | 164 // We're inside an inner multicol container. We have no business there. |
165 // Continue on the outside. | 165 // Continue on the outside. |
166 object = placeholderFlowThread->parent(); | 166 object = placeholderFlowThread->parent(); |
167 ASSERT(object->isDescendantOf(flowThread)); | 167 DCHECK(object->isDescendantOf(flowThread)); |
168 continue; | 168 continue; |
169 } | 169 } |
170 if (object->flowThreadContainingBlock() == flowThread) { | 170 if (object->flowThreadContainingBlock() == flowThread) { |
171 LayoutObject* ancestor; | 171 LayoutObject* ancestor; |
172 for (ancestor = object->parent();; ancestor = ancestor->parent()) { | 172 for (ancestor = object->parent();; ancestor = ancestor->parent()) { |
173 if (ancestor == flowThread) | 173 if (ancestor == flowThread) |
174 return object; | 174 return object; |
175 if (isMultiColumnContainer(*ancestor)) { | 175 if (isMultiColumnContainer(*ancestor)) { |
176 // We're inside an inner multicol container. We have no business | 176 // We're inside an inner multicol container. We have no business |
177 // there. | 177 // there. |
178 break; | 178 break; |
179 } | 179 } |
180 } | 180 } |
181 object = ancestor; | 181 object = ancestor; |
182 ASSERT(ancestor->isDescendantOf(flowThread)); | 182 DCHECK(ancestor->isDescendantOf(flowThread)); |
183 continue; // Continue on the outside of the inner flow thread. | 183 continue; // Continue on the outside of the inner flow thread. |
184 } | 184 } |
185 // We're inside something that's out-of-flow. Keep looking upwards and | 185 // We're inside something that's out-of-flow. Keep looking upwards and |
186 // backwards in the tree. | 186 // backwards in the tree. |
187 object = object->previousInPreOrder(flowThread); | 187 object = object->previousInPreOrder(flowThread); |
188 } | 188 } |
189 if (!object || object == flowThread) | 189 if (!object || object == flowThread) |
190 return nullptr; | 190 return nullptr; |
191 #if DCHECK_IS_ON() | 191 #if DCHECK_IS_ON() |
192 // Make sure that we didn't stumble into an inner multicol container. | 192 // Make sure that we didn't stumble into an inner multicol container. |
193 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; | 193 for (LayoutObject* walker = object->parent(); walker && walker != flowThread; |
194 walker = walker->parent()) | 194 walker = walker->parent()) |
195 ASSERT(!isMultiColumnContainer(*walker)); | 195 DCHECK(!isMultiColumnContainer(*walker)); |
196 #endif | 196 #endif |
197 return object; | 197 return object; |
198 } | 198 } |
199 | 199 |
200 static LayoutObject* firstLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { | 200 static LayoutObject* firstLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { |
201 LayoutBox* sibling = multicolSet->previousSiblingMultiColumnBox(); | 201 LayoutBox* sibling = multicolSet->previousSiblingMultiColumnBox(); |
202 if (!sibling) | 202 if (!sibling) |
203 return multicolSet->flowThread()->firstChild(); | 203 return multicolSet->flowThread()->firstChild(); |
204 // Adjacent column content sets should not occur. We would have no way of | 204 // Adjacent column content sets should not occur. We would have no way of |
205 // figuring out what each of them contains then. | 205 // figuring out what each of them contains then. |
206 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder()); | 206 DCHECK(sibling->isLayoutMultiColumnSpannerPlaceholder()); |
207 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) | 207 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) |
208 ->layoutObjectInFlowThread(); | 208 ->layoutObjectInFlowThread(); |
209 return nextInPreOrderAfterChildrenSkippingOutOfFlow( | 209 return nextInPreOrderAfterChildrenSkippingOutOfFlow( |
210 multicolSet->multiColumnFlowThread(), spanner); | 210 multicolSet->multiColumnFlowThread(), spanner); |
211 } | 211 } |
212 | 212 |
213 static LayoutObject* lastLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { | 213 static LayoutObject* lastLayoutObjectInSet(LayoutMultiColumnSet* multicolSet) { |
214 LayoutBox* sibling = multicolSet->nextSiblingMultiColumnBox(); | 214 LayoutBox* sibling = multicolSet->nextSiblingMultiColumnBox(); |
215 // By right we should return lastLeafChild() here, but the caller doesn't | 215 // By right we should return lastLeafChild() here, but the caller doesn't |
216 // care, so just return nullptr. | 216 // care, so just return nullptr. |
217 if (!sibling) | 217 if (!sibling) |
218 return nullptr; | 218 return nullptr; |
219 // Adjacent column content sets should not occur. We would have no way of | 219 // Adjacent column content sets should not occur. We would have no way of |
220 // figuring out what each of them contains then. | 220 // figuring out what each of them contains then. |
221 ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder()); | 221 DCHECK(sibling->isLayoutMultiColumnSpannerPlaceholder()); |
222 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) | 222 LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling) |
223 ->layoutObjectInFlowThread(); | 223 ->layoutObjectInFlowThread(); |
224 return previousInPreOrderSkippingOutOfFlow( | 224 return previousInPreOrderSkippingOutOfFlow( |
225 multicolSet->multiColumnFlowThread(), spanner); | 225 multicolSet->multiColumnFlowThread(), spanner); |
226 } | 226 } |
227 | 227 |
228 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::mapDescendantToColumnSet( | 228 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::mapDescendantToColumnSet( |
229 LayoutObject* layoutObject) const { | 229 LayoutObject* layoutObject) const { |
230 // Should not be used for spanners or content inside them. | 230 // Should not be used for spanners or content inside them. |
231 DCHECK(!containingColumnSpannerPlaceholder(layoutObject)); | 231 DCHECK(!containingColumnSpannerPlaceholder(layoutObject)); |
232 DCHECK(layoutObject != this); | 232 DCHECK_NE(layoutObject, this); |
233 DCHECK(layoutObject->isDescendantOf(this)); | 233 DCHECK(layoutObject->isDescendantOf(this)); |
234 // Out-of-flow objects don't belong in column sets. | 234 // Out-of-flow objects don't belong in column sets. |
235 DCHECK(layoutObject->containingBlock()->isDescendantOf(this)); | 235 DCHECK(layoutObject->containingBlock()->isDescendantOf(this)); |
236 DCHECK(layoutObject->flowThreadContainingBlock() == this); | 236 DCHECK_EQ(layoutObject->flowThreadContainingBlock(), this); |
237 DCHECK(!layoutObject->isLayoutMultiColumnSet()); | 237 DCHECK(!layoutObject->isLayoutMultiColumnSet()); |
238 DCHECK(!layoutObject->isLayoutMultiColumnSpannerPlaceholder()); | 238 DCHECK(!layoutObject->isLayoutMultiColumnSpannerPlaceholder()); |
239 LayoutMultiColumnSet* multicolSet = firstMultiColumnSet(); | 239 LayoutMultiColumnSet* multicolSet = firstMultiColumnSet(); |
240 if (!multicolSet) | 240 if (!multicolSet) |
241 return nullptr; | 241 return nullptr; |
242 if (!multicolSet->nextSiblingMultiColumnSet()) | 242 if (!multicolSet->nextSiblingMultiColumnSet()) |
243 return multicolSet; | 243 return multicolSet; |
244 | 244 |
245 // This is potentially SLOW! But luckily very uncommon. You would have to | 245 // This is potentially SLOW! But luckily very uncommon. You would have to |
246 // dynamically insert a spanner into the middle of column contents to need | 246 // dynamically insert a spanner into the middle of column contents to need |
247 // this. | 247 // this. |
248 for (; multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { | 248 for (; multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { |
249 LayoutObject* firstLayoutObject = firstLayoutObjectInSet(multicolSet); | 249 LayoutObject* firstLayoutObject = firstLayoutObjectInSet(multicolSet); |
250 LayoutObject* lastLayoutObject = lastLayoutObjectInSet(multicolSet); | 250 LayoutObject* lastLayoutObject = lastLayoutObjectInSet(multicolSet); |
251 ASSERT(firstLayoutObject); | 251 DCHECK(firstLayoutObject); |
252 | 252 |
253 for (LayoutObject* walker = firstLayoutObject; walker; | 253 for (LayoutObject* walker = firstLayoutObject; walker; |
254 walker = walker->nextInPreOrder(this)) { | 254 walker = walker->nextInPreOrder(this)) { |
255 if (walker == layoutObject) | 255 if (walker == layoutObject) |
256 return multicolSet; | 256 return multicolSet; |
257 if (walker == lastLayoutObject) | 257 if (walker == lastLayoutObject) |
258 break; | 258 break; |
259 } | 259 } |
260 } | 260 } |
261 | 261 |
262 return nullptr; | 262 return nullptr; |
263 } | 263 } |
264 | 264 |
265 LayoutMultiColumnSpannerPlaceholder* | 265 LayoutMultiColumnSpannerPlaceholder* |
266 LayoutMultiColumnFlowThread::containingColumnSpannerPlaceholder( | 266 LayoutMultiColumnFlowThread::containingColumnSpannerPlaceholder( |
267 const LayoutObject* descendant) const { | 267 const LayoutObject* descendant) const { |
268 ASSERT(descendant->isDescendantOf(this)); | 268 DCHECK(descendant->isDescendantOf(this)); |
269 | 269 |
270 if (!hasAnyColumnSpanners(*this)) | 270 if (!hasAnyColumnSpanners(*this)) |
271 return nullptr; | 271 return nullptr; |
272 | 272 |
273 // We have spanners. See if the layoutObject in question is one or inside of | 273 // We have spanners. See if the layoutObject in question is one or inside of |
274 // one then. | 274 // one then. |
275 for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this; | 275 for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this; |
276 ancestor = ancestor->parent()) { | 276 ancestor = ancestor->parent()) { |
277 if (LayoutMultiColumnSpannerPlaceholder* placeholder = | 277 if (LayoutMultiColumnSpannerPlaceholder* placeholder = |
278 ancestor->spannerPlaceholder()) | 278 ancestor->spannerPlaceholder()) |
279 return placeholder; | 279 return placeholder; |
280 } | 280 } |
281 return nullptr; | 281 return nullptr; |
282 } | 282 } |
283 | 283 |
284 void LayoutMultiColumnFlowThread::populate() { | 284 void LayoutMultiColumnFlowThread::populate() { |
285 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 285 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
286 ASSERT(!nextSibling()); | 286 DCHECK(!nextSibling()); |
287 // Reparent children preceding the flow thread into the flow thread. It's | 287 // Reparent children preceding the flow thread into the flow thread. It's |
288 // multicol content now. At this point there's obviously nothing after the | 288 // multicol content now. At this point there's obviously nothing after the |
289 // flow thread, but layoutObjects (column sets and spanners) will be inserted | 289 // flow thread, but layoutObjects (column sets and spanners) will be inserted |
290 // there as we insert elements into the flow thread. | 290 // there as we insert elements into the flow thread. |
291 multicolContainer->removeFloatingObjectsFromDescendants(); | 291 multicolContainer->removeFloatingObjectsFromDescendants(); |
292 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, | 292 multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, |
293 true); | 293 true); |
294 } | 294 } |
295 | 295 |
296 void LayoutMultiColumnFlowThread::evacuateAndDestroy() { | 296 void LayoutMultiColumnFlowThread::evacuateAndDestroy() { |
297 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 297 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
298 m_isBeingEvacuated = true; | 298 m_isBeingEvacuated = true; |
299 | 299 |
300 // Remove all sets and spanners. | 300 // Remove all sets and spanners. |
301 while (LayoutBox* columnBox = firstMultiColumnBox()) { | 301 while (LayoutBox* columnBox = firstMultiColumnBox()) { |
302 ASSERT(columnBox->isAnonymous()); | 302 DCHECK(columnBox->isAnonymous()); |
303 columnBox->destroy(); | 303 columnBox->destroy(); |
304 } | 304 } |
305 | 305 |
306 ASSERT(!previousSibling()); | 306 DCHECK(!previousSibling()); |
307 ASSERT(!nextSibling()); | 307 DCHECK(!nextSibling()); |
308 | 308 |
309 // Finally we can promote all flow thread's children. Before we move them to | 309 // Finally we can promote all flow thread's children. Before we move them to |
310 // the flow thread's container, we need to unregister the flow thread, so that | 310 // the flow thread's container, we need to unregister the flow thread, so that |
311 // they aren't just re-added again to the flow thread that we're trying to | 311 // they aren't just re-added again to the flow thread that we're trying to |
312 // empty. | 312 // empty. |
313 multicolContainer->resetMultiColumnFlowThread(); | 313 multicolContainer->resetMultiColumnFlowThread(); |
314 moveAllChildrenTo(multicolContainer, true); | 314 moveAllChildrenTo(multicolContainer, true); |
315 | 315 |
316 // We used to manually nuke the line box tree here, but that should happen | 316 // We used to manually nuke the line box tree here, but that should happen |
317 // automatically when moving children around (the code above). | 317 // automatically when moving children around (the code above). |
318 ASSERT(!firstLineBox()); | 318 DCHECK(!firstLineBox()); |
319 | 319 |
320 destroy(); | 320 destroy(); |
321 } | 321 } |
322 | 322 |
323 LayoutUnit LayoutMultiColumnFlowThread::maxColumnLogicalHeight() const { | 323 LayoutUnit LayoutMultiColumnFlowThread::maxColumnLogicalHeight() const { |
324 if (m_columnHeightAvailable) { | 324 if (m_columnHeightAvailable) { |
325 // If height is non-auto, it's already constrained against max-height as | 325 // If height is non-auto, it's already constrained against max-height as |
326 // well. Just return it. | 326 // well. Just return it. |
327 return m_columnHeightAvailable; | 327 return m_columnHeightAvailable; |
328 } | 328 } |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 } | 570 } |
571 | 571 |
572 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() { | 572 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() { |
573 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; | 573 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; |
574 columnSet = columnSet->nextSiblingMultiColumnSet()) | 574 columnSet = columnSet->nextSiblingMultiColumnSet()) |
575 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange); | 575 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange); |
576 } | 576 } |
577 | 577 |
578 bool LayoutMultiColumnFlowThread::removeSpannerPlaceholderIfNoLongerValid( | 578 bool LayoutMultiColumnFlowThread::removeSpannerPlaceholderIfNoLongerValid( |
579 LayoutBox* spannerObjectInFlowThread) { | 579 LayoutBox* spannerObjectInFlowThread) { |
580 ASSERT(spannerObjectInFlowThread->spannerPlaceholder()); | 580 DCHECK(spannerObjectInFlowThread->spannerPlaceholder()); |
581 if (descendantIsValidColumnSpanner(spannerObjectInFlowThread)) | 581 if (descendantIsValidColumnSpanner(spannerObjectInFlowThread)) |
582 return false; // Still a valid spanner. | 582 return false; // Still a valid spanner. |
583 | 583 |
584 // No longer a valid spanner. Get rid of the placeholder. | 584 // No longer a valid spanner. Get rid of the placeholder. |
585 destroySpannerPlaceholder(spannerObjectInFlowThread->spannerPlaceholder()); | 585 destroySpannerPlaceholder(spannerObjectInFlowThread->spannerPlaceholder()); |
586 ASSERT(!spannerObjectInFlowThread->spannerPlaceholder()); | 586 DCHECK(!spannerObjectInFlowThread->spannerPlaceholder()); |
587 | 587 |
588 // We may have a new containing block, since we're no longer a spanner. Mark | 588 // We may have a new containing block, since we're no longer a spanner. Mark |
589 // it for relayout. | 589 // it for relayout. |
590 spannerObjectInFlowThread->containingBlock() | 590 spannerObjectInFlowThread->containingBlock() |
591 ->setNeedsLayoutAndPrefWidthsRecalc( | 591 ->setNeedsLayoutAndPrefWidthsRecalc( |
592 LayoutInvalidationReason::ColumnsChanged); | 592 LayoutInvalidationReason::ColumnsChanged); |
593 | 593 |
594 // Now generate a column set for this ex-spanner, if needed and none is there | 594 // Now generate a column set for this ex-spanner, if needed and none is there |
595 // for us already. | 595 // for us already. |
596 flowThreadDescendantWasInserted(spannerObjectInFlowThread); | 596 flowThreadDescendantWasInserted(spannerObjectInFlowThread); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 lastRow.blockOffsetInEnclosingFragmentationContext() + | 663 lastRow.blockOffsetInEnclosingFragmentationContext() + |
664 lastRow.logicalHeight(); | 664 lastRow.logicalHeight(); |
665 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded( | 665 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded( |
666 logicalOffsetInOuter, AssociateWithLatterPage); | 666 logicalOffsetInOuter, AssociateWithLatterPage); |
667 } | 667 } |
668 | 668 |
669 const MultiColumnFragmentainerGroup& newRow = | 669 const MultiColumnFragmentainerGroup& newRow = |
670 columnSet->appendNewFragmentainerGroup(); | 670 columnSet->appendNewFragmentainerGroup(); |
671 // Zero-height rows should really not occur here, but if it does anyway, | 671 // Zero-height rows should really not occur here, but if it does anyway, |
672 // break, so that we don't get stuck in an infinite loop. | 672 // break, so that we don't get stuck in an infinite loop. |
673 ASSERT(newRow.logicalHeight() > 0); | 673 DCHECK_GT(newRow.logicalHeight(), 0); |
674 if (newRow.logicalHeight() <= 0) | 674 if (newRow.logicalHeight() <= 0) |
675 break; | 675 break; |
676 } while (columnSet->needsNewFragmentainerGroupAt(offsetInFlowThread, | 676 } while (columnSet->needsNewFragmentainerGroupAt(offsetInFlowThread, |
677 pageBoundaryRule)); | 677 pageBoundaryRule)); |
678 } | 678 } |
679 } | 679 } |
680 | 680 |
681 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() { | 681 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() { |
682 return isPageLogicalHeightKnown(); | 682 return isPageLogicalHeightKnown(); |
683 } | 683 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 LayoutUnit& width, | 721 LayoutUnit& width, |
722 unsigned& count) const { | 722 unsigned& count) const { |
723 LayoutBlock* columnBlock = multiColumnBlockFlow(); | 723 LayoutBlock* columnBlock = multiColumnBlockFlow(); |
724 const ComputedStyle* columnStyle = columnBlock->style(); | 724 const ComputedStyle* columnStyle = columnBlock->style(); |
725 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); | 725 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); |
726 LayoutUnit columnGap = LayoutUnit(columnBlock->columnGap()); | 726 LayoutUnit columnGap = LayoutUnit(columnBlock->columnGap()); |
727 LayoutUnit computedColumnWidth = | 727 LayoutUnit computedColumnWidth = |
728 max(LayoutUnit(1), LayoutUnit(columnStyle->columnWidth())); | 728 max(LayoutUnit(1), LayoutUnit(columnStyle->columnWidth())); |
729 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); | 729 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); |
730 | 730 |
731 ASSERT(!columnStyle->hasAutoColumnCount() || | 731 DCHECK(!columnStyle->hasAutoColumnCount() || |
732 !columnStyle->hasAutoColumnWidth()); | 732 !columnStyle->hasAutoColumnWidth()); |
733 if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount()) { | 733 if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount()) { |
734 count = computedColumnCount; | 734 count = computedColumnCount; |
735 width = ((availableWidth - ((count - 1) * columnGap)) / count) | 735 width = ((availableWidth - ((count - 1) * columnGap)) / count) |
736 .clampNegativeToZero(); | 736 .clampNegativeToZero(); |
737 } else if (!columnStyle->hasAutoColumnWidth() && | 737 } else if (!columnStyle->hasAutoColumnWidth() && |
738 columnStyle->hasAutoColumnCount()) { | 738 columnStyle->hasAutoColumnCount()) { |
739 count = std::max(LayoutUnit(1), (availableWidth + columnGap) / | 739 count = std::max(LayoutUnit(1), (availableWidth + columnGap) / |
740 (computedColumnWidth + columnGap)) | 740 (computedColumnWidth + columnGap)) |
741 .toUnsigned(); | 741 .toUnsigned(); |
(...skipping 11 matching lines...) Expand all Loading... |
753 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet( | 753 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet( |
754 LayoutBox* insertBefore) { | 754 LayoutBox* insertBefore) { |
755 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 755 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
756 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous( | 756 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous( |
757 *this, multicolContainer->styleRef()); | 757 *this, multicolContainer->styleRef()); |
758 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); | 758 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); |
759 invalidateColumnSets(); | 759 invalidateColumnSets(); |
760 | 760 |
761 // We cannot handle immediate column set siblings (and there's no need for it, | 761 // We cannot handle immediate column set siblings (and there's no need for it, |
762 // either). There has to be at least one spanner separating them. | 762 // either). There has to be at least one spanner separating them. |
763 ASSERT(!newSet->previousSiblingMultiColumnBox() || | 763 DCHECK(!newSet->previousSiblingMultiColumnBox() || |
764 !newSet->previousSiblingMultiColumnBox()->isLayoutMultiColumnSet()); | 764 !newSet->previousSiblingMultiColumnBox()->isLayoutMultiColumnSet()); |
765 ASSERT(!newSet->nextSiblingMultiColumnBox() || | 765 DCHECK(!newSet->nextSiblingMultiColumnBox() || |
766 !newSet->nextSiblingMultiColumnBox()->isLayoutMultiColumnSet()); | 766 !newSet->nextSiblingMultiColumnBox()->isLayoutMultiColumnSet()); |
767 } | 767 } |
768 | 768 |
769 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder( | 769 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder( |
770 LayoutBox* spannerObjectInFlowThread, | 770 LayoutBox* spannerObjectInFlowThread, |
771 LayoutObject* insertedBeforeInFlowThread) { | 771 LayoutObject* insertedBeforeInFlowThread) { |
772 LayoutBox* insertBeforeColumnBox = nullptr; | 772 LayoutBox* insertBeforeColumnBox = nullptr; |
773 LayoutMultiColumnSet* setToSplit = nullptr; | 773 LayoutMultiColumnSet* setToSplit = nullptr; |
774 if (insertedBeforeInFlowThread) { | 774 if (insertedBeforeInFlowThread) { |
775 // The spanner is inserted before something. Figure out what this entails. | 775 // The spanner is inserted before something. Figure out what this entails. |
(...skipping 13 matching lines...) Expand all Loading... |
789 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = | 789 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = |
790 containingColumnSpannerPlaceholder(previousLayoutObject)) { | 790 containingColumnSpannerPlaceholder(previousLayoutObject)) { |
791 // Before us is another spanner. We belong right after it then. | 791 // Before us is another spanner. We belong right after it then. |
792 insertBeforeColumnBox = | 792 insertBeforeColumnBox = |
793 previousPlaceholder->nextSiblingMultiColumnBox(); | 793 previousPlaceholder->nextSiblingMultiColumnBox(); |
794 } else { | 794 } else { |
795 // We're inside regular column content with both feet. Find out which | 795 // We're inside regular column content with both feet. Find out which |
796 // column set this is. It needs to be split it into two sets, so that we | 796 // column set this is. It needs to be split it into two sets, so that we |
797 // can insert a new spanner placeholder between them. | 797 // can insert a new spanner placeholder between them. |
798 setToSplit = mapDescendantToColumnSet(previousLayoutObject); | 798 setToSplit = mapDescendantToColumnSet(previousLayoutObject); |
799 ASSERT(setToSplit == | 799 DCHECK_EQ(setToSplit, |
800 mapDescendantToColumnSet(insertedBeforeInFlowThread)); | 800 mapDescendantToColumnSet(insertedBeforeInFlowThread)); |
801 insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox(); | 801 insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox(); |
802 // We've found out which set that needs to be split. Now proceed to | 802 // We've found out which set that needs to be split. Now proceed to |
803 // inserting the spanner placeholder, and then insert a second column | 803 // inserting the spanner placeholder, and then insert a second column |
804 // set. | 804 // set. |
805 } | 805 } |
806 } | 806 } |
807 ASSERT(setToSplit || insertBeforeColumnBox); | 807 DCHECK(setToSplit || insertBeforeColumnBox); |
808 } | 808 } |
809 | 809 |
810 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 810 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
811 LayoutMultiColumnSpannerPlaceholder* newPlaceholder = | 811 LayoutMultiColumnSpannerPlaceholder* newPlaceholder = |
812 LayoutMultiColumnSpannerPlaceholder::createAnonymous( | 812 LayoutMultiColumnSpannerPlaceholder::createAnonymous( |
813 multicolContainer->styleRef(), *spannerObjectInFlowThread); | 813 multicolContainer->styleRef(), *spannerObjectInFlowThread); |
814 ASSERT(!insertBeforeColumnBox || | 814 DCHECK(!insertBeforeColumnBox || |
815 insertBeforeColumnBox->parent() == multicolContainer); | 815 insertBeforeColumnBox->parent() == multicolContainer); |
816 multicolContainer->LayoutBlock::addChild(newPlaceholder, | 816 multicolContainer->LayoutBlock::addChild(newPlaceholder, |
817 insertBeforeColumnBox); | 817 insertBeforeColumnBox); |
818 spannerObjectInFlowThread->setSpannerPlaceholder(*newPlaceholder); | 818 spannerObjectInFlowThread->setSpannerPlaceholder(*newPlaceholder); |
819 | 819 |
820 if (setToSplit) | 820 if (setToSplit) |
821 createAndInsertMultiColumnSet(insertBeforeColumnBox); | 821 createAndInsertMultiColumnSet(insertBeforeColumnBox); |
822 } | 822 } |
823 | 823 |
824 void LayoutMultiColumnFlowThread::destroySpannerPlaceholder( | 824 void LayoutMultiColumnFlowThread::destroySpannerPlaceholder( |
(...skipping 17 matching lines...) Expand all Loading... |
842 // one (return true). | 842 // one (return true). |
843 // - When the descendant doesn't have a spanner placeholder and still should | 843 // - When the descendant doesn't have a spanner placeholder and still should |
844 // not have one (return false). | 844 // not have one (return false). |
845 // - When the descendant has a spanner placeholder but should no longer have | 845 // - When the descendant has a spanner placeholder but should no longer have |
846 // one (return false). | 846 // one (return false). |
847 // - When the descendant has a spanner placeholder and should still have one | 847 // - When the descendant has a spanner placeholder and should still have one |
848 // (return true). | 848 // (return true). |
849 | 849 |
850 // We assume that we're inside the flow thread. This function is not to be | 850 // We assume that we're inside the flow thread. This function is not to be |
851 // called otherwise. | 851 // called otherwise. |
852 ASSERT(descendant->isDescendantOf(this)); | 852 DCHECK(descendant->isDescendantOf(this)); |
853 | 853 |
854 // The spec says that column-span only applies to in-flow block-level | 854 // The spec says that column-span only applies to in-flow block-level |
855 // elements. | 855 // elements. |
856 if (descendant->style()->getColumnSpan() != ColumnSpanAll || | 856 if (descendant->style()->getColumnSpan() != ColumnSpanAll || |
857 !descendant->isBox() || descendant->isInline() || | 857 !descendant->isBox() || descendant->isInline() || |
858 descendant->isFloatingOrOutOfFlowPositioned()) | 858 descendant->isFloatingOrOutOfFlowPositioned()) |
859 return false; | 859 return false; |
860 | 860 |
861 if (!descendant->containingBlock()->isLayoutBlockFlow()) { | 861 if (!descendant->containingBlock()->isLayoutBlockFlow()) { |
862 // Needs to be in a block-flow container, and not e.g. a table. | 862 // Needs to be in a block-flow container, and not e.g. a table. |
863 return false; | 863 return false; |
864 } | 864 } |
865 | 865 |
866 // This looks like a spanner, but if we're inside something unbreakable or | 866 // This looks like a spanner, but if we're inside something unbreakable or |
867 // something that establishes a new formatting context, it's not to be treated | 867 // something that establishes a new formatting context, it's not to be treated |
868 // as one. | 868 // as one. |
869 for (LayoutBox* ancestor = toLayoutBox(descendant)->parentBox(); ancestor; | 869 for (LayoutBox* ancestor = toLayoutBox(descendant)->parentBox(); ancestor; |
870 ancestor = ancestor->containingBlock()) { | 870 ancestor = ancestor->containingBlock()) { |
871 if (ancestor->isLayoutFlowThread()) { | 871 if (ancestor->isLayoutFlowThread()) { |
872 ASSERT(ancestor == this); | 872 DCHECK_EQ(ancestor, this); |
873 return true; | 873 return true; |
874 } | 874 } |
875 if (!canContainSpannerInParentFragmentationContext(*ancestor)) | 875 if (!canContainSpannerInParentFragmentationContext(*ancestor)) |
876 return false; | 876 return false; |
877 } | 877 } |
878 NOTREACHED(); | 878 NOTREACHED(); |
879 return false; | 879 return false; |
880 } | 880 } |
881 | 881 |
882 void LayoutMultiColumnFlowThread::addColumnSetToThread( | 882 void LayoutMultiColumnFlowThread::addColumnSetToThread( |
883 LayoutMultiColumnSet* columnSet) { | 883 LayoutMultiColumnSet* columnSet) { |
884 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { | 884 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { |
885 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSet); | 885 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSet); |
886 ASSERT(it != m_multiColumnSetList.end()); | 886 DCHECK(it != m_multiColumnSetList.end()); |
887 m_multiColumnSetList.insertBefore(it, columnSet); | 887 m_multiColumnSetList.insertBefore(it, columnSet); |
888 } else { | 888 } else { |
889 m_multiColumnSetList.insert(columnSet); | 889 m_multiColumnSetList.insert(columnSet); |
890 } | 890 } |
891 } | 891 } |
892 | 892 |
893 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() { | 893 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() { |
894 // Detach all column sets from the flow thread. Cannot destroy them at this | 894 // Detach all column sets from the flow thread. Cannot destroy them at this |
895 // point, since they are siblings of this object, and there may be pointers to | 895 // point, since they are siblings of this object, and there may be pointers to |
896 // this object's sibling somewhere further up on the call stack. | 896 // this object's sibling somewhere further up on the call stack. |
897 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; | 897 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; |
898 columnSet = columnSet->nextSiblingMultiColumnSet()) | 898 columnSet = columnSet->nextSiblingMultiColumnSet()) |
899 columnSet->detachFromFlowThread(); | 899 columnSet->detachFromFlowThread(); |
900 multiColumnBlockFlow()->resetMultiColumnFlowThread(); | 900 multiColumnBlockFlow()->resetMultiColumnFlowThread(); |
901 LayoutFlowThread::willBeRemovedFromTree(); | 901 LayoutFlowThread::willBeRemovedFromTree(); |
902 } | 902 } |
903 | 903 |
904 void LayoutMultiColumnFlowThread::skipColumnSpanner( | 904 void LayoutMultiColumnFlowThread::skipColumnSpanner( |
905 LayoutBox* layoutObject, | 905 LayoutBox* layoutObject, |
906 LayoutUnit logicalTopInFlowThread) { | 906 LayoutUnit logicalTopInFlowThread) { |
907 ASSERT(layoutObject->isColumnSpanAll()); | 907 DCHECK(layoutObject->isColumnSpanAll()); |
908 LayoutMultiColumnSpannerPlaceholder* placeholder = | 908 LayoutMultiColumnSpannerPlaceholder* placeholder = |
909 layoutObject->spannerPlaceholder(); | 909 layoutObject->spannerPlaceholder(); |
910 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); | 910 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); |
911 if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) | 911 if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) |
912 toLayoutMultiColumnSet(previousColumnBox)->endFlow(logicalTopInFlowThread); | 912 toLayoutMultiColumnSet(previousColumnBox)->endFlow(logicalTopInFlowThread); |
913 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); | 913 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); |
914 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) { | 914 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) { |
915 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox); | 915 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox); |
916 m_lastSetWorkedOn = nextSet; | 916 m_lastSetWorkedOn = nextSet; |
917 nextSet->beginFlow(logicalTopInFlowThread); | 917 nextSet->beginFlow(logicalTopInFlowThread); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 child.containingBlock()->flowThreadContainingBlock() != flowThread) { | 959 child.containingBlock()->flowThreadContainingBlock() != flowThread) { |
960 // Out-of-flow with its containing block on the outside of the multicol | 960 // Out-of-flow with its containing block on the outside of the multicol |
961 // container. | 961 // container. |
962 return true; | 962 return true; |
963 } | 963 } |
964 return false; | 964 return false; |
965 } | 965 } |
966 | 966 |
967 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted( | 967 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted( |
968 LayoutObject* descendant) { | 968 LayoutObject* descendant) { |
969 ASSERT(!m_isBeingEvacuated); | 969 DCHECK(!m_isBeingEvacuated); |
970 // This method ensures that the list of column sets and spanner placeholders | 970 // This method ensures that the list of column sets and spanner placeholders |
971 // reflects the multicol content after having inserted a descendant (or | 971 // reflects the multicol content after having inserted a descendant (or |
972 // descendant subtree). See the header file for more information. Go through | 972 // descendant subtree). See the header file for more information. Go through |
973 // the subtree that was just inserted and create column sets (needed by | 973 // the subtree that was just inserted and create column sets (needed by |
974 // regular column content) and spanner placeholders (one needed by each | 974 // regular column content) and spanner placeholders (one needed by each |
975 // spanner) where needed. | 975 // spanner) where needed. |
976 if (shouldSkipInsertedOrRemovedChild(this, *descendant)) | 976 if (shouldSkipInsertedOrRemovedChild(this, *descendant)) |
977 return; | 977 return; |
978 LayoutObject* objectAfterSubtree = | 978 LayoutObject* objectAfterSubtree = |
979 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); | 979 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); |
(...skipping 22 matching lines...) Expand all Loading... |
1002 objectAfterSubtree->spannerPlaceholder()) { | 1002 objectAfterSubtree->spannerPlaceholder()) { |
1003 // If inserted right before a spanner, we need to make sure that there's | 1003 // If inserted right before a spanner, we need to make sure that there's |
1004 // a set for us there. | 1004 // a set for us there. |
1005 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox(); | 1005 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox(); |
1006 if (!previous || !previous->isLayoutMultiColumnSet()) | 1006 if (!previous || !previous->isLayoutMultiColumnSet()) |
1007 createAndInsertMultiColumnSet(placeholder); | 1007 createAndInsertMultiColumnSet(placeholder); |
1008 } else { | 1008 } else { |
1009 // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean | 1009 // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean |
1010 // that there's already a set for that content. We can use it for this | 1010 // that there's already a set for that content. We can use it for this |
1011 // layoutObject too. | 1011 // layoutObject too. |
1012 ASSERT(mapDescendantToColumnSet(objectAfterSubtree)); | 1012 DCHECK(mapDescendantToColumnSet(objectAfterSubtree)); |
1013 ASSERT(mapDescendantToColumnSet(layoutObject) == | 1013 DCHECK_EQ(mapDescendantToColumnSet(layoutObject), |
1014 mapDescendantToColumnSet(objectAfterSubtree)); | 1014 mapDescendantToColumnSet(objectAfterSubtree)); |
1015 } | 1015 } |
1016 } else { | 1016 } else { |
1017 // Inserting at the end. Then we just need to make sure that there's a | 1017 // Inserting at the end. Then we just need to make sure that there's a |
1018 // column set at the end. | 1018 // column set at the end. |
1019 LayoutBox* lastColumnBox = lastMultiColumnBox(); | 1019 LayoutBox* lastColumnBox = lastMultiColumnBox(); |
1020 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet()) | 1020 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet()) |
1021 createAndInsertMultiColumnSet(); | 1021 createAndInsertMultiColumnSet(); |
1022 } | 1022 } |
1023 } | 1023 } |
1024 } | 1024 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 return; // Followed by column content. Set still needed. | 1083 return; // Followed by column content. Set still needed. |
1084 } | 1084 } |
1085 // We have now determined that, with the removal of |descendant|, we should | 1085 // We have now determined that, with the removal of |descendant|, we should |
1086 // remove a column set. Locate it and remove it. Do it without involving | 1086 // remove a column set. Locate it and remove it. Do it without involving |
1087 // mapDescendantToColumnSet(), as that might be very slow. Deduce the right | 1087 // mapDescendantToColumnSet(), as that might be very slow. Deduce the right |
1088 // set from the spanner placeholders that we've already found. | 1088 // set from the spanner placeholders that we've already found. |
1089 LayoutMultiColumnSet* columnSetToRemove; | 1089 LayoutMultiColumnSet* columnSetToRemove; |
1090 if (adjacentNextSpannerPlaceholder) { | 1090 if (adjacentNextSpannerPlaceholder) { |
1091 columnSetToRemove = toLayoutMultiColumnSet( | 1091 columnSetToRemove = toLayoutMultiColumnSet( |
1092 adjacentNextSpannerPlaceholder->previousSiblingMultiColumnBox()); | 1092 adjacentNextSpannerPlaceholder->previousSiblingMultiColumnBox()); |
1093 ASSERT(!adjacentPreviousSpannerPlaceholder || | 1093 DCHECK(!adjacentPreviousSpannerPlaceholder || |
1094 columnSetToRemove == | 1094 columnSetToRemove == |
1095 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); | 1095 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); |
1096 } else if (adjacentPreviousSpannerPlaceholder) { | 1096 } else if (adjacentPreviousSpannerPlaceholder) { |
1097 columnSetToRemove = toLayoutMultiColumnSet( | 1097 columnSetToRemove = toLayoutMultiColumnSet( |
1098 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); | 1098 adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); |
1099 } else { | 1099 } else { |
1100 // If there were no adjacent spanners, it has to mean that there's only one | 1100 // If there were no adjacent spanners, it has to mean that there's only one |
1101 // column set, since it's only spanners that may cause creation of | 1101 // column set, since it's only spanners that may cause creation of |
1102 // multiple sets. | 1102 // multiple sets. |
1103 columnSetToRemove = firstMultiColumnSet(); | 1103 columnSetToRemove = firstMultiColumnSet(); |
1104 ASSERT(columnSetToRemove); | 1104 DCHECK(columnSetToRemove); |
1105 ASSERT(!columnSetToRemove->nextSiblingMultiColumnSet()); | 1105 DCHECK(!columnSetToRemove->nextSiblingMultiColumnSet()); |
1106 } | 1106 } |
1107 ASSERT(columnSetToRemove); | 1107 DCHECK(columnSetToRemove); |
1108 columnSetToRemove->destroy(); | 1108 columnSetToRemove->destroy(); |
1109 } | 1109 } |
1110 | 1110 |
1111 static inline bool needsToReinsertIntoFlowThread( | 1111 static inline bool needsToReinsertIntoFlowThread( |
1112 const ComputedStyle& oldStyle, | 1112 const ComputedStyle& oldStyle, |
1113 const ComputedStyle& newStyle) { | 1113 const ComputedStyle& newStyle) { |
1114 // If we've become (or are about to become) a container for absolutely | 1114 // If we've become (or are about to become) a container for absolutely |
1115 // positioned descendants, or if we're no longer going to be one, we need to | 1115 // positioned descendants, or if we're no longer going to be one, we need to |
1116 // re-evaluate the need for column sets. There may be out-of-flow descendants | 1116 // re-evaluate the need for column sets. There may be out-of-flow descendants |
1117 // further down that become part of the flow thread, or cease to be part of | 1117 // further down that become part of the flow thread, or cease to be part of |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1170 const ComputedStyle& oldStyle) { | 1170 const ComputedStyle& oldStyle) { |
1171 bool toggleSpannersIfNeeded = s_toggleSpannersIfNeeded; | 1171 bool toggleSpannersIfNeeded = s_toggleSpannersIfNeeded; |
1172 s_toggleSpannersIfNeeded = false; | 1172 s_toggleSpannersIfNeeded = false; |
1173 | 1173 |
1174 if (needsToInsertIntoFlowThread(oldStyle, descendant->styleRef())) { | 1174 if (needsToInsertIntoFlowThread(oldStyle, descendant->styleRef())) { |
1175 flowThreadDescendantWasInserted(descendant); | 1175 flowThreadDescendantWasInserted(descendant); |
1176 return; | 1176 return; |
1177 } | 1177 } |
1178 if (descendantIsValidColumnSpanner(descendant)) { | 1178 if (descendantIsValidColumnSpanner(descendant)) { |
1179 // We went from being regular column content to becoming a spanner. | 1179 // We went from being regular column content to becoming a spanner. |
1180 ASSERT(!descendant->spannerPlaceholder()); | 1180 DCHECK(!descendant->spannerPlaceholder()); |
1181 | 1181 |
1182 // First remove this as regular column content. Note that this will walk the | 1182 // First remove this as regular column content. Note that this will walk the |
1183 // entire subtree of |descendant|. There might be spanners there (which | 1183 // entire subtree of |descendant|. There might be spanners there (which |
1184 // won't be spanners anymore, since we're not allowed to nest spanners), | 1184 // won't be spanners anymore, since we're not allowed to nest spanners), |
1185 // whose placeholders must die. | 1185 // whose placeholders must die. |
1186 flowThreadDescendantWillBeRemoved(descendant); | 1186 flowThreadDescendantWillBeRemoved(descendant); |
1187 | 1187 |
1188 createAndInsertSpannerPlaceholder( | 1188 createAndInsertSpannerPlaceholder( |
1189 descendant, | 1189 descendant, |
1190 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant)); | 1190 nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant)); |
1191 return; | 1191 return; |
1192 } | 1192 } |
1193 | 1193 |
1194 if (!toggleSpannersIfNeeded) | 1194 if (!toggleSpannersIfNeeded) |
1195 return; | 1195 return; |
1196 #if DCHECK_IS_ON() | 1196 #if DCHECK_IS_ON() |
1197 // Make sure that we were preceded by a call to | 1197 // Make sure that we were preceded by a call to |
1198 // flowThreadDescendantStyleWillChange() with the same descendant as we have | 1198 // flowThreadDescendantStyleWillChange() with the same descendant as we have |
1199 // now. | 1199 // now. |
1200 DCHECK(s_styleChangedBox == descendant); | 1200 DCHECK_EQ(s_styleChangedBox, descendant); |
1201 #endif | 1201 #endif |
1202 | 1202 |
1203 if (s_couldContainSpanners != | 1203 if (s_couldContainSpanners != |
1204 canContainSpannerInParentFragmentationContext(*descendant)) | 1204 canContainSpannerInParentFragmentationContext(*descendant)) |
1205 toggleSpannersInSubtree(descendant); | 1205 toggleSpannersInSubtree(descendant); |
1206 } | 1206 } |
1207 | 1207 |
1208 void LayoutMultiColumnFlowThread::toggleSpannersInSubtree( | 1208 void LayoutMultiColumnFlowThread::toggleSpannersInSubtree( |
1209 LayoutBox* descendant) { | 1209 LayoutBox* descendant) { |
1210 DCHECK(s_couldContainSpanners != | 1210 DCHECK_NE(s_couldContainSpanners, |
1211 canContainSpannerInParentFragmentationContext(*descendant)); | 1211 canContainSpannerInParentFragmentationContext(*descendant)); |
1212 | 1212 |
1213 // If there are no spanners at all in this multicol container, there's no | 1213 // If there are no spanners at all in this multicol container, there's no |
1214 // need to look for any to remove. | 1214 // need to look for any to remove. |
1215 if (s_couldContainSpanners && !hasAnyColumnSpanners(*this)) | 1215 if (s_couldContainSpanners && !hasAnyColumnSpanners(*this)) |
1216 return; | 1216 return; |
1217 | 1217 |
1218 bool walkChildren; | 1218 bool walkChildren; |
1219 for (LayoutObject* object = descendant->nextInPreOrder(descendant); object; | 1219 for (LayoutObject* object = descendant->nextInPreOrder(descendant); object; |
1220 object = walkChildren | 1220 object = walkChildren |
1221 ? object->nextInPreOrder(descendant) | 1221 ? object->nextInPreOrder(descendant) |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 computedValues.m_position = logicalTop; | 1294 computedValues.m_position = logicalTop; |
1295 } | 1295 } |
1296 | 1296 |
1297 void LayoutMultiColumnFlowThread::updateLogicalWidth() { | 1297 void LayoutMultiColumnFlowThread::updateLogicalWidth() { |
1298 LayoutUnit columnWidth; | 1298 LayoutUnit columnWidth; |
1299 calculateColumnCountAndWidth(columnWidth, m_columnCount); | 1299 calculateColumnCountAndWidth(columnWidth, m_columnCount); |
1300 setLogicalWidth(columnWidth); | 1300 setLogicalWidth(columnWidth); |
1301 } | 1301 } |
1302 | 1302 |
1303 void LayoutMultiColumnFlowThread::layout() { | 1303 void LayoutMultiColumnFlowThread::layout() { |
1304 ASSERT(!m_lastSetWorkedOn); | 1304 DCHECK(!m_lastSetWorkedOn); |
1305 m_lastSetWorkedOn = firstMultiColumnSet(); | 1305 m_lastSetWorkedOn = firstMultiColumnSet(); |
1306 if (m_lastSetWorkedOn) | 1306 if (m_lastSetWorkedOn) |
1307 m_lastSetWorkedOn->beginFlow(LayoutUnit()); | 1307 m_lastSetWorkedOn->beginFlow(LayoutUnit()); |
1308 LayoutFlowThread::layout(); | 1308 LayoutFlowThread::layout(); |
1309 if (LayoutMultiColumnSet* lastSet = lastMultiColumnSet()) { | 1309 if (LayoutMultiColumnSet* lastSet = lastMultiColumnSet()) { |
1310 ASSERT(lastSet == m_lastSetWorkedOn); | 1310 DCHECK_EQ(lastSet, m_lastSetWorkedOn); |
1311 if (!lastSet->nextSiblingMultiColumnSet()) { | 1311 if (!lastSet->nextSiblingMultiColumnSet()) { |
1312 // Include trailing overflow in the last column set (also if the last set | 1312 // Include trailing overflow in the last column set (also if the last set |
1313 // is followed by one or more spanner placeholders). The idea is that we | 1313 // is followed by one or more spanner placeholders). The idea is that we |
1314 // will generate additional columns and pages to hold that overflow, | 1314 // will generate additional columns and pages to hold that overflow, |
1315 // since people do write bad content like <body style="height:0px"> in | 1315 // since people do write bad content like <body style="height:0px"> in |
1316 // multi-column layouts. | 1316 // multi-column layouts. |
1317 // TODO(mstensho): Once we support nested multicol, adding in overflow | 1317 // TODO(mstensho): Once we support nested multicol, adding in overflow |
1318 // here may result in the need for creating additional rows, since there | 1318 // here may result in the need for creating additional rows, since there |
1319 // may not be enough space remaining in the currently last row. | 1319 // may not be enough space remaining in the currently last row. |
1320 LayoutRect layoutRect = layoutOverflowRect(); | 1320 LayoutRect layoutRect = layoutOverflowRect(); |
1321 LayoutUnit logicalBottomInFlowThread = | 1321 LayoutUnit logicalBottomInFlowThread = |
1322 isHorizontalWritingMode() ? layoutRect.maxY() : layoutRect.maxX(); | 1322 isHorizontalWritingMode() ? layoutRect.maxY() : layoutRect.maxX(); |
1323 ASSERT(logicalBottomInFlowThread >= logicalHeight()); | 1323 DCHECK_GE(logicalBottomInFlowThread, logicalHeight()); |
1324 lastSet->endFlow(logicalBottomInFlowThread); | 1324 lastSet->endFlow(logicalBottomInFlowThread); |
1325 } | 1325 } |
1326 } | 1326 } |
1327 m_lastSetWorkedOn = nullptr; | 1327 m_lastSetWorkedOn = nullptr; |
1328 } | 1328 } |
1329 | 1329 |
1330 void LayoutMultiColumnFlowThread::contentWasLaidOut( | 1330 void LayoutMultiColumnFlowThread::contentWasLaidOut( |
1331 LayoutUnit logicalBottomInFlowThreadAfterPagination) { | 1331 LayoutUnit logicalBottomInFlowThreadAfterPagination) { |
1332 // Check if we need another fragmentainer group. If we've run out of columns | 1332 // Check if we need another fragmentainer group. If we've run out of columns |
1333 // in the last fragmentainer group (column row), we need to insert another | 1333 // in the last fragmentainer group (column row), we need to insert another |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 const { | 1377 const { |
1378 return MultiColumnLayoutState(m_lastSetWorkedOn); | 1378 return MultiColumnLayoutState(m_lastSetWorkedOn); |
1379 } | 1379 } |
1380 | 1380 |
1381 void LayoutMultiColumnFlowThread::restoreMultiColumnLayoutState( | 1381 void LayoutMultiColumnFlowThread::restoreMultiColumnLayoutState( |
1382 const MultiColumnLayoutState& state) { | 1382 const MultiColumnLayoutState& state) { |
1383 m_lastSetWorkedOn = state.columnSet(); | 1383 m_lastSetWorkedOn = state.columnSet(); |
1384 } | 1384 } |
1385 | 1385 |
1386 } // namespace blink | 1386 } // namespace blink |
OLD | NEW |