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 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 m_inBalancingPass = needsRelayout; | 354 m_inBalancingPass = needsRelayout; |
355 return needsRelayout; | 355 return needsRelayout; |
356 } | 356 } |
357 | 357 |
358 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() | 358 void LayoutMultiColumnFlowThread::columnRuleStyleDidChange() |
359 { | 359 { |
360 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) | 360 for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col
umnSet = columnSet->nextSiblingMultiColumnSet()) |
361 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange
); | 361 columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange
); |
362 } | 362 } |
363 | 363 |
| 364 bool LayoutMultiColumnFlowThread::removeSpannerPlaceholderIfNoLongerValid(Layout
Box* spannerObjectInFlowThread) |
| 365 { |
| 366 ASSERT(spannerObjectInFlowThread->spannerPlaceholder()); |
| 367 if (descendantIsValidColumnSpanner(spannerObjectInFlowThread)) |
| 368 return false; // Still a valid spanner. |
| 369 |
| 370 // No longer a valid spanner. Get rid of the placeholder. |
| 371 destroySpannerPlaceholder(spannerObjectInFlowThread->spannerPlaceholder()); |
| 372 ASSERT(!spannerObjectInFlowThread->spannerPlaceholder()); |
| 373 |
| 374 // We may have a new containing block, since we're no longer a spanner. Mark
it for relayout. |
| 375 spannerObjectInFlowThread->containingBlock()->setNeedsLayoutAndPrefWidthsRec
alc(LayoutInvalidationReason::ColumnsChanged); |
| 376 |
| 377 // Now generate a column set for this ex-spanner, if needed and none is ther
e for us already. |
| 378 flowThreadDescendantWasInserted(spannerObjectInFlowThread); |
| 379 |
| 380 return true; |
| 381 } |
| 382 |
364 void LayoutMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
, unsigned& count) const | 383 void LayoutMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
, unsigned& count) const |
365 { | 384 { |
366 LayoutBlock* columnBlock = multiColumnBlockFlow(); | 385 LayoutBlock* columnBlock = multiColumnBlockFlow(); |
367 const ComputedStyle* columnStyle = columnBlock->style(); | 386 const ComputedStyle* columnStyle = columnBlock->style(); |
368 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); | 387 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); |
369 LayoutUnit columnGap = columnBlock->columnGap(); | 388 LayoutUnit columnGap = columnBlock->columnGap(); |
370 LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->
columnWidth())); | 389 LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->
columnWidth())); |
371 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); | 390 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); |
372 | 391 |
373 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); | 392 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 nextColumnBox->destroy(); | 470 nextColumnBox->destroy(); |
452 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::ColumnsC
hanged); | 471 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::ColumnsC
hanged); |
453 invalidateColumnSets(); | 472 invalidateColumnSets(); |
454 } | 473 } |
455 } | 474 } |
456 placeholder->destroy(); | 475 placeholder->destroy(); |
457 } | 476 } |
458 | 477 |
459 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner(LayoutObject* d
escendant) const | 478 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner(LayoutObject* d
escendant) const |
460 { | 479 { |
| 480 // This method needs to behave correctly in the following situations: |
| 481 // - When the descendant doesn't have a spanner placeholder but should have
one (return true) |
| 482 // - When the descendant doesn't have a spanner placeholder and still should
not have one (return false) |
| 483 // - When the descendant has a spanner placeholder but should no longer have
one (return false) |
| 484 // - When the descendant has a spanner placeholder and should still have one
(return true) |
| 485 |
461 // We assume that we're inside the flow thread. This function is not to be c
alled otherwise. | 486 // We assume that we're inside the flow thread. This function is not to be c
alled otherwise. |
462 ASSERT(descendant->isDescendantOf(this)); | 487 ASSERT(descendant->isDescendantOf(this)); |
463 | 488 |
464 // We're evaluating if the descendant should be turned into a proper spanner
. It shouldn't | |
465 // already be one. | |
466 ASSERT(!descendant->spannerPlaceholder()); | |
467 | |
468 // The spec says that column-span only applies to in-flow block-level elemen
ts. | 489 // The spec says that column-span only applies to in-flow block-level elemen
ts. |
469 if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox
() || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned()) | 490 if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox
() || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned()) |
470 return false; | 491 return false; |
471 | 492 |
472 if (!descendant->containingBlock()->isLayoutBlockFlow()) { | 493 if (!descendant->containingBlock()->isLayoutBlockFlow()) { |
473 // Needs to be in a block-flow container, and not e.g. a table. | 494 // Needs to be in a block-flow container, and not e.g. a table. |
474 return false; | 495 return false; |
475 } | 496 } |
476 | 497 |
477 // This looks like a spanner, but if we're inside something unbreakable, it'
s not to be treated as one. | 498 // This looks like a spanner, but if we're inside something unbreakable, it'
s not to be treated as one. |
478 for (LayoutBlock* ancestor = descendant->containingBlock(); ancestor; ancest
or = ancestor->containingBlock()) { | 499 for (LayoutBox* ancestor = toLayoutBox(descendant)->parentBox(); ancestor; a
ncestor = ancestor->containingBlock()) { |
479 if (ancestor->isLayoutFlowThread()) { | 500 if (ancestor->isLayoutFlowThread()) { |
480 ASSERT(ancestor == this); | 501 ASSERT(ancestor == this); |
481 return true; | 502 return true; |
482 } | 503 } |
483 if (ancestor->spannerPlaceholder()) { | 504 if (ancestor->spannerPlaceholder()) { |
484 // FIXME: do we want to support nested spanners in a different way?
The outer spanner | 505 // FIXME: do we want to support nested spanners in a different way?
The outer spanner |
485 // has already broken out from the columns to become sized by the mu
lticol container, | 506 // has already broken out from the columns to become sized by the mu
lticol container, |
486 // which may be good enough for the inner spanner. But margins, bord
ers, padding and | 507 // which may be good enough for the inner spanner. But margins, bord
ers, padding and |
487 // explicit widths on the outer spanner, or on any children between
the outer and inner | 508 // explicit widths on the outer spanner, or on any children between
the outer and inner |
488 // spanner, will affect the width of the inner spanner this way, whi
ch might be | 509 // spanner, will affect the width of the inner spanner this way, whi
ch might be |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleDidChange(LayoutObjec
t* descendant, StyleDifference diff, const ComputedStyle& oldStyle) | 726 void LayoutMultiColumnFlowThread::flowThreadDescendantStyleDidChange(LayoutObjec
t* descendant, StyleDifference diff, const ComputedStyle& oldStyle) |
706 { | 727 { |
707 // If an out-of-flow descendant goes in-flow, we may have to insert a column
set. | 728 // If an out-of-flow descendant goes in-flow, we may have to insert a column
set. |
708 if (descendant->isText()) { | 729 if (descendant->isText()) { |
709 // Text nodes inherit all properties from the parent node (including non
-inheritable | 730 // Text nodes inherit all properties from the parent node (including non
-inheritable |
710 // ones). We don't care what its 'position' is. In fact, we _must_ ignor
e it, since the | 731 // ones). We don't care what its 'position' is. In fact, we _must_ ignor
e it, since the |
711 // parent may be the multicol container, and having that accidentally le
aked into children | 732 // parent may be the multicol container, and having that accidentally le
aked into children |
712 // of the multicol is bad. | 733 // of the multicol is bad. |
713 return; | 734 return; |
714 } | 735 } |
715 if (oldStyle.hasOutOfFlowPosition() && !styleRef().hasOutOfFlowPosition()) | 736 if (styleRef().hasOutOfFlowPosition()) |
| 737 return; |
| 738 |
| 739 // We're not out of flow. |
| 740 if (oldStyle.hasOutOfFlowPosition()) { |
| 741 // ... but we used to be out of flow. So we might need to insert a colum
n set (or |
| 742 // spanner placeholder, in case this descendant is now a valid column sp
anner). |
716 flowThreadDescendantWasInserted(descendant); | 743 flowThreadDescendantWasInserted(descendant); |
| 744 return; |
| 745 } |
| 746 if (descendantIsValidColumnSpanner(descendant)) { |
| 747 // We went from being regular column content to becoming a spanner. |
| 748 ASSERT(!toLayoutBox(descendant)->spannerPlaceholder()); |
| 749 |
| 750 // First remove this as regular column content. Note that this will walk
the entire subtree |
| 751 // of |descendant|. There might be spanners there (which won't be spanne
rs anymore, since |
| 752 // we're not allowed to nest spanners), whose placeholders must die. |
| 753 flowThreadDescendantWillBeRemoved(descendant); |
| 754 |
| 755 createAndInsertSpannerPlaceholder(toLayoutBox(descendant), nextInPreOrde
rAfterChildrenSkippingOutOfFlow(this, descendant)); |
| 756 } |
717 } | 757 } |
718 | 758 |
719 void LayoutMultiColumnFlowThread::computePreferredLogicalWidths() | 759 void LayoutMultiColumnFlowThread::computePreferredLogicalWidths() |
720 { | 760 { |
721 LayoutFlowThread::computePreferredLogicalWidths(); | 761 LayoutFlowThread::computePreferredLogicalWidths(); |
722 | 762 |
723 // The min/max intrinsic widths calculated really tell how much space elemen
ts need when | 763 // The min/max intrinsic widths calculated really tell how much space elemen
ts need when |
724 // laid out inside the columns. In order to eventually end up with the desir
ed column width, | 764 // laid out inside the columns. In order to eventually end up with the desir
ed column width, |
725 // we need to convert them to values pertaining to the multicol container. | 765 // we need to convert them to values pertaining to the multicol container. |
726 const LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 766 const LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 } | 844 } |
805 | 845 |
806 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const | 846 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const |
807 { | 847 { |
808 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) | 848 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) |
809 return columnSet->pageLogicalHeight(); | 849 return columnSet->pageLogicalHeight(); |
810 return false; | 850 return false; |
811 } | 851 } |
812 | 852 |
813 } | 853 } |
OLD | NEW |