Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1238)

Side by Side Diff: Source/core/layout/LayoutGrid.cpp

Issue 1298623002: [CSS Grid Layout] Implement auto-margins alignment of grid items (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Don't need the resetAutoMargins function. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2011 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 1334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 child->setOverrideContainingBlockContentLogicalWidth(overrideContainingB lockContentLogicalWidth); 1345 child->setOverrideContainingBlockContentLogicalWidth(overrideContainingB lockContentLogicalWidth);
1346 child->setOverrideContainingBlockContentLogicalHeight(overrideContaining BlockContentLogicalHeight); 1346 child->setOverrideContainingBlockContentLogicalHeight(overrideContaining BlockContentLogicalHeight);
1347 1347
1348 // Stretching logic might force a child layout, so we need to run it bef ore the layoutIfNeeded 1348 // Stretching logic might force a child layout, so we need to run it bef ore the layoutIfNeeded
1349 // call to avoid unnecessary relayouts. This might imply that child marg ins, needed to correctly 1349 // call to avoid unnecessary relayouts. This might imply that child marg ins, needed to correctly
1350 // determine the available space before stretching, are not set yet. 1350 // determine the available space before stretching, are not set yet.
1351 applyStretchAlignmentToChildIfNeeded(*child); 1351 applyStretchAlignmentToChildIfNeeded(*child);
1352 1352
1353 child->layoutIfNeeded(); 1353 child->layoutIfNeeded();
1354 1354
1355 // We need pending layouts to be done in order to compute auto-margins p roperly.
Manuel Rego 2015/09/24 11:38:26 Probably we could add an ASSERT in the methods to
jfernandez 2015/09/25 13:47:02 Acknowledged.
1356 updateAutoMarginsInColumnAxisIfNeeded(*child);
1357 updateAutoMarginsInRowAxisIfNeeded(*child);
1358
1355 #if ENABLE(ASSERT) 1359 #if ENABLE(ASSERT)
1356 const GridCoordinate& coordinate = cachedGridCoordinate(*child); 1360 const GridCoordinate& coordinate = cachedGridCoordinate(*child);
1357 ASSERT(coordinate.columns.resolvedInitialPosition.toInt() < sizingData.c olumnTracks.size()); 1361 ASSERT(coordinate.columns.resolvedInitialPosition.toInt() < sizingData.c olumnTracks.size());
1358 ASSERT(coordinate.rows.resolvedInitialPosition.toInt() < sizingData.rowT racks.size()); 1362 ASSERT(coordinate.rows.resolvedInitialPosition.toInt() < sizingData.rowT racks.size());
1359 #endif 1363 #endif
1360 child->setLogicalLocation(findChildLogicalPosition(*child, sizingData)); 1364 child->setLogicalLocation(findChildLogicalPosition(*child, sizingData));
1361 1365
1362 // Keep track of children overflowing their grid area as we might need t o paint them even if the grid-area is 1366 // Keep track of children overflowing their grid area as we might need t o paint them even if the grid-area is
1363 // not visible 1367 // not visible
1364 if (child->logicalHeight() > overrideContainingBlockContentLogicalHeight 1368 if (child->logicalHeight() > overrideContainingBlockContentLogicalHeight
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1601 LayoutUnit marginAfter; 1605 LayoutUnit marginAfter;
1602 child.computeMarginsForDirection(BlockDirection, this, child.containingBlock LogicalWidthForContent(), child.logicalHeight(), marginBefore, marginAfter, 1606 child.computeMarginsForDirection(BlockDirection, this, child.containingBlock LogicalWidthForContent(), child.logicalHeight(), marginBefore, marginAfter,
1603 child.style()->marginBeforeUsing(style()), 1607 child.style()->marginBeforeUsing(style()),
1604 child.style()->marginAfterUsing(style())); 1608 child.style()->marginAfterUsing(style()));
1605 1609
1606 return marginBefore + marginAfter; 1610 return marginBefore + marginAfter;
1607 } 1611 }
1608 1612
1609 LayoutUnit LayoutGrid::availableAlignmentSpaceForChildBeforeStretching(LayoutUni t gridAreaBreadthForChild, const LayoutBox& child) const 1613 LayoutUnit LayoutGrid::availableAlignmentSpaceForChildBeforeStretching(LayoutUni t gridAreaBreadthForChild, const LayoutBox& child) const
1610 { 1614 {
1611 LayoutUnit childMarginLogicalHeight = marginLogicalHeightForChild(child);
1612
1613 // Because we want to avoid multiple layouts, stretching logic might be perf ormed before 1615 // Because we want to avoid multiple layouts, stretching logic might be perf ormed before
1614 // children are laid out, so we can't use the child cached values. Hence, we need to 1616 // children are laid out, so we can't use the child cached values. Hence, we need to
1615 // compute margins in order to determine the available height before stretch ing. 1617 // compute margins in order to determine the available height before stretch ing.
1616 if (childMarginLogicalHeight == 0) 1618 return gridAreaBreadthForChild - (child.needsLayout() ? computeMarginLogical HeightForChild(child) : marginLogicalHeightForChild(child));
1617 childMarginLogicalHeight = computeMarginLogicalHeightForChild(child);
1618
1619 return gridAreaBreadthForChild - childMarginLogicalHeight;
1620 } 1619 }
1621 1620
1622 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to La youtBox. 1621 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to La youtBox.
1623 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child) 1622 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child)
1624 { 1623 {
1625 // We clear both width and height override values because we will decide now whether they 1624 // We clear both width and height override values because we will decide now whether they
1626 // are allowed or not, evaluating the conditions which might have changed si nce the old 1625 // are allowed or not, evaluating the conditions which might have changed si nce the old
1627 // values were set. 1626 // values were set.
1628 child.clearOverrideSize(); 1627 child.clearOverrideSize();
1629 1628
(...skipping 26 matching lines...) Expand all
1656 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.b orderAndPaddingLogicalHeight()); 1655 child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.b orderAndPaddingLogicalHeight());
1657 if (desiredLogicalHeight != child.logicalHeight()) { 1656 if (desiredLogicalHeight != child.logicalHeight()) {
1658 // TODO (lajava): Can avoid laying out here in some cases. See h ttps://webkit.org/b/87905. 1657 // TODO (lajava): Can avoid laying out here in some cases. See h ttps://webkit.org/b/87905.
1659 child.setLogicalHeight(0); 1658 child.setLogicalHeight(0);
1660 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); 1659 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1661 } 1660 }
1662 } 1661 }
1663 } 1662 }
1664 } 1663 }
1665 1664
1665 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be move d to LayoutBox.
1666 bool LayoutGrid::hasAutoMarginsInColumnAxis(const LayoutBox& child) const
1667 {
1668 if (isHorizontalWritingMode())
1669 return child.style()->marginTop().isAuto() || child.style()->marginBotto m().isAuto();
1670 return child.style()->marginLeft().isAuto() || child.style()->marginRight(). isAuto();
1671 }
1672
1673 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be move d to LayoutBox.
1674 bool LayoutGrid::hasAutoMarginsInRowAxis(const LayoutBox& child) const
1675 {
1676 if (isHorizontalWritingMode())
1677 return child.style()->marginLeft().isAuto() || child.style()->marginRigh t().isAuto();
1678 return child.style()->marginTop().isAuto() || child.style()->marginBottom(). isAuto();
1679 }
1680
1681 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be move d to LayoutBox.
1682 void LayoutGrid::updateAutoMarginsInRowAxisIfNeeded(LayoutBox& child)
1683 {
1684 ASSERT(!child.isOutOfFlowPositioned());
1685
1686 LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLog icalWidth() - child.logicalWidth();
1687 if (availableAlignmentSpace <= 0)
1688 return;
1689
1690 bool isHorizontal = isHorizontalWritingMode();
1691 Length topOrLeft = isHorizontal ? child.style()->marginLeft() : child.style( )->marginTop();
Manuel Rego 2015/09/24 11:38:26 To simplify the code and all the checks related to
jfernandez 2015/09/25 13:47:02 I think it wouldn't be an equivalent logic. Be awa
Manuel Rego 2015/09/25 16:00:58 BTW, I was thinking in style()->marginStart() whic
1692 Length bottomOrRight = isHorizontal ? child.style()->marginRight() : child.s tyle()->marginBottom();
Manuel Rego 2015/09/24 11:38:27 Ditto.
jfernandez 2015/09/25 13:47:02 Replied.
1693 if (topOrLeft.isAuto() && bottomOrRight.isAuto()) {
1694 if (isHorizontal) {
1695 child.setMarginLeft(availableAlignmentSpace / 2);
1696 child.setMarginRight(availableAlignmentSpace / 2);
1697 } else {
1698 child.setMarginTop(availableAlignmentSpace / 2);
1699 child.setMarginBottom(availableAlignmentSpace / 2);
1700 }
Manuel Rego 2015/09/24 11:38:27 Probably here you could use setMarginStart().
jfernandez 2015/09/25 13:47:02 This could be true, but I'm not sure whether it'd
1701 } else if (topOrLeft.isAuto()) {
1702 if (isHorizontal)
1703 child.setMarginLeft(availableAlignmentSpace);
1704 else
1705 child.setMarginTop(availableAlignmentSpace);
Manuel Rego 2015/09/24 11:38:27 Ditto.
jfernandez 2015/09/25 13:47:02 Replied.
1706 } else if (bottomOrRight.isAuto()) {
1707 if (isHorizontal)
1708 child.setMarginRight(availableAlignmentSpace);
1709 else
1710 child.setMarginBottom(availableAlignmentSpace);
Manuel Rego 2015/09/24 11:38:27 Ditto.
jfernandez 2015/09/25 13:47:02 Replied.
1711 }
1712 }
1713
1714 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be move d to LayoutBox.
1715 void LayoutGrid::updateAutoMarginsInColumnAxisIfNeeded(LayoutBox& child)
1716 {
1717 ASSERT(!child.isOutOfFlowPositioned());
1718
1719 LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLog icalHeight() - child.logicalHeight();
1720 if (availableAlignmentSpace <= 0)
1721 return;
1722
1723 bool isHorizontal = isHorizontalWritingMode();
1724 Length topOrLeft = isHorizontal ? child.style()->marginTop() : child.style() ->marginLeft();
Manuel Rego 2015/09/24 11:38:26 The same than in the row axis method.
jfernandez 2015/09/25 13:47:02 Replied.
1725 Length bottomOrRight = isHorizontal ? child.style()->marginBottom() : child. style()->marginRight();
1726 if (topOrLeft.isAuto() && bottomOrRight.isAuto()) {
1727 if (isHorizontal) {
1728 child.setMarginTop(availableAlignmentSpace / 2);
1729 child.setMarginBottom(availableAlignmentSpace / 2);
1730 } else {
1731 child.setMarginLeft(availableAlignmentSpace / 2);
1732 child.setMarginRight(availableAlignmentSpace / 2);
1733 }
1734 } else if (topOrLeft.isAuto()) {
1735 if (isHorizontal)
1736 child.setMarginTop(availableAlignmentSpace);
1737 else
1738 child.setMarginLeft(availableAlignmentSpace);
1739 } else if (bottomOrRight.isAuto()) {
1740 if (isHorizontal)
1741 child.setMarginBottom(availableAlignmentSpace);
1742 else
1743 child.setMarginRight(availableAlignmentSpace);
1744 }
1745 }
1746
1666 GridAxisPosition LayoutGrid::columnAxisPositionForChild(const LayoutBox& child) const 1747 GridAxisPosition LayoutGrid::columnAxisPositionForChild(const LayoutBox& child) const
1667 { 1748 {
1668 bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizon talWritingMode(); 1749 bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizon talWritingMode();
1669 bool hasSameWritingMode = child.styleRef().writingMode() == styleRef().writi ngMode(); 1750 bool hasSameWritingMode = child.styleRef().writingMode() == styleRef().writi ngMode();
1670 1751
1671 switch (ComputedStyle::resolveAlignment(styleRef(), child.styleRef(), ItemPo sitionStretch)) { 1752 switch (ComputedStyle::resolveAlignment(styleRef(), child.styleRef(), ItemPo sitionStretch)) {
1672 case ItemPositionSelfStart: 1753 case ItemPositionSelfStart:
1673 // If orthogonal writing-modes, this computes to 'start'. 1754 // If orthogonal writing-modes, this computes to 'start'.
1674 // FIXME: grid track sizing and positioning do not support orthogonal mo des yet. 1755 // FIXME: grid track sizing and positioning do not support orthogonal mo des yet.
1675 // self-start is based on the child's block axis direction. That's why w e need to check against the grid container's block flow. 1756 // self-start is based on the child's block axis direction. That's why w e need to check against the grid container's block flow.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 1834
1754 ASSERT_NOT_REACHED(); 1835 ASSERT_NOT_REACHED();
1755 return GridAxisStart; 1836 return GridAxisStart;
1756 } 1837 }
1757 1838
1758 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const 1839 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const
1759 { 1840 {
1760 const GridCoordinate& coordinate = cachedGridCoordinate(child); 1841 const GridCoordinate& coordinate = cachedGridCoordinate(child);
1761 LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPositi on.toInt()]; 1842 LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPositi on.toInt()];
1762 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); 1843 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
1844 if (hasAutoMarginsInColumnAxis(child))
1845 return startPosition;
1763 GridAxisPosition axisPosition = columnAxisPositionForChild(child); 1846 GridAxisPosition axisPosition = columnAxisPositionForChild(child);
1764 switch (axisPosition) { 1847 switch (axisPosition) {
1765 case GridAxisStart: 1848 case GridAxisStart:
1766 return startPosition; 1849 return startPosition;
1767 case GridAxisEnd: 1850 case GridAxisEnd:
1768 case GridAxisCenter: { 1851 case GridAxisCenter: {
1769 LayoutUnit endOfRow = m_rowPositions[coordinate.rows.resolvedFinalPositi on.next().toInt()]; 1852 LayoutUnit endOfRow = m_rowPositions[coordinate.rows.resolvedFinalPositi on.next().toInt()];
1770 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil d.styleRef().alignSelfOverflowAlignment(), endOfRow - startOfRow, child.logicalH eight() + child.marginLogicalHeight()); 1853 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil d.styleRef().alignSelfOverflowAlignment(), endOfRow - startOfRow, child.logicalH eight() + child.marginLogicalHeight());
1771 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos ition : offsetFromStartPosition / 2); 1854 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos ition : offsetFromStartPosition / 2);
1772 } 1855 }
1773 } 1856 }
1774 1857
1775 ASSERT_NOT_REACHED(); 1858 ASSERT_NOT_REACHED();
1776 return 0; 1859 return 0;
1777 } 1860 }
1778 1861
1779 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child) const 1862 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child) const
1780 { 1863 {
1781 const GridCoordinate& coordinate = cachedGridCoordinate(child); 1864 const GridCoordinate& coordinate = cachedGridCoordinate(child);
1782 LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInit ialPosition.toInt()]; 1865 LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInit ialPosition.toInt()];
1783 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); 1866 LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
1867 if (hasAutoMarginsInRowAxis(child))
1868 return startPosition;
1784 GridAxisPosition axisPosition = rowAxisPositionForChild(child); 1869 GridAxisPosition axisPosition = rowAxisPositionForChild(child);
1785 switch (axisPosition) { 1870 switch (axisPosition) {
1786 case GridAxisStart: 1871 case GridAxisStart:
1787 return startPosition; 1872 return startPosition;
1788 case GridAxisEnd: 1873 case GridAxisEnd:
1789 case GridAxisCenter: { 1874 case GridAxisCenter: {
1790 LayoutUnit endOfColumn = m_columnPositions[coordinate.columns.resolvedFi nalPosition.next().toInt()]; 1875 LayoutUnit endOfColumn = m_columnPositions[coordinate.columns.resolvedFi nalPosition.next().toInt()];
1791 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil d.styleRef().justifySelfOverflowAlignment(), endOfColumn - startOfColumn, child. logicalWidth() + child.marginLogicalWidth()); 1876 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil d.styleRef().justifySelfOverflowAlignment(), endOfColumn - startOfColumn, child. logicalWidth() + child.marginLogicalWidth());
1792 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos ition : offsetFromStartPosition / 2); 1877 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos ition : offsetFromStartPosition / 2);
1793 } 1878 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 2008
1924 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); 2009 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child));
1925 } 2010 }
1926 2011
1927 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) 2012 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset)
1928 { 2013 {
1929 GridPainter(*this).paintChildren(paintInfo, paintOffset); 2014 GridPainter(*this).paintChildren(paintInfo, paintOffset);
1930 } 2015 }
1931 2016
1932 } // namespace blink 2017 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698