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