| 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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 // and instead leave you with dangling root line box pointers. But since thi
s is how it is done | 176 // and instead leave you with dangling root line box pointers. But since thi
s is how it is done |
| 177 // in other parts of the code that deal with reparenting layoutObjects, let'
s do the cleanup on our | 177 // in other parts of the code that deal with reparenting layoutObjects, let'
s do the cleanup on our |
| 178 // own here as well. | 178 // own here as well. |
| 179 deleteLineBoxTree(); | 179 deleteLineBoxTree(); |
| 180 | 180 |
| 181 destroy(); | 181 destroy(); |
| 182 } | 182 } |
| 183 | 183 |
| 184 LayoutSize LayoutMultiColumnFlowThread::columnOffset(const LayoutPoint& point) c
onst | 184 LayoutSize LayoutMultiColumnFlowThread::columnOffset(const LayoutPoint& point) c
onst |
| 185 { | 185 { |
| 186 if (!hasValidRegionInfo()) | 186 if (!hasValidColumnSetInfo()) |
| 187 return LayoutSize(0, 0); | 187 return LayoutSize(0, 0); |
| 188 | 188 |
| 189 LayoutPoint flowThreadPoint = flipForWritingMode(point); | 189 LayoutPoint flowThreadPoint = flipForWritingMode(point); |
| 190 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f
lowThreadPoint.x(); | 190 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f
lowThreadPoint.x(); |
| 191 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(blockOffset); | 191 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(blockOffset); |
| 192 if (!columnSet) | 192 if (!columnSet) |
| 193 return LayoutSize(0, 0); | 193 return LayoutSize(0, 0); |
| 194 return columnSet->flowThreadTranslationAtOffset(blockOffset); | 194 return columnSet->flowThreadTranslationAtOffset(blockOffset); |
| 195 } | 195 } |
| 196 | 196 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 215 } | 215 } |
| 216 | 216 |
| 217 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::columnSetAtBlockOffset(Layout
Unit offset) const | 217 LayoutMultiColumnSet* LayoutMultiColumnFlowThread::columnSetAtBlockOffset(Layout
Unit offset) const |
| 218 { | 218 { |
| 219 if (m_lastSetWorkedOn) { | 219 if (m_lastSetWorkedOn) { |
| 220 // Layout in progress. We are calculating the set heights as we speak, s
o the column set range | 220 // Layout in progress. We are calculating the set heights as we speak, s
o the column set range |
| 221 // information is not up-to-date. | 221 // information is not up-to-date. |
| 222 return m_lastSetWorkedOn; | 222 return m_lastSetWorkedOn; |
| 223 } | 223 } |
| 224 | 224 |
| 225 ASSERT(!m_regionsInvalidated); | 225 ASSERT(!m_columnSetsInvalidated); |
| 226 if (m_multiColumnSetList.isEmpty()) | 226 if (m_multiColumnSetList.isEmpty()) |
| 227 return 0; | 227 return 0; |
| 228 if (offset <= 0) | 228 if (offset <= 0) |
| 229 return m_multiColumnSetList.first(); | 229 return m_multiColumnSetList.first(); |
| 230 | 230 |
| 231 MultiColumnSetSearchAdapter adapter(offset); | 231 MultiColumnSetSearchAdapter adapter(offset); |
| 232 m_multiColumnSetIntervalTree.allOverlapsWithAdapter<MultiColumnSetSearchAdap
ter>(adapter); | 232 m_multiColumnSetIntervalTree.allOverlapsWithAdapter<MultiColumnSetSearchAdap
ter>(adapter); |
| 233 | 233 |
| 234 // If no set was found, the offset is in the flow thread overflow. | 234 // If no set was found, the offset is in the flow thread overflow. |
| 235 if (!adapter.result() && !m_multiColumnSetList.isEmpty()) | 235 if (!adapter.result() && !m_multiColumnSetList.isEmpty()) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 262 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); | 262 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); |
| 263 if (!m_inBalancingPass) { | 263 if (!m_inBalancingPass) { |
| 264 // This is the initial layout pass. We need to reset the column heig
ht, because contents | 264 // This is the initial layout pass. We need to reset the column heig
ht, because contents |
| 265 // typically have changed. | 265 // typically have changed. |
| 266 columnSet->resetColumnHeight(); | 266 columnSet->resetColumnHeight(); |
| 267 } | 267 } |
| 268 if (!m_needsColumnHeightsRecalculation) | 268 if (!m_needsColumnHeightsRecalculation) |
| 269 m_needsColumnHeightsRecalculation = columnSet->heightIsAuto(); | 269 m_needsColumnHeightsRecalculation = columnSet->heightIsAuto(); |
| 270 } | 270 } |
| 271 | 271 |
| 272 invalidateRegions(); | 272 invalidateColumnSets(); |
| 273 layout(); | 273 layout(); |
| 274 } | 274 } |
| 275 | 275 |
| 276 bool LayoutMultiColumnFlowThread::recalculateColumnHeights() | 276 bool LayoutMultiColumnFlowThread::recalculateColumnHeights() |
| 277 { | 277 { |
| 278 // All column sets that needed layout have now been laid out, so we can fina
lly validate them. | 278 // All column sets that needed layout have now been laid out, so we can fina
lly validate them. |
| 279 validateRegions(); | 279 validateColumnSets(); |
| 280 | 280 |
| 281 if (!m_needsColumnHeightsRecalculation) | 281 if (!m_needsColumnHeightsRecalculation) |
| 282 return false; | 282 return false; |
| 283 | 283 |
| 284 // Column heights may change here because of balancing. We may have to do mu
ltiple layout | 284 // Column heights may change here because of balancing. We may have to do mu
ltiple layout |
| 285 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most | 285 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most |
| 286 // cases, laying out again twice or even just once will suffice. Sometimes w
e need more | 286 // cases, laying out again twice or even just once will suffice. Sometimes w
e need more |
| 287 // passes than that, though, but the number of retries should not exceed the
number of | 287 // passes than that, though, but the number of retries should not exceed the
number of |
| 288 // columns, unless we have a bug. | 288 // columns, unless we have a bug. |
| 289 bool needsRelayout = false; | 289 bool needsRelayout = false; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, (
availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1); | 331 count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, (
availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1); |
| 332 width = ((availableWidth + columnGap) / count) - columnGap; | 332 width = ((availableWidth + columnGap) / count) - columnGap; |
| 333 } | 333 } |
| 334 } | 334 } |
| 335 | 335 |
| 336 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet(LayoutBox* inser
tBefore) | 336 void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet(LayoutBox* inser
tBefore) |
| 337 { | 337 { |
| 338 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 338 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
| 339 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(*this,
multicolContainer->styleRef()); | 339 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(*this,
multicolContainer->styleRef()); |
| 340 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); | 340 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); |
| 341 invalidateRegions(); | 341 invalidateColumnSets(); |
| 342 | 342 |
| 343 // We cannot handle immediate column set siblings (and there's no need for i
t, either). | 343 // We cannot handle immediate column set siblings (and there's no need for i
t, either). |
| 344 // There has to be at least one spanner separating them. | 344 // There has to be at least one spanner separating them. |
| 345 ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingM
ultiColumnBox()->isLayoutMultiColumnSet()); | 345 ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingM
ultiColumnBox()->isLayoutMultiColumnSet()); |
| 346 ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColu
mnBox()->isLayoutMultiColumnSet()); | 346 ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColu
mnBox()->isLayoutMultiColumnSet()); |
| 347 } | 347 } |
| 348 | 348 |
| 349 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(LayoutBox* s
panner, LayoutBox* insertBefore) | 349 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(LayoutBox* s
panner, LayoutBox* insertBefore) |
| 350 { | 350 { |
| 351 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 351 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 // after layout. Similarly for absolutely positioned boxes. | 394 // after layout. Similarly for absolutely positioned boxes. |
| 395 return false; | 395 return false; |
| 396 } | 396 } |
| 397 if (ancestor->isUnsplittableForPagination()) | 397 if (ancestor->isUnsplittableForPagination()) |
| 398 return false; | 398 return false; |
| 399 } | 399 } |
| 400 ASSERT_NOT_REACHED(); | 400 ASSERT_NOT_REACHED(); |
| 401 return false; | 401 return false; |
| 402 } | 402 } |
| 403 | 403 |
| 404 void LayoutMultiColumnFlowThread::addRegionToThread(LayoutMultiColumnSet* column
Set) | 404 void LayoutMultiColumnFlowThread::addColumnSetToThread(LayoutMultiColumnSet* col
umnSet) |
| 405 { | 405 { |
| 406 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet())
{ | 406 if (LayoutMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet())
{ |
| 407 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe
t); | 407 LayoutMultiColumnSetList::iterator it = m_multiColumnSetList.find(nextSe
t); |
| 408 ASSERT(it != m_multiColumnSetList.end()); | 408 ASSERT(it != m_multiColumnSetList.end()); |
| 409 m_multiColumnSetList.insertBefore(it, columnSet); | 409 m_multiColumnSetList.insertBefore(it, columnSet); |
| 410 } else { | 410 } else { |
| 411 m_multiColumnSetList.add(columnSet); | 411 m_multiColumnSetList.add(columnSet); |
| 412 } | 412 } |
| 413 columnSet->setIsValid(true); | |
| 414 } | 413 } |
| 415 | 414 |
| 416 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() | 415 void LayoutMultiColumnFlowThread::willBeRemovedFromTree() |
| 417 { | 416 { |
| 418 // Detach all column sets from the flow thread. Cannot destroy them at this
point, since they | 417 // Detach all column sets from the flow thread. Cannot destroy them at this
point, since they |
| 419 // are siblings of this object, and there may be pointers to this object's s
ibling somewhere | 418 // are siblings of this object, and there may be pointers to this object's s
ibling somewhere |
| 420 // further up on the call stack. | 419 // further up on the call stack. |
| 421 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) | 420 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) |
| 422 columnSet->detachRegion(); | 421 columnSet->detachFromFlowThread(); |
| 423 multiColumnBlockFlow()->resetMultiColumnFlowThread(); | 422 multiColumnBlockFlow()->resetMultiColumnFlowThread(); |
| 424 LayoutFlowThread::willBeRemovedFromTree(); | 423 LayoutFlowThread::willBeRemovedFromTree(); |
| 425 } | 424 } |
| 426 | 425 |
| 427 LayoutUnit LayoutMultiColumnFlowThread::skipColumnSpanner(LayoutBox* layoutObjec
t, LayoutUnit logicalTopInFlowThread) | 426 LayoutUnit LayoutMultiColumnFlowThread::skipColumnSpanner(LayoutBox* layoutObjec
t, LayoutUnit logicalTopInFlowThread) |
| 428 { | 427 { |
| 429 ASSERT(layoutObject->isColumnSpanAll()); | 428 ASSERT(layoutObject->isColumnSpanAll()); |
| 430 LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlac
eholder(); | 429 LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlac
eholder(); |
| 431 LayoutUnit adjustment; | 430 LayoutUnit adjustment; |
| 432 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); | 431 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 continue; | 591 continue; |
| 593 } | 592 } |
| 594 next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a
spanner. Its children are of no interest to us. | 593 next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a
spanner. Its children are of no interest to us. |
| 595 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox())
{ | 594 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox())
{ |
| 596 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColu
mnBox(); | 595 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColu
mnBox(); |
| 597 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() | 596 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() |
| 598 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSe
t()) { | 597 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSe
t()) { |
| 599 // Need to merge two column sets. | 598 // Need to merge two column sets. |
| 600 nextColumnBox->destroy(); | 599 nextColumnBox->destroy(); |
| 601 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::Colu
mnsChanged); | 600 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::Colu
mnsChanged); |
| 602 invalidateRegions(); | 601 invalidateColumnSets(); |
| 603 } | 602 } |
| 604 } | 603 } |
| 605 placeholder->destroy(); | 604 placeholder->destroy(); |
| 606 } | 605 } |
| 607 if (hadContainingPlaceholder || !processedSomething) | 606 if (hadContainingPlaceholder || !processedSomething) |
| 608 return; // No column content will be removed, so we can stop here. | 607 return; // No column content will be removed, so we can stop here. |
| 609 | 608 |
| 610 // Column content will be removed. Does this mean that we should destroy a c
olumn set? | 609 // Column content will be removed. Does this mean that we should destroy a c
olumn set? |
| 611 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 0; | 610 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 0; |
| 612 LayoutObject* previousLayoutObject = descendant->previousInPreOrder(this); | 611 LayoutObject* previousLayoutObject = descendant->previousInPreOrder(this); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) | 710 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) |
| 712 multicolSet->recordSpaceShortage(offset, spaceShortage); | 711 multicolSet->recordSpaceShortage(offset, spaceShortage); |
| 713 } | 712 } |
| 714 | 713 |
| 715 void LayoutMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay
outUnit minHeight) | 714 void LayoutMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay
outUnit minHeight) |
| 716 { | 715 { |
| 717 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) | 716 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) |
| 718 multicolSet->updateMinimumColumnHeight(offset, minHeight); | 717 multicolSet->updateMinimumColumnHeight(offset, minHeight); |
| 719 } | 718 } |
| 720 | 719 |
| 721 bool LayoutMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Layout
Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) | 720 bool LayoutMultiColumnFlowThread::addForcedColumnBreak(LayoutUnit offset, Layout
Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) |
| 722 { | 721 { |
| 723 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) { | 722 if (LayoutMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) { |
| 724 multicolSet->addContentRun(offset); | 723 multicolSet->addContentRun(offset); |
| 725 if (offsetBreakAdjustment) | 724 if (offsetBreakAdjustment) |
| 726 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe
mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); | 725 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe
mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); |
| 727 return true; | 726 return true; |
| 728 } | 727 } |
| 729 return false; | 728 return false; |
| 730 } | 729 } |
| 731 | 730 |
| 732 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const | 731 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const |
| 733 { | 732 { |
| 734 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) | 733 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) |
| 735 return columnSet->pageLogicalHeight(); | 734 return columnSet->pageLogicalHeight(); |
| 736 return false; | 735 return false; |
| 737 } | 736 } |
| 738 | 737 |
| 739 } | 738 } |
| OLD | NEW |