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 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2114 // | 2114 // |
2115 // Note also that the previous flow may collapse its margin into the top of | 2115 // Note also that the previous flow may collapse its margin into the top of |
2116 // our block. If this is the case, then we do not add the margin in to our | 2116 // our block. If this is the case, then we do not add the margin in to our |
2117 // height when computing the position of the float. This condition can be | 2117 // height when computing the position of the float. This condition can be |
2118 // tested for by simply calling canCollapseWithMarginBefore. See | 2118 // tested for by simply calling canCollapseWithMarginBefore. See |
2119 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for | 2119 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for |
2120 // an example of this scenario. | 2120 // an example of this scenario. |
2121 LayoutUnit logicalTop = logicalHeight(); | 2121 LayoutUnit logicalTop = logicalHeight(); |
2122 if (!marginInfo.canCollapseWithMarginBefore()) | 2122 if (!marginInfo.canCollapseWithMarginBefore()) |
2123 logicalTop += marginInfo.margin(); | 2123 logicalTop += marginInfo.margin(); |
2124 positionNewFloats(logicalTop); | 2124 placeNewFloats(logicalTop); |
2125 } | 2125 } |
2126 | 2126 |
2127 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, | 2127 void LayoutBlockFlow::handleAfterSideOfBlock(LayoutBox* lastChild, |
2128 LayoutUnit beforeSide, | 2128 LayoutUnit beforeSide, |
2129 LayoutUnit afterSide, | 2129 LayoutUnit afterSide, |
2130 MarginInfo& marginInfo) { | 2130 MarginInfo& marginInfo) { |
2131 marginInfo.setAtAfterSideOfBlock(true); | 2131 marginInfo.setAtAfterSideOfBlock(true); |
2132 | 2132 |
2133 // If our last child was a self-collapsing block with clearance then our | 2133 // If our last child was a self-collapsing block with clearance then our |
2134 // logical height is flush with the bottom edge of the float that the child | 2134 // logical height is flush with the bottom edge of the float that the child |
(...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3318 } | 3318 } |
3319 | 3319 |
3320 void LayoutBlockFlow::childBecameNonInline(LayoutObject*) { | 3320 void LayoutBlockFlow::childBecameNonInline(LayoutObject*) { |
3321 makeChildrenNonInline(); | 3321 makeChildrenNonInline(); |
3322 if (isAnonymousBlock() && parent() && parent()->isLayoutBlock()) | 3322 if (isAnonymousBlock() && parent() && parent()->isLayoutBlock()) |
3323 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); | 3323 toLayoutBlock(parent())->removeLeftoverAnonymousBlock(this); |
3324 // |this| may be dead here | 3324 // |this| may be dead here |
3325 } | 3325 } |
3326 | 3326 |
3327 void LayoutBlockFlow::clearFloats(EClear clear) { | 3327 void LayoutBlockFlow::clearFloats(EClear clear) { |
3328 positionNewFloats(logicalHeight()); | 3328 placeNewFloats(logicalHeight()); |
3329 // set y position | 3329 // set y position |
3330 LayoutUnit newY = lowestFloatLogicalBottom(clear); | 3330 LayoutUnit newY = lowestFloatLogicalBottom(clear); |
3331 if (size().height() < newY) | 3331 if (size().height() < newY) |
3332 setLogicalHeight(newY); | 3332 setLogicalHeight(newY); |
3333 } | 3333 } |
3334 | 3334 |
3335 bool LayoutBlockFlow::containsFloat(LayoutBox* layoutBox) const { | 3335 bool LayoutBlockFlow::containsFloat(LayoutBox* layoutBox) const { |
3336 return m_floatingObjects && | 3336 return m_floatingObjects && |
3337 m_floatingObjects->set().contains<FloatingObjectHashTranslator>( | 3337 m_floatingObjects->set().contains<FloatingObjectHashTranslator>( |
3338 layoutBox); | 3338 layoutBox); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3558 FloatingObject* curr = floatingObjectSet.last().get(); | 3558 FloatingObject* curr = floatingObjectSet.last().get(); |
3559 while (curr != lastFloat && | 3559 while (curr != lastFloat && |
3560 (!curr->isPlaced() || logicalTopForFloat(*curr) >= logicalOffset)) { | 3560 (!curr->isPlaced() || logicalTopForFloat(*curr) >= logicalOffset)) { |
3561 m_floatingObjects->remove(curr); | 3561 m_floatingObjects->remove(curr); |
3562 if (floatingObjectSet.isEmpty()) | 3562 if (floatingObjectSet.isEmpty()) |
3563 break; | 3563 break; |
3564 curr = floatingObjectSet.last().get(); | 3564 curr = floatingObjectSet.last().get(); |
3565 } | 3565 } |
3566 } | 3566 } |
3567 | 3567 |
3568 bool LayoutBlockFlow::positionNewFloats(LayoutUnit logicalTop, | 3568 bool LayoutBlockFlow::placeNewFloats(LayoutUnit logicalTopMarginEdge, |
3569 LineWidth* width) { | 3569 LineWidth* width) { |
3570 if (!m_floatingObjects) | 3570 if (!m_floatingObjects) |
3571 return false; | 3571 return false; |
3572 | 3572 |
3573 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 3573 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
3574 if (floatingObjectSet.isEmpty()) | 3574 if (floatingObjectSet.isEmpty()) |
3575 return false; | 3575 return false; |
3576 | 3576 |
3577 // If all floats have already been positioned, then we have no work to do. | 3577 // If all floats have already been positioned, then we have no work to do. |
3578 if (floatingObjectSet.last()->isPlaced()) | 3578 if (floatingObjectSet.last()->isPlaced()) |
3579 return false; | 3579 return false; |
3580 | 3580 |
3581 // Move backwards through our floating object list until we find a float that | 3581 // Move backwards through our floating object list until we find a float that |
3582 // has already been positioned. Then we'll be able to move forward, | 3582 // has already been positioned. Then we'll be able to move forward, |
3583 // positioning all of the new floats that need it. | 3583 // positioning all of the new floats that need it. |
3584 FloatingObjectSetIterator it = floatingObjectSet.end(); | 3584 FloatingObjectSetIterator it = floatingObjectSet.end(); |
3585 --it; // Go to last item. | 3585 --it; // Go to last item. |
3586 FloatingObjectSetIterator begin = floatingObjectSet.begin(); | 3586 FloatingObjectSetIterator begin = floatingObjectSet.begin(); |
3587 FloatingObject* lastPlacedFloatingObject = nullptr; | 3587 FloatingObject* lastPlacedFloatingObject = nullptr; |
3588 while (it != begin) { | 3588 while (it != begin) { |
3589 --it; | 3589 --it; |
3590 if ((*it)->isPlaced()) { | 3590 if ((*it)->isPlaced()) { |
3591 lastPlacedFloatingObject = it->get(); | 3591 lastPlacedFloatingObject = it->get(); |
3592 ++it; | 3592 ++it; |
3593 break; | 3593 break; |
3594 } | 3594 } |
3595 } | 3595 } |
3596 | 3596 |
3597 // The float cannot start above the top position of the last positioned float. | 3597 // The float cannot start above the top position of the last positioned float. |
3598 if (lastPlacedFloatingObject) | 3598 if (lastPlacedFloatingObject) { |
3599 logicalTop = | 3599 logicalTopMarginEdge = std::max( |
3600 std::max(logicalTopForFloat(*lastPlacedFloatingObject), logicalTop); | 3600 logicalTopMarginEdge, logicalTopForFloat(*lastPlacedFloatingObject)); |
| 3601 } |
3601 | 3602 |
3602 FloatingObjectSetIterator end = floatingObjectSet.end(); | 3603 FloatingObjectSetIterator end = floatingObjectSet.end(); |
3603 // Now walk through the set of unpositioned floats and place them. | 3604 // Now walk through the set of unpositioned floats and place them. |
3604 for (; it != end; ++it) { | 3605 for (; it != end; ++it) { |
3605 FloatingObject& floatingObject = *it->get(); | 3606 FloatingObject& floatingObject = *it->get(); |
3606 // The containing block is responsible for positioning floats, so if we have | 3607 // The containing block is responsible for positioning floats, so if we have |
3607 // unplaced floats in our list that come from somewhere else, we have a bug. | 3608 // unplaced floats in our list that come from somewhere else, we have a bug. |
3608 DCHECK_EQ(floatingObject.layoutObject()->containingBlock(), this); | 3609 DCHECK_EQ(floatingObject.layoutObject()->containingBlock(), this); |
3609 | 3610 |
3610 logicalTop = positionAndLayoutFloat(floatingObject, logicalTop); | 3611 logicalTopMarginEdge = |
| 3612 positionAndLayoutFloat(floatingObject, logicalTopMarginEdge); |
3611 | 3613 |
3612 m_floatingObjects->addPlacedObject(floatingObject); | 3614 m_floatingObjects->addPlacedObject(floatingObject); |
3613 | 3615 |
3614 if (width) | 3616 if (width) |
3615 width->shrinkAvailableWidthForNewFloatIfNeeded(floatingObject); | 3617 width->shrinkAvailableWidthForNewFloatIfNeeded(floatingObject); |
3616 } | 3618 } |
3617 return true; | 3619 return true; |
3618 } | 3620 } |
3619 | 3621 |
3620 LayoutUnit LayoutBlockFlow::positionAndLayoutFloat( | 3622 LayoutUnit LayoutBlockFlow::positionAndLayoutFloat( |
3621 FloatingObject& floatingObject, | 3623 FloatingObject& floatingObject, |
3622 LayoutUnit logicalTop) { | 3624 LayoutUnit logicalTopMarginEdge) { |
3623 LayoutBox& childBox = *floatingObject.layoutObject(); | 3625 LayoutBox& childBox = *floatingObject.layoutObject(); |
3624 | 3626 |
3625 // FIXME Investigate if this can be removed. crbug.com/370006 | 3627 // FIXME Investigate if this can be removed. crbug.com/370006 |
3626 childBox.setMayNeedPaintInvalidation(); | 3628 childBox.setMayNeedPaintInvalidation(); |
3627 | 3629 |
3628 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() | 3630 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() |
3629 ? marginStartForChild(childBox) | 3631 ? marginStartForChild(childBox) |
3630 : marginEndForChild(childBox); | 3632 : marginEndForChild(childBox); |
3631 logicalTop = | 3633 logicalTopMarginEdge = |
3632 std::max(logicalTop, lowestFloatLogicalBottom(childBox.style()->clear())); | 3634 std::max(logicalTopMarginEdge, |
| 3635 lowestFloatLogicalBottom(childBox.style()->clear())); |
3633 | 3636 |
3634 bool isPaginated = view()->layoutState()->isPaginated(); | 3637 bool isPaginated = view()->layoutState()->isPaginated(); |
3635 if (isPaginated && !childrenInline()) { | 3638 if (isPaginated && !childrenInline()) { |
3636 // Forced breaks are inserted at class A break points. Floats may be | 3639 // Forced breaks are inserted at class A break points. Floats may be |
3637 // affected by a break-after value on the previous in-flow sibling. | 3640 // affected by a break-after value on the previous in-flow sibling. |
3638 if (LayoutBox* previousInFlowBox = childBox.previousInFlowSiblingBox()) { | 3641 if (LayoutBox* previousInFlowBox = childBox.previousInFlowSiblingBox()) { |
3639 logicalTop = | 3642 logicalTopMarginEdge = applyForcedBreak(logicalTopMarginEdge, |
3640 applyForcedBreak(logicalTop, previousInFlowBox->breakAfter()); | 3643 previousInFlowBox->breakAfter()); |
3641 } | 3644 } |
3642 } | 3645 } |
3643 | 3646 |
3644 LayoutPoint floatLogicalLocation = | 3647 LayoutPoint floatLogicalLocation = |
3645 computeLogicalLocationForFloat(floatingObject, logicalTop); | 3648 computeLogicalLocationForFloat(floatingObject, logicalTopMarginEdge); |
| 3649 logicalTopMarginEdge = floatLogicalLocation.y(); |
3646 | 3650 |
3647 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3651 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
3648 | 3652 |
3649 setLogicalLeftForChild(childBox, | 3653 setLogicalLeftForChild(childBox, |
3650 floatLogicalLocation.x() + childLogicalLeftMargin); | 3654 floatLogicalLocation.x() + childLogicalLeftMargin); |
3651 setLogicalTopForChild( | 3655 setLogicalTopForChild(childBox, |
3652 childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox)); | 3656 logicalTopMarginEdge + marginBeforeForChild(childBox)); |
3653 | 3657 |
3654 SubtreeLayoutScope layoutScope(childBox); | 3658 SubtreeLayoutScope layoutScope(childBox); |
3655 if (isPaginated && !childBox.needsLayout()) | 3659 if (isPaginated && !childBox.needsLayout()) |
3656 markChildForPaginationRelayoutIfNeeded(childBox, layoutScope); | 3660 markChildForPaginationRelayoutIfNeeded(childBox, layoutScope); |
3657 | 3661 |
3658 childBox.layoutIfNeeded(); | 3662 childBox.layoutIfNeeded(); |
3659 | 3663 |
3660 if (isPaginated) { | 3664 if (isPaginated) { |
3661 LayoutBlockFlow* childBlockFlow = | 3665 LayoutBlockFlow* childBlockFlow = |
3662 childBox.isLayoutBlockFlow() ? toLayoutBlockFlow(&childBox) : nullptr; | 3666 childBox.isLayoutBlockFlow() ? toLayoutBlockFlow(&childBox) : nullptr; |
(...skipping 21 matching lines...) Expand all Loading... |
3684 LayoutUnit remainingSpace = pageRemainingLogicalHeightForOffset( | 3688 LayoutUnit remainingSpace = pageRemainingLogicalHeightForOffset( |
3685 marginEdge, AssociateWithLatterPage); | 3689 marginEdge, AssociateWithLatterPage); |
3686 if (remainingSpace <= marginBefore) | 3690 if (remainingSpace <= marginBefore) |
3687 strut += remainingSpace; | 3691 strut += remainingSpace; |
3688 } | 3692 } |
3689 } | 3693 } |
3690 } | 3694 } |
3691 if (!strut) { | 3695 if (!strut) { |
3692 // If we are unsplittable and don't fit, move to the next page or column | 3696 // If we are unsplittable and don't fit, move to the next page or column |
3693 // if that helps the situation. | 3697 // if that helps the situation. |
3694 strut = adjustForUnsplittableChild(childBox, floatLogicalLocation.y()) - | 3698 strut = adjustForUnsplittableChild(childBox, logicalTopMarginEdge) - |
3695 floatLogicalLocation.y(); | 3699 logicalTopMarginEdge; |
3696 } | 3700 } |
3697 | 3701 |
3698 childBox.setPaginationStrut(strut); | 3702 childBox.setPaginationStrut(strut); |
3699 if (strut) { | 3703 if (strut) { |
3700 floatLogicalLocation = computeLogicalLocationForFloat( | 3704 floatLogicalLocation = computeLogicalLocationForFloat( |
3701 floatingObject, floatLogicalLocation.y() + strut); | 3705 floatingObject, logicalTopMarginEdge + strut); |
| 3706 logicalTopMarginEdge = floatLogicalLocation.y(); |
3702 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); | 3707 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); |
3703 | 3708 |
3704 setLogicalLeftForChild(childBox, | 3709 setLogicalLeftForChild(childBox, |
3705 floatLogicalLocation.x() + childLogicalLeftMargin); | 3710 floatLogicalLocation.x() + childLogicalLeftMargin); |
3706 setLogicalTopForChild( | 3711 setLogicalTopForChild( |
3707 childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox)); | 3712 childBox, logicalTopMarginEdge + marginBeforeForChild(childBox)); |
3708 | 3713 |
3709 if (childBox.isLayoutBlock()) | 3714 if (childBox.isLayoutBlock()) |
3710 childBox.setChildNeedsLayout(MarkOnlyThis); | 3715 childBox.setChildNeedsLayout(MarkOnlyThis); |
3711 childBox.layoutIfNeeded(); | 3716 childBox.layoutIfNeeded(); |
3712 } | 3717 } |
3713 } | 3718 } |
3714 | 3719 |
3715 setLogicalTopForFloat(floatingObject, floatLogicalLocation.y()); | 3720 setLogicalTopForFloat(floatingObject, logicalTopMarginEdge); |
3716 | 3721 |
3717 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + | 3722 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + |
3718 marginBeforeForChild(childBox) + | 3723 marginBeforeForChild(childBox) + |
3719 marginAfterForChild(childBox)); | 3724 marginAfterForChild(childBox)); |
3720 | 3725 |
3721 if (ShapeOutsideInfo* shapeOutside = childBox.shapeOutsideInfo()) | 3726 if (ShapeOutsideInfo* shapeOutside = childBox.shapeOutsideInfo()) |
3722 shapeOutside->setReferenceBoxLogicalSize(logicalSizeForChild(childBox)); | 3727 shapeOutside->setReferenceBoxLogicalSize(logicalSizeForChild(childBox)); |
3723 | 3728 |
3724 return floatLogicalLocation.y(); | 3729 return logicalTopMarginEdge; |
3725 } | 3730 } |
3726 | 3731 |
3727 bool LayoutBlockFlow::hasOverhangingFloat(LayoutBox* layoutBox) { | 3732 bool LayoutBlockFlow::hasOverhangingFloat(LayoutBox* layoutBox) { |
3728 if (!m_floatingObjects || !parent()) | 3733 if (!m_floatingObjects || !parent()) |
3729 return false; | 3734 return false; |
3730 | 3735 |
3731 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); | 3736 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); |
3732 FloatingObjectSetIterator it = | 3737 FloatingObjectSetIterator it = |
3733 floatingObjectSet.find<FloatingObjectHashTranslator>(layoutBox); | 3738 floatingObjectSet.find<FloatingObjectHashTranslator>(layoutBox); |
3734 if (it == floatingObjectSet.end()) | 3739 if (it == floatingObjectSet.end()) |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4542 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); | 4547 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState); |
4543 } | 4548 } |
4544 | 4549 |
4545 void LayoutBlockFlow::invalidateDisplayItemClients( | 4550 void LayoutBlockFlow::invalidateDisplayItemClients( |
4546 PaintInvalidationReason invalidationReason) const { | 4551 PaintInvalidationReason invalidationReason) const { |
4547 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( | 4552 BlockFlowPaintInvalidator(*this).invalidateDisplayItemClients( |
4548 invalidationReason); | 4553 invalidationReason); |
4549 } | 4554 } |
4550 | 4555 |
4551 } // namespace blink | 4556 } // namespace blink |
OLD | NEW |