| 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 |