OLD | NEW |
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 |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "core/layout/LayoutGrid.h" | 26 #include "core/layout/LayoutGrid.h" |
27 | 27 |
| 28 #include <algorithm> |
| 29 #include <memory> |
28 #include "core/frame/UseCounter.h" | 30 #include "core/frame/UseCounter.h" |
29 #include "core/layout/LayoutState.h" | 31 #include "core/layout/LayoutState.h" |
30 #include "core/layout/TextAutosizer.h" | 32 #include "core/layout/TextAutosizer.h" |
31 #include "core/paint/GridPainter.h" | 33 #include "core/paint/GridPainter.h" |
32 #include "core/paint/PaintLayer.h" | 34 #include "core/paint/PaintLayer.h" |
33 #include "core/style/ComputedStyle.h" | 35 #include "core/style/ComputedStyle.h" |
34 #include "core/style/GridArea.h" | 36 #include "core/style/GridArea.h" |
35 #include "platform/LengthFunctions.h" | 37 #include "platform/LengthFunctions.h" |
| 38 #include "platform/text/WritingMode.h" |
36 #include "wtf/PtrUtil.h" | 39 #include "wtf/PtrUtil.h" |
37 #include <algorithm> | |
38 #include <memory> | |
39 | 40 |
40 namespace blink { | 41 namespace blink { |
41 | 42 |
42 struct ContentAlignmentData { | 43 struct ContentAlignmentData { |
43 STACK_ALLOCATED(); | 44 STACK_ALLOCATED(); |
44 | 45 |
45 public: | 46 public: |
46 ContentAlignmentData(){}; | 47 ContentAlignmentData(){}; |
47 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) | 48 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) |
48 : positionOffset(position), distributionOffset(distribution) {} | 49 : positionOffset(position), distributionOffset(distribution) {} |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 TrackSizing, availableSpace, freeSpace); | 161 TrackSizing, availableSpace, freeSpace); |
161 m_trackSizingAlgorithm.run(); | 162 m_trackSizingAlgorithm.run(); |
162 | 163 |
163 #if DCHECK_IS_ON() | 164 #if DCHECK_IS_ON() |
164 DCHECK(m_trackSizingAlgorithm.tracksAreWiderThanMinTrackBreadth()); | 165 DCHECK(m_trackSizingAlgorithm.tracksAreWiderThanMinTrackBreadth()); |
165 #endif | 166 #endif |
166 } | 167 } |
167 | 168 |
168 void LayoutGrid::repeatTracksSizingIfNeeded(LayoutUnit availableSpaceForColumns, | 169 void LayoutGrid::repeatTracksSizingIfNeeded(LayoutUnit availableSpaceForColumns, |
169 LayoutUnit availableSpaceForRows) { | 170 LayoutUnit availableSpaceForRows) { |
| 171 // Baseline alignment may change item's intrinsic size, hence changing its |
| 172 // min-content contribution. |
| 173 // https://drafts.csswg.org/css-align-3/#baseline-align-content |
| 174 // https://drafts.csswg.org/css-align-3/#baseline-align-self |
| 175 bool baselineAffectIntrinsicWidth = baselineMayAffectIntrinsicWidth(); |
| 176 bool baselineAffectIntrinsicHeight = baselineMayAffectIntrinsicHeight(); |
| 177 |
170 // In orthogonal flow cases column track's size is determined by using the | 178 // In orthogonal flow cases column track's size is determined by using the |
171 // computed row track's size, which it was estimated during the first cycle of | 179 // computed row track's size, which it was estimated during the first cycle of |
172 // the sizing algorithm. | 180 // the sizing algorithm. |
173 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns | 181 bool hasAnyOrthogonal = |
174 // and rows, to determine the final values. | 182 m_trackSizingAlgorithm.grid().hasAnyOrthogonalGridItem(); |
175 // TODO (lajava): orthogonal flows is just one of the cases which may require | 183 |
| 184 // TODO (lajava): these are just some of the cases which may require |
176 // a new cycle of the sizing algorithm; there may be more. In addition, not | 185 // a new cycle of the sizing algorithm; there may be more. In addition, not |
177 // all the cases with orthogonal flows require this extra cycle; we need a | 186 // all the cases with orthogonal flows require this extra cycle; we need a |
178 // more specific condition to detect whether child's min-content contribution | 187 // more specific condition to detect whether child's min-content contribution |
179 // has changed or not. | 188 // has changed or not. |
180 if (m_grid.hasAnyOrthogonalGridItem()) { | 189 if (!baselineAffectIntrinsicWidth && !baselineAffectIntrinsicHeight && |
181 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns); | 190 !hasAnyOrthogonal) |
182 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows); | 191 return; |
| 192 |
| 193 // TODO (lajava): Whenever the min-content contribution of a grid item changes |
| 194 // we may need to update the grid container's intrinsic width. The new |
| 195 // intrinsic width may also affect the extra Track Sizing algorithm cycles we |
| 196 // are about to execute. |
| 197 // https://crbug.com/704713 |
| 198 // https://github.com/w3c/csswg-drafts/issues/1039 |
| 199 |
| 200 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns |
| 201 // and rows, to determine the final values. |
| 202 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns); |
| 203 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows); |
| 204 |
| 205 if (baselineAffectIntrinsicHeight) { |
| 206 setLogicalHeight(computeTrackBasedLogicalHeight() + |
| 207 borderAndPaddingLogicalHeight() + |
| 208 scrollbarLogicalHeight()); |
183 } | 209 } |
184 } | 210 } |
185 | 211 |
186 void LayoutGrid::layoutBlock(bool relayoutChildren) { | 212 void LayoutGrid::layoutBlock(bool relayoutChildren) { |
187 ASSERT(needsLayout()); | 213 ASSERT(needsLayout()); |
188 | 214 |
189 // We cannot perform a simplifiedLayout() on a dirty grid that | 215 // We cannot perform a simplifiedLayout() on a dirty grid that |
190 // has positioned items to be laid out. | 216 // has positioned items to be laid out. |
191 if (!relayoutChildren && | 217 if (!relayoutChildren && |
192 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && | 218 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && |
193 simplifiedLayout()) | 219 simplifiedLayout()) |
194 return; | 220 return; |
195 | 221 |
| 222 m_rowAxisAlignmentContext.clear(); |
| 223 m_colAxisAlignmentContext.clear(); |
| 224 |
196 SubtreeLayoutScope layoutScope(*this); | 225 SubtreeLayoutScope layoutScope(*this); |
197 | 226 |
198 { | 227 { |
199 // LayoutState needs this deliberate scope to pop before updating scroll | 228 // LayoutState needs this deliberate scope to pop before updating scroll |
200 // information (which may trigger relayout). | 229 // information (which may trigger relayout). |
201 LayoutState state(*this); | 230 LayoutState state(*this); |
202 | 231 |
203 LayoutSize previousSize = size(); | 232 LayoutSize previousSize = size(); |
204 | 233 |
205 // We need to clear both own and containingBlock override sizes to | 234 // We need to clear both own and containingBlock override sizes to |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); | 281 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
253 updateLogicalHeight(); | 282 updateLogicalHeight(); |
254 | 283 |
255 // Once grid's indefinite height is resolved, we can compute the | 284 // Once grid's indefinite height is resolved, we can compute the |
256 // available free space for Content Alignment. | 285 // available free space for Content Alignment. |
257 if (!cachedHasDefiniteLogicalHeight()) { | 286 if (!cachedHasDefiniteLogicalHeight()) { |
258 m_trackSizingAlgorithm.freeSpace(ForRows) = | 287 m_trackSizingAlgorithm.freeSpace(ForRows) = |
259 logicalHeight() - trackBasedLogicalHeight; | 288 logicalHeight() - trackBasedLogicalHeight; |
260 } | 289 } |
261 | 290 |
| 291 // TODO (lajava): We need to compute baselines after step 2 so |
| 292 // items with a relative size (percentages) can resolve it before |
| 293 // determining its baseline. However, we only set item's grid area |
| 294 // (via override sizes) as part of the content-sized tracks sizing |
| 295 // logic. Hence, items located at fixed or flexible tracks can't |
| 296 // resolve correctly their size at this stage, which may lead to |
| 297 // an incorrect computation of their shared context's baseline. |
| 298 computeBaselineAlignmentContext(); |
| 299 |
262 // 3- If the min-content contribution of any grid items have changed based | 300 // 3- If the min-content contribution of any grid items have changed based |
263 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with | 301 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with |
264 // the new min-content contribution (once only). | 302 // the new min-content contribution (once only). |
265 repeatTracksSizingIfNeeded(availableSpaceForColumns, | 303 repeatTracksSizingIfNeeded(availableSpaceForColumns, |
266 contentLogicalHeight()); | 304 contentLogicalHeight()); |
267 | 305 |
268 // Grid container should have the minimum height of a line if it's editable. | 306 // Grid container should have the minimum height of a line if it's editable. |
269 // That doesn't affect track sizing though. | 307 // That doesn't affect track sizing though. |
270 if (hasLineIfEmpty()) | 308 if (hasLineIfEmpty()) |
271 setLogicalHeight( | 309 setLogicalHeight( |
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 .toInt(); | 1611 .toInt(); |
1574 } | 1612 } |
1575 | 1613 |
1576 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, | 1614 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, |
1577 LineDirectionMode direction) { | 1615 LineDirectionMode direction) { |
1578 return (direction == HorizontalLine ? box.size().height() | 1616 return (direction == HorizontalLine ? box.size().height() |
1579 : box.size().width()) | 1617 : box.size().width()) |
1580 .toInt(); | 1618 .toInt(); |
1581 } | 1619 } |
1582 | 1620 |
1583 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be | |
1584 // refactored somehow. | |
1585 int LayoutGrid::baselinePosition(FontBaseline, | 1621 int LayoutGrid::baselinePosition(FontBaseline, |
1586 bool, | 1622 bool, |
1587 LineDirectionMode direction, | 1623 LineDirectionMode direction, |
1588 LinePositionMode mode) const { | 1624 LinePositionMode mode) const { |
1589 DCHECK_EQ(mode, PositionOnContainingLine); | 1625 DCHECK_EQ(mode, PositionOnContainingLine); |
1590 int baseline = firstLineBoxBaseline(); | 1626 int baseline = firstLineBoxBaseline(); |
1591 // We take content-box's bottom if no valid baseline. | 1627 // We take content-box's bottom if no valid baseline. |
1592 if (baseline == -1) | 1628 if (baseline == -1) |
1593 baseline = synthesizedBaselineFromContentBox(*this, direction); | 1629 baseline = synthesizedBaselineFromContentBox(*this, direction); |
1594 | 1630 |
1595 return baseline + beforeMarginInLineDirection(direction); | 1631 return baseline + beforeMarginInLineDirection(direction); |
1596 } | 1632 } |
1597 | 1633 |
1598 bool LayoutGrid::isInlineBaselineAlignedChild(const LayoutBox* child) const { | |
1599 return alignSelfForChild(*child).position() == ItemPositionBaseline && | |
1600 !isOrthogonalChild(*child) && !hasAutoMarginsInColumnAxis(*child); | |
1601 } | |
1602 | |
1603 int LayoutGrid::firstLineBoxBaseline() const { | 1634 int LayoutGrid::firstLineBoxBaseline() const { |
1604 if (isWritingModeRoot() || !m_grid.hasGridItems()) | 1635 if (isWritingModeRoot() || !m_grid.hasGridItems()) |
1605 return -1; | 1636 return -1; |
1606 const LayoutBox* baselineChild = nullptr; | 1637 const LayoutBox* baselineChild = nullptr; |
1607 const LayoutBox* firstChild = nullptr; | 1638 const LayoutBox* firstChild = nullptr; |
1608 bool isBaselineAligned = false; | 1639 bool isBaselineAligned = false; |
1609 // Finding the first grid item in grid order. | 1640 // Finding the first grid item in grid order. |
1610 for (size_t column = 0; | 1641 for (size_t column = 0; |
1611 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { | 1642 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { |
1612 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { | 1643 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { |
1613 const LayoutBox* child = m_grid.cell(0, column)[index]; | 1644 const LayoutBox* child = m_grid.cell(0, column)[index]; |
1614 DCHECK(!child->isOutOfFlowPositioned()); | 1645 DCHECK(!child->isOutOfFlowPositioned()); |
1615 // If an item participates in baseline alignmen, we select such item. | 1646 // If an item participates in baseline alignment, we select such item. |
1616 if (isInlineBaselineAlignedChild(child)) { | 1647 if (isBaselineAlignmentForChild(*child)) { |
1617 // TODO (lajava): self-baseline and content-baseline alignment | 1648 // TODO (lajava): self-baseline and content-baseline alignment |
1618 // still not implemented. | 1649 // still not implemented. |
1619 baselineChild = child; | 1650 baselineChild = child; |
1620 isBaselineAligned = true; | 1651 isBaselineAligned = true; |
1621 break; | 1652 break; |
1622 } | 1653 } |
1623 if (!baselineChild) { | 1654 if (!baselineChild) { |
1624 // Use dom order for items in the same cell. | 1655 // Use dom order for items in the same cell. |
1625 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < | 1656 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < |
1626 m_grid.gridItemPaintOrder(*firstChild))) | 1657 m_grid.gridItemPaintOrder(*firstChild))) |
(...skipping 29 matching lines...) Expand all Loading... |
1656 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { | 1687 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { |
1657 int baseline = firstLineBoxBaseline(); | 1688 int baseline = firstLineBoxBaseline(); |
1658 if (baseline != -1) | 1689 if (baseline != -1) |
1659 return baseline; | 1690 return baseline; |
1660 | 1691 |
1661 int marginHeight = | 1692 int marginHeight = |
1662 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); | 1693 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); |
1663 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; | 1694 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; |
1664 } | 1695 } |
1665 | 1696 |
| 1697 bool LayoutGrid::isHorizontalGridAxis(GridAxis axis) const { |
| 1698 return axis == GridRowAxis ? isHorizontalWritingMode() |
| 1699 : !isHorizontalWritingMode(); |
| 1700 } |
| 1701 |
| 1702 bool LayoutGrid::isParallelToBlockAxisForChild(const LayoutBox& child, |
| 1703 GridAxis axis) const { |
| 1704 return axis == GridColumnAxis ? !isOrthogonalChild(child) |
| 1705 : isOrthogonalChild(child); |
| 1706 } |
| 1707 |
| 1708 bool LayoutGrid::isDescentBaselineForChild(const LayoutBox& child, |
| 1709 GridAxis baselineAxis) const { |
| 1710 return isHorizontalGridAxis(baselineAxis) && |
| 1711 ((child.styleRef().isFlippedBlocksWritingMode() && |
| 1712 !styleRef().isFlippedBlocksWritingMode()) || |
| 1713 (child.styleRef().isFlippedLinesWritingMode() && |
| 1714 styleRef().isFlippedBlocksWritingMode())); |
| 1715 } |
| 1716 |
| 1717 bool LayoutGrid::isBaselineAlignmentForChild(const LayoutBox& child, |
| 1718 GridAxis baselineAxis) const { |
| 1719 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 1720 ItemPosition align = isColumnAxisBaseline |
| 1721 ? alignSelfForChild(child).position() |
| 1722 : justifySelfForChild(child).position(); |
| 1723 bool hasAutoMargins = isColumnAxisBaseline ? hasAutoMarginsInColumnAxis(child) |
| 1724 : hasAutoMarginsInRowAxis(child); |
| 1725 return isBaselinePosition(align) && !hasAutoMargins; |
| 1726 } |
| 1727 |
| 1728 const BaselineGroup& LayoutGrid::getBaselineGroupForChild( |
| 1729 const LayoutBox& child, |
| 1730 GridAxis baselineAxis) const { |
| 1731 DCHECK(isBaselineAlignmentForChild(child, baselineAxis)); |
| 1732 auto& grid = m_trackSizingAlgorithm.grid(); |
| 1733 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 1734 bool isRowAxisContext = isColumnAxisBaseline; |
| 1735 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) |
| 1736 : grid.gridItemSpan(child, ForColumns); |
| 1737 auto& contextsMap = |
| 1738 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; |
| 1739 auto* context = contextsMap.at(span.startLine()); |
| 1740 DCHECK(context); |
| 1741 ItemPosition align = isColumnAxisBaseline |
| 1742 ? alignSelfForChild(child).position() |
| 1743 : justifySelfForChild(child).position(); |
| 1744 return context->getSharedGroup(child, align); |
| 1745 } |
| 1746 |
| 1747 LayoutUnit LayoutGrid::marginOverForChild(const LayoutBox& child, |
| 1748 GridAxis axis) const { |
| 1749 return isHorizontalGridAxis(axis) ? child.marginRight() : child.marginTop(); |
| 1750 } |
| 1751 |
| 1752 LayoutUnit LayoutGrid::marginUnderForChild(const LayoutBox& child, |
| 1753 GridAxis axis) const { |
| 1754 return isHorizontalGridAxis(axis) ? child.marginLeft() : child.marginBottom(); |
| 1755 } |
| 1756 |
| 1757 LayoutUnit LayoutGrid::logicalAscentForChild(const LayoutBox& child, |
| 1758 GridAxis baselineAxis) const { |
| 1759 LayoutUnit ascent = ascentForChild(child, baselineAxis); |
| 1760 return isDescentBaselineForChild(child, baselineAxis) |
| 1761 ? descentForChild(child, ascent, baselineAxis) |
| 1762 : ascent; |
| 1763 } |
| 1764 |
| 1765 LayoutUnit LayoutGrid::ascentForChild(const LayoutBox& child, |
| 1766 GridAxis baselineAxis) const { |
| 1767 LayoutUnit margin = isDescentBaselineForChild(child, baselineAxis) |
| 1768 ? marginUnderForChild(child, baselineAxis) |
| 1769 : marginOverForChild(child, baselineAxis); |
| 1770 int baseline = isParallelToBlockAxisForChild(child, baselineAxis) |
| 1771 ? child.firstLineBoxBaseline() |
| 1772 : -1; |
| 1773 // We take border-box's under edge if no valid baseline. |
| 1774 if (baseline == -1) { |
| 1775 if (isHorizontalGridAxis(baselineAxis)) { |
| 1776 return styleRef().isFlippedBlocksWritingMode() |
| 1777 ? child.size().width().toInt() + margin |
| 1778 : margin; |
| 1779 } |
| 1780 return child.size().height() + margin; |
| 1781 } |
| 1782 return LayoutUnit(baseline) + margin; |
| 1783 } |
| 1784 |
| 1785 LayoutUnit LayoutGrid::descentForChild(const LayoutBox& child, |
| 1786 LayoutUnit ascent, |
| 1787 GridAxis baselineAxis) const { |
| 1788 if (isParallelToBlockAxisForChild(child, baselineAxis)) |
| 1789 return child.marginLogicalHeight() + child.logicalHeight() - ascent; |
| 1790 return child.marginLogicalWidth() + child.logicalWidth() - ascent; |
| 1791 } |
| 1792 |
| 1793 bool LayoutGrid::isBaselineContextComputed(GridAxis baselineAxis) const { |
| 1794 return baselineAxis == GridColumnAxis ? !m_rowAxisAlignmentContext.isEmpty() |
| 1795 : !m_colAxisAlignmentContext.isEmpty(); |
| 1796 } |
| 1797 |
| 1798 bool LayoutGrid::baselineMayAffectIntrinsicWidth() const { |
| 1799 if (!styleRef().logicalWidth().isIntrinsicOrAuto()) |
| 1800 return false; |
| 1801 for (const auto& context : m_colAxisAlignmentContext) { |
| 1802 for (const auto& group : context.value->sharedGroups()) { |
| 1803 if (group.size() > 1) |
| 1804 return true; |
| 1805 } |
| 1806 } |
| 1807 return false; |
| 1808 } |
| 1809 |
| 1810 bool LayoutGrid::baselineMayAffectIntrinsicHeight() const { |
| 1811 if (!styleRef().logicalHeight().isIntrinsicOrAuto()) |
| 1812 return false; |
| 1813 for (const auto& context : m_rowAxisAlignmentContext) { |
| 1814 for (const auto& group : context.value->sharedGroups()) { |
| 1815 if (group.size() > 1) |
| 1816 return true; |
| 1817 } |
| 1818 } |
| 1819 return false; |
| 1820 } |
| 1821 |
| 1822 void LayoutGrid::computeBaselineAlignmentContext() { |
| 1823 for (auto* child = firstInFlowChildBox(); child; |
| 1824 child = child->nextInFlowSiblingBox()) { |
| 1825 updateBaselineAlignmentContextIfNeeded(*child, GridRowAxis); |
| 1826 updateBaselineAlignmentContextIfNeeded(*child, GridColumnAxis); |
| 1827 } |
| 1828 } |
| 1829 |
| 1830 void LayoutGrid::updateBaselineAlignmentContextIfNeeded(LayoutBox& child, |
| 1831 GridAxis baselineAxis) { |
| 1832 // TODO (lajava): We must ensure this method is not called as part of an |
| 1833 // intrinsic size computation. |
| 1834 if (!isBaselineAlignmentForChild(child, baselineAxis)) |
| 1835 return; |
| 1836 |
| 1837 child.layoutIfNeeded(); |
| 1838 |
| 1839 // Determine Ascent and Descent values of this child with respect to |
| 1840 // its grid container. |
| 1841 LayoutUnit ascent = ascentForChild(child, baselineAxis); |
| 1842 LayoutUnit descent = descentForChild(child, ascent, baselineAxis); |
| 1843 if (isDescentBaselineForChild(child, baselineAxis)) |
| 1844 std::swap(ascent, descent); |
| 1845 |
| 1846 // Looking up for a shared alignment context perpendicular to the |
| 1847 // baseline axis. |
| 1848 auto& grid = m_trackSizingAlgorithm.grid(); |
| 1849 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 1850 bool isRowAxisContext = isColumnAxisBaseline; |
| 1851 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) |
| 1852 : grid.gridItemSpan(child, ForColumns); |
| 1853 auto& contextsMap = |
| 1854 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; |
| 1855 auto addResult = contextsMap.insert(span.startLine(), nullptr); |
| 1856 |
| 1857 // Looking for a compatible baseline-sharing group. |
| 1858 ItemPosition align = isColumnAxisBaseline |
| 1859 ? alignSelfForChild(child).position() |
| 1860 : justifySelfForChild(child).position(); |
| 1861 if (addResult.isNewEntry) { |
| 1862 addResult.storedValue->value = |
| 1863 WTF::makeUnique<BaselineContext>(child, align, ascent, descent); |
| 1864 } else { |
| 1865 auto* context = addResult.storedValue->value.get(); |
| 1866 context->updateSharedGroup(child, align, ascent, descent); |
| 1867 } |
| 1868 } |
| 1869 |
| 1870 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild( |
| 1871 const LayoutBox& child) const { |
| 1872 if (!isBaselineAlignmentForChild(child, GridColumnAxis)) |
| 1873 return LayoutUnit(); |
| 1874 auto& group = getBaselineGroupForChild(child, GridColumnAxis); |
| 1875 if (group.size() > 1) |
| 1876 return group.maxAscent() - logicalAscentForChild(child, GridColumnAxis); |
| 1877 return LayoutUnit(); |
| 1878 } |
| 1879 |
| 1880 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild( |
| 1881 const LayoutBox& child) const { |
| 1882 if (!isBaselineAlignmentForChild(child, GridRowAxis)) |
| 1883 return LayoutUnit(); |
| 1884 auto& group = getBaselineGroupForChild(child, GridRowAxis); |
| 1885 if (group.size() > 1) |
| 1886 return group.maxAscent() - logicalAscentForChild(child, GridRowAxis); |
| 1887 return LayoutUnit(); |
| 1888 } |
| 1889 |
1666 GridAxisPosition LayoutGrid::columnAxisPositionForChild( | 1890 GridAxisPosition LayoutGrid::columnAxisPositionForChild( |
1667 const LayoutBox& child) const { | 1891 const LayoutBox& child) const { |
1668 bool hasSameWritingMode = | 1892 bool hasSameWritingMode = |
1669 child.styleRef().getWritingMode() == styleRef().getWritingMode(); | 1893 child.styleRef().getWritingMode() == styleRef().getWritingMode(); |
1670 bool childIsLTR = child.styleRef().isLeftToRightDirection(); | 1894 bool childIsLTR = child.styleRef().isLeftToRightDirection(); |
1671 | 1895 |
1672 switch (alignSelfForChild(child).position()) { | 1896 switch (alignSelfForChild(child).position()) { |
1673 case ItemPositionSelfStart: | 1897 case ItemPositionSelfStart: |
1674 // TODO (lajava): Should we implement this logic in a generic utility | 1898 // TODO (lajava): Should we implement this logic in a generic utility |
1675 // function? | 1899 // function? |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 // Only used in flex layout, otherwise equivalent to 'end'. | 1949 // Only used in flex layout, otherwise equivalent to 'end'. |
1726 case ItemPositionFlexEnd: | 1950 case ItemPositionFlexEnd: |
1727 // Aligns the alignment subject to be flush with the alignment container's | 1951 // Aligns the alignment subject to be flush with the alignment container's |
1728 // 'end' edge (block-end) in the column axis. | 1952 // 'end' edge (block-end) in the column axis. |
1729 case ItemPositionEnd: | 1953 case ItemPositionEnd: |
1730 return GridAxisEnd; | 1954 return GridAxisEnd; |
1731 case ItemPositionStretch: | 1955 case ItemPositionStretch: |
1732 return GridAxisStart; | 1956 return GridAxisStart; |
1733 case ItemPositionBaseline: | 1957 case ItemPositionBaseline: |
1734 case ItemPositionLastBaseline: | 1958 case ItemPositionLastBaseline: |
1735 // FIXME: These two require implementing Baseline Alignment. For now, we | |
1736 // always 'start' align the child. crbug.com/234191 | |
1737 return GridAxisStart; | 1959 return GridAxisStart; |
1738 case ItemPositionAuto: | 1960 case ItemPositionAuto: |
1739 case ItemPositionNormal: | 1961 case ItemPositionNormal: |
1740 break; | 1962 break; |
1741 } | 1963 } |
1742 | 1964 |
1743 NOTREACHED(); | 1965 NOTREACHED(); |
1744 return GridAxisStart; | 1966 return GridAxisStart; |
1745 } | 1967 } |
1746 | 1968 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1804 // Only used in flex layout, otherwise equivalent to 'end'. | 2026 // Only used in flex layout, otherwise equivalent to 'end'. |
1805 case ItemPositionFlexEnd: | 2027 case ItemPositionFlexEnd: |
1806 // Aligns the alignment subject to be flush with the alignment container's | 2028 // Aligns the alignment subject to be flush with the alignment container's |
1807 // 'end' edge (inline-end) in the row axis. | 2029 // 'end' edge (inline-end) in the row axis. |
1808 case ItemPositionEnd: | 2030 case ItemPositionEnd: |
1809 return GridAxisEnd; | 2031 return GridAxisEnd; |
1810 case ItemPositionStretch: | 2032 case ItemPositionStretch: |
1811 return GridAxisStart; | 2033 return GridAxisStart; |
1812 case ItemPositionBaseline: | 2034 case ItemPositionBaseline: |
1813 case ItemPositionLastBaseline: | 2035 case ItemPositionLastBaseline: |
1814 // FIXME: These two require implementing Baseline Alignment. For now, we | |
1815 // always 'start' align the child. crbug.com/234191 | |
1816 return GridAxisStart; | 2036 return GridAxisStart; |
1817 case ItemPositionAuto: | 2037 case ItemPositionAuto: |
1818 case ItemPositionNormal: | 2038 case ItemPositionNormal: |
1819 break; | 2039 break; |
1820 } | 2040 } |
1821 | 2041 |
1822 NOTREACHED(); | 2042 NOTREACHED(); |
1823 return GridAxisStart; | 2043 return GridAxisStart; |
1824 } | 2044 } |
1825 | 2045 |
1826 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const { | 2046 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const { |
1827 const GridSpan& rowsSpan = | 2047 const GridSpan& rowsSpan = |
1828 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows); | 2048 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows); |
1829 size_t childStartLine = rowsSpan.startLine(); | 2049 size_t childStartLine = rowsSpan.startLine(); |
1830 LayoutUnit startOfRow = m_rowPositions[childStartLine]; | 2050 LayoutUnit startOfRow = m_rowPositions[childStartLine]; |
1831 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 2051 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
1832 if (hasAutoMarginsInColumnAxis(child)) | 2052 if (hasAutoMarginsInColumnAxis(child)) |
1833 return startPosition; | 2053 return startPosition; |
1834 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 2054 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
1835 switch (axisPosition) { | 2055 switch (axisPosition) { |
1836 case GridAxisStart: | 2056 case GridAxisStart: |
1837 return startPosition; | 2057 return startPosition + columnAxisBaselineOffsetForChild(child); |
1838 case GridAxisEnd: | 2058 case GridAxisEnd: |
1839 case GridAxisCenter: { | 2059 case GridAxisCenter: { |
1840 size_t childEndLine = rowsSpan.endLine(); | 2060 size_t childEndLine = rowsSpan.endLine(); |
1841 LayoutUnit endOfRow = m_rowPositions[childEndLine]; | 2061 LayoutUnit endOfRow = m_rowPositions[childEndLine]; |
1842 // m_rowPositions include distribution offset (because of content | 2062 // m_rowPositions include distribution offset (because of content |
1843 // alignment) and gutters so we need to subtract them to get the actual | 2063 // alignment) and gutters so we need to subtract them to get the actual |
1844 // end position for a given row (this does not have to be done for the | 2064 // end position for a given row (this does not have to be done for the |
1845 // last track as there are no more m_columnPositions after it). | 2065 // last track as there are no more m_columnPositions after it). |
1846 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing); | 2066 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing); |
1847 if (childEndLine < m_rowPositions.size() - 1) { | 2067 if (childEndLine < m_rowPositions.size() - 1) { |
(...skipping 21 matching lines...) Expand all Loading... |
1869 const GridSpan& columnsSpan = | 2089 const GridSpan& columnsSpan = |
1870 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns); | 2090 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns); |
1871 size_t childStartLine = columnsSpan.startLine(); | 2091 size_t childStartLine = columnsSpan.startLine(); |
1872 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; | 2092 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; |
1873 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 2093 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
1874 if (hasAutoMarginsInRowAxis(child)) | 2094 if (hasAutoMarginsInRowAxis(child)) |
1875 return startPosition; | 2095 return startPosition; |
1876 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 2096 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
1877 switch (axisPosition) { | 2097 switch (axisPosition) { |
1878 case GridAxisStart: | 2098 case GridAxisStart: |
1879 return startPosition; | 2099 return startPosition + rowAxisBaselineOffsetForChild(child); |
1880 case GridAxisEnd: | 2100 case GridAxisEnd: |
1881 case GridAxisCenter: { | 2101 case GridAxisCenter: { |
1882 size_t childEndLine = columnsSpan.endLine(); | 2102 size_t childEndLine = columnsSpan.endLine(); |
1883 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; | 2103 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; |
1884 // m_columnPositions include distribution offset (because of content | 2104 // m_columnPositions include distribution offset (because of content |
1885 // alignment) and gutters so we need to subtract them to get the actual | 2105 // alignment) and gutters so we need to subtract them to get the actual |
1886 // end position for a given column (this does not have to be done for the | 2106 // end position for a given column (this does not have to be done for the |
1887 // last track as there are no more m_columnPositions after it). | 2107 // last track as there are no more m_columnPositions after it). |
1888 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing); | 2108 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing); |
1889 if (childEndLine < m_columnPositions.size() - 1) { | 2109 if (childEndLine < m_columnPositions.size() - 1) { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 if (direction == ForRows) | 2323 if (direction == ForRows) |
2104 return grid.numTracks(ForRows); | 2324 return grid.numTracks(ForRows); |
2105 | 2325 |
2106 return grid.numTracks(ForRows) | 2326 return grid.numTracks(ForRows) |
2107 ? grid.numTracks(ForColumns) | 2327 ? grid.numTracks(ForColumns) |
2108 : GridPositionsResolver::explicitGridColumnCount( | 2328 : GridPositionsResolver::explicitGridColumnCount( |
2109 styleRef(), grid.autoRepeatTracks(ForColumns)); | 2329 styleRef(), grid.autoRepeatTracks(ForColumns)); |
2110 } | 2330 } |
2111 | 2331 |
2112 } // namespace blink | 2332 } // namespace blink |
OLD | NEW |