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 |