OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 child->setY(logicalTop); | 541 child->setY(logicalTop); |
542 } else { | 542 } else { |
543 child->setX(logicalTop); | 543 child->setX(logicalTop); |
544 } | 544 } |
545 } | 545 } |
546 | 546 |
547 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
LayoutUnit& previousFloatLogicalBottom) | 547 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
LayoutUnit& previousFloatLogicalBottom) |
548 { | 548 { |
549 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); | 549 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); |
550 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); | 550 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); |
| 551 bool isColumnSpanner = child->isColumnSpanAll(); |
| 552 |
| 553 if (isColumnSpanner) { |
| 554 // Margins of a column spanner cannot collapse with anything. |
| 555 setLogicalHeight(logicalHeight() + marginInfo.margin()); |
| 556 marginInfo.clearMargin(); |
| 557 LayoutUnit adjustment = flowThreadContainingBlock()->enterColumnSpanner(
child, logicalHeight()); |
| 558 setLogicalHeight(logicalHeight() + adjustment); |
| 559 } |
551 | 560 |
552 // The child is a normal flow object. Compute the margins we will use for co
llapsing now. | 561 // The child is a normal flow object. Compute the margins we will use for co
llapsing now. |
553 child->computeAndSetBlockDirectionMargins(this); | 562 child->computeAndSetBlockDirectionMargins(this); |
554 | 563 |
555 // Try to guess our correct logical top position. In most cases this guess w
ill | 564 // Try to guess our correct logical top position. In most cases this guess w
ill |
556 // be correct. Only if we're wrong (when we compute the real logical top pos
ition) | 565 // be correct. Only if we're wrong (when we compute the real logical top pos
ition) |
557 // will we have to potentially relayout. | 566 // will we have to potentially relayout. |
558 LayoutUnit estimateWithoutPagination; | 567 LayoutUnit estimateWithoutPagination; |
559 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo
, estimateWithoutPagination); | 568 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo
, estimateWithoutPagination); |
560 | 569 |
561 bool isColumnSpanner = child->isColumnSpanAll(); | |
562 if (isColumnSpanner) { | |
563 LayoutUnit margin = child->marginBefore(); | |
564 logicalTopEstimate -= margin; | |
565 flowThreadContainingBlock()->enterColumnSpanner(child, logicalTopEstimat
e); | |
566 logicalTopEstimate += margin; | |
567 } | |
568 | |
569 // Cache our old rect so that we can dirty the proper paint invalidation rec
ts if the child moves. | 570 // Cache our old rect so that we can dirty the proper paint invalidation rec
ts if the child moves. |
570 LayoutRect oldRect = child->frameRect(); | 571 LayoutRect oldRect = child->frameRect(); |
571 LayoutUnit oldLogicalTop = logicalTopForChild(child); | 572 LayoutUnit oldLogicalTop = logicalTopForChild(child); |
572 | 573 |
573 // Go ahead and position the child as though it didn't collapse with the top
. | 574 // Go ahead and position the child as though it didn't collapse with the top
. |
574 setLogicalTopForChild(child, logicalTopEstimate); | 575 setLogicalTopForChild(child, logicalTopEstimate); |
575 | 576 |
576 RenderBlockFlow* childRenderBlockFlow = child->isRenderBlockFlow() ? toRende
rBlockFlow(child) : 0; | 577 RenderBlockFlow* childRenderBlockFlow = child->isRenderBlockFlow() ? toRende
rBlockFlow(child) : 0; |
577 bool markDescendantsWithFloats = false; | 578 bool markDescendantsWithFloats = false; |
578 if (logicalTopEstimate != oldLogicalTop && childRenderBlockFlow && !childRen
derBlockFlow->avoidsFloats() && childRenderBlockFlow->containsFloats()) { | 579 if (logicalTopEstimate != oldLogicalTop && childRenderBlockFlow && !childRen
derBlockFlow->avoidsFloats() && childRenderBlockFlow->containsFloats()) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 | 727 |
727 // Our guess was wrong. Make the child lay itself out again. | 728 // Our guess was wrong. Make the child lay itself out again. |
728 child->layoutIfNeeded(); | 729 child->layoutIfNeeded(); |
729 } | 730 } |
730 | 731 |
731 LayoutUnit oldTop = logicalTopAfterClear; | 732 LayoutUnit oldTop = logicalTopAfterClear; |
732 | 733 |
733 // If the object has a page or column break value of "before", then we shoul
d shift to the top of the next page. | 734 // If the object has a page or column break value of "before", then we shoul
d shift to the top of the next page. |
734 LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear); | 735 LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear); |
735 | 736 |
736 if (child->isColumnSpanAll()) | |
737 result += flowThreadContainingBlock()->spannerLogicalTopAdjustment(child
, result - child->marginBefore()); | |
738 | |
739 // For replaced elements and scrolled elements, we want to shift them to the
next page if they don't fit on the current one. | 737 // For replaced elements and scrolled elements, we want to shift them to the
next page if they don't fit on the current one. |
740 LayoutUnit logicalTopBeforeUnsplittableAdjustment = result; | 738 LayoutUnit logicalTopBeforeUnsplittableAdjustment = result; |
741 LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChil
d(child, result); | 739 LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChil
d(child, result); |
742 | 740 |
743 LayoutUnit paginationStrut = 0; | 741 LayoutUnit paginationStrut = 0; |
744 LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustme
nt - logicalTopBeforeUnsplittableAdjustment; | 742 LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustme
nt - logicalTopBeforeUnsplittableAdjustment; |
745 LayoutUnit childLogicalHeight = child->logicalHeight(); | 743 LayoutUnit childLogicalHeight = child->logicalHeight(); |
746 if (unsplittableAdjustmentDelta) { | 744 if (unsplittableAdjustmentDelta) { |
747 setPageBreak(result, childLogicalHeight - unsplittableAdjustmentDelta); | 745 setPageBreak(result, childLogicalHeight - unsplittableAdjustmentDelta); |
748 paginationStrut = unsplittableAdjustmentDelta; | 746 paginationStrut = unsplittableAdjustmentDelta; |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 // top to get new posTop and negTop values. | 1174 // top to get new posTop and negTop values. |
1177 if (childIsSelfCollapsing) { | 1175 if (childIsSelfCollapsing) { |
1178 posTop = std::max(posTop, childMargins.positiveMarginAfter()); | 1176 posTop = std::max(posTop, childMargins.positiveMarginAfter()); |
1179 negTop = std::max(negTop, childMargins.negativeMarginAfter()); | 1177 negTop = std::max(negTop, childMargins.negativeMarginAfter()); |
1180 } | 1178 } |
1181 | 1179 |
1182 // See if the top margin is quirky. We only care if this child has | 1180 // See if the top margin is quirky. We only care if this child has |
1183 // margins that will collapse with us. | 1181 // margins that will collapse with us. |
1184 bool topQuirk = hasMarginBeforeQuirk(child); | 1182 bool topQuirk = hasMarginBeforeQuirk(child); |
1185 | 1183 |
1186 if (marginInfo.canCollapseWithMarginBefore() && !mustSeparateMarginBeforeFor
Child(child)) { | 1184 if (marginInfo.canCollapseWithMarginBefore()) { |
1187 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { | 1185 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { |
1188 // This child is collapsing with the top of the | 1186 // This child is collapsing with the top of the |
1189 // block. If it has larger margin values, then we need to update | 1187 // block. If it has larger margin values, then we need to update |
1190 // our own maximal values. | 1188 // our own maximal values. |
1191 if (!document().inQuirksMode() || !marginInfo.quirkContainer() || !t
opQuirk) | 1189 if (!document().inQuirksMode() || !marginInfo.quirkContainer() || !t
opQuirk) |
1192 setMaxMarginBeforeValues(std::max(posTop, maxPositiveMarginBefor
e()), std::max(negTop, maxNegativeMarginBefore())); | 1190 setMaxMarginBeforeValues(std::max(posTop, maxPositiveMarginBefor
e()), std::max(negTop, maxNegativeMarginBefore())); |
1193 | 1191 |
1194 // The minute any of the margins involved isn't a quirk, don't | 1192 // The minute any of the margins involved isn't a quirk, don't |
1195 // collapse it away, even if the margin is smaller (www.webreference
.com | 1193 // collapse it away, even if the margin is smaller (www.webreference
.com |
1196 // has an example of this, a <dt> with 0.8em author-specified inside | 1194 // has an example of this, a <dt> with 0.8em author-specified inside |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1461 RenderBox* grandchildBox = childBlockFlow->firstChildBox(); | 1459 RenderBox* grandchildBox = childBlockFlow->firstChildBox(); |
1462 for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { | 1460 for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { |
1463 if (!grandchildBox->isFloatingOrOutOfFlowPositioned()) | 1461 if (!grandchildBox->isFloatingOrOutOfFlowPositioned()) |
1464 break; | 1462 break; |
1465 } | 1463 } |
1466 | 1464 |
1467 // Give up if there is clearance on the box, since it probably won't collaps
e into us. | 1465 // Give up if there is clearance on the box, since it probably won't collaps
e into us. |
1468 if (!grandchildBox || grandchildBox->style()->clear() != CNONE) | 1466 if (!grandchildBox || grandchildBox->style()->clear() != CNONE) |
1469 return; | 1467 return; |
1470 | 1468 |
1471 if (childBlockFlow->mustSeparateMarginBeforeForChild(grandchildBox)) | |
1472 return; | |
1473 | |
1474 // Make sure to update the block margins now for the grandchild box so that
we're looking at current values. | 1469 // Make sure to update the block margins now for the grandchild box so that
we're looking at current values. |
1475 if (grandchildBox->needsLayout()) { | 1470 if (grandchildBox->needsLayout()) { |
1476 grandchildBox->computeAndSetBlockDirectionMargins(this); | 1471 grandchildBox->computeAndSetBlockDirectionMargins(this); |
1477 if (grandchildBox->isRenderBlock()) { | 1472 if (grandchildBox->isRenderBlock()) { |
1478 RenderBlock* grandchildBlock = toRenderBlock(grandchildBox); | 1473 RenderBlock* grandchildBlock = toRenderBlock(grandchildBox); |
1479 grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->has
MarginBeforeQuirk()); | 1474 grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->has
MarginBeforeQuirk()); |
1480 grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasM
arginAfterQuirk()); | 1475 grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasM
arginAfterQuirk()); |
1481 } | 1476 } |
1482 } | 1477 } |
1483 | 1478 |
1484 // Collapse the margin of the grandchild box with our own to produce an esti
mate. | 1479 // Collapse the margin of the grandchild box with our own to produce an esti
mate. |
1485 childBlockFlow->marginBeforeEstimateForChild(grandchildBox, positiveMarginBe
fore, negativeMarginBefore, discardMarginBefore); | 1480 childBlockFlow->marginBeforeEstimateForChild(grandchildBox, positiveMarginBe
fore, negativeMarginBefore, discardMarginBefore); |
1486 } | 1481 } |
1487 | 1482 |
1488 LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox* child, const M
arginInfo& marginInfo, LayoutUnit& estimateWithoutPagination) | 1483 LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox* child, const M
arginInfo& marginInfo, LayoutUnit& estimateWithoutPagination) |
1489 { | 1484 { |
1490 // FIXME: We need to eliminate the estimation of vertical position, because
when it's wrong we sometimes trigger a pathological | 1485 // FIXME: We need to eliminate the estimation of vertical position, because
when it's wrong we sometimes trigger a pathological |
1491 // relayout if there are intruding floats. | 1486 // relayout if there are intruding floats. |
1492 LayoutUnit logicalTopEstimate = logicalHeight(); | 1487 LayoutUnit logicalTopEstimate = logicalHeight(); |
1493 if (!marginInfo.canCollapseWithMarginBefore() || mustSeparateMarginBeforeFor
Child(child)) { | 1488 if (!marginInfo.canCollapseWithMarginBefore()) { |
1494 LayoutUnit positiveMarginBefore = 0; | 1489 LayoutUnit positiveMarginBefore = 0; |
1495 LayoutUnit negativeMarginBefore = 0; | 1490 LayoutUnit negativeMarginBefore = 0; |
1496 bool discardMarginBefore = false; | 1491 bool discardMarginBefore = false; |
1497 if (child->selfNeedsLayout()) { | 1492 if (child->selfNeedsLayout()) { |
1498 // Try to do a basic estimation of how the collapse is going to go. | 1493 // Try to do a basic estimation of how the collapse is going to go. |
1499 marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMa
rginBefore, discardMarginBefore); | 1494 marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMa
rginBefore, discardMarginBefore); |
1500 } else { | 1495 } else { |
1501 // Use the cached collapsed margin values from a previous layout. Mo
st of the time they | 1496 // Use the cached collapsed margin values from a previous layout. Mo
st of the time they |
1502 // will be right. | 1497 // will be right. |
1503 RenderBlockFlow::MarginValues marginValues = marginValuesForChild(ch
ild); | 1498 RenderBlockFlow::MarginValues marginValues = marginValuesForChild(ch
ild); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 if (pos == RenderBlockFlowRareData::positiveMarginAfterDefault(this) &&
neg == RenderBlockFlowRareData::negativeMarginAfterDefault(this)) | 1673 if (pos == RenderBlockFlowRareData::positiveMarginAfterDefault(this) &&
neg == RenderBlockFlowRareData::negativeMarginAfterDefault(this)) |
1679 return; | 1674 return; |
1680 m_rareData = adoptPtrWillBeNoop(new RenderBlockFlowRareData(this)); | 1675 m_rareData = adoptPtrWillBeNoop(new RenderBlockFlowRareData(this)); |
1681 } | 1676 } |
1682 m_rareData->m_margins.setPositiveMarginAfter(pos); | 1677 m_rareData->m_margins.setPositiveMarginAfter(pos); |
1683 m_rareData->m_margins.setNegativeMarginAfter(neg); | 1678 m_rareData->m_margins.setNegativeMarginAfter(neg); |
1684 } | 1679 } |
1685 | 1680 |
1686 bool RenderBlockFlow::mustSeparateMarginBeforeForChild(const RenderBox* child) c
onst | 1681 bool RenderBlockFlow::mustSeparateMarginBeforeForChild(const RenderBox* child) c
onst |
1687 { | 1682 { |
1688 if (child->isColumnSpanAll()) | 1683 ASSERT(!child->selfNeedsLayout()); |
1689 return true; | |
1690 const RenderStyle* childStyle = child->style(); | 1684 const RenderStyle* childStyle = child->style(); |
1691 if (!child->isWritingModeRoot()) | 1685 if (!child->isWritingModeRoot()) |
1692 return childStyle->marginBeforeCollapse() == MSEPARATE; | 1686 return childStyle->marginBeforeCollapse() == MSEPARATE; |
1693 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) | 1687 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) |
1694 return childStyle->marginAfterCollapse() == MSEPARATE; | 1688 return childStyle->marginAfterCollapse() == MSEPARATE; |
1695 | 1689 |
1696 // FIXME: See |mustDiscardMarginBeforeForChild| above. | 1690 // FIXME: See |mustDiscardMarginBeforeForChild| above. |
1697 return false; | 1691 return false; |
1698 } | 1692 } |
1699 | 1693 |
1700 bool RenderBlockFlow::mustSeparateMarginAfterForChild(const RenderBox* child) co
nst | 1694 bool RenderBlockFlow::mustSeparateMarginAfterForChild(const RenderBox* child) co
nst |
1701 { | 1695 { |
1702 if (child->isColumnSpanAll()) | 1696 ASSERT(!child->selfNeedsLayout()); |
1703 return true; | |
1704 const RenderStyle* childStyle = child->style(); | 1697 const RenderStyle* childStyle = child->style(); |
1705 if (!child->isWritingModeRoot()) | 1698 if (!child->isWritingModeRoot()) |
1706 return childStyle->marginAfterCollapse() == MSEPARATE; | 1699 return childStyle->marginAfterCollapse() == MSEPARATE; |
1707 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) | 1700 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) |
1708 return childStyle->marginBeforeCollapse() == MSEPARATE; | 1701 return childStyle->marginBeforeCollapse() == MSEPARATE; |
1709 | 1702 |
1710 // FIXME: See |mustDiscardMarginBeforeForChild| above. | 1703 // FIXME: See |mustDiscardMarginBeforeForChild| above. |
1711 return false; | 1704 return false; |
1712 } | 1705 } |
1713 | 1706 |
(...skipping 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2924 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() | 2917 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() |
2925 { | 2918 { |
2926 if (m_rareData) | 2919 if (m_rareData) |
2927 return *m_rareData; | 2920 return *m_rareData; |
2928 | 2921 |
2929 m_rareData = adoptPtrWillBeNoop(new RenderBlockFlowRareData(this)); | 2922 m_rareData = adoptPtrWillBeNoop(new RenderBlockFlowRareData(this)); |
2930 return *m_rareData; | 2923 return *m_rareData; |
2931 } | 2924 } |
2932 | 2925 |
2933 } // namespace blink | 2926 } // namespace blink |
OLD | NEW |