Chromium Code Reviews| 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(); |
|
svillar
2017/03/24 10:52:05
Nit: no need for a variable here, we just use this
jfernandez
2017/03/24 14:15:18
Well, I admit it's not strictly necessary but IMHO
| |
| 175 // TODO (lajava): orthogonal flows is just one of the cases which may require | 183 |
| 184 bool intrinsicWidthMayHaveChanged = | |
| 185 baselineAffectIntrinsicWidth || hasAnyOrthogonal; | |
| 186 if (!intrinsicWidthMayHaveChanged && !baselineAffectIntrinsicHeight) | |
| 187 return; | |
| 188 | |
| 189 // 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 | 190 // 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 | 191 // 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 | 192 // more specific condition to detect whether child's min-content contribution |
| 179 // has changed or not. | 193 // has changed or not. |
| 180 if (m_grid.hasAnyOrthogonalGridItem()) { | 194 if (!intrinsicWidthMayHaveChanged && !baselineAffectIntrinsicHeight) |
| 181 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns); | 195 return; |
| 182 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows); | 196 |
| 197 // TODO (lajava): Whenever the min-content contribution of a grid item changes | |
| 198 // we may need to update the grid container's intrinsic width. The new | |
| 199 // intrinsic width may also affect the extra Track Sizing algorithm cycles we | |
| 200 // are about to execute. | |
| 201 // https://crbug.com/704713 | |
| 202 // https://github.com/w3c/csswg-drafts/issues/1039 | |
| 203 | |
| 204 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns | |
| 205 // and rows, to determine the final values. | |
| 206 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns); | |
| 207 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows); | |
| 208 | |
| 209 if (baselineAffectIntrinsicHeight) { | |
| 210 setLogicalHeight(computeTrackBasedLogicalHeight() + | |
| 211 borderAndPaddingLogicalHeight() + | |
| 212 scrollbarLogicalHeight()); | |
| 183 } | 213 } |
| 184 } | 214 } |
| 185 | 215 |
| 186 void LayoutGrid::layoutBlock(bool relayoutChildren) { | 216 void LayoutGrid::layoutBlock(bool relayoutChildren) { |
| 187 ASSERT(needsLayout()); | 217 ASSERT(needsLayout()); |
| 188 | 218 |
| 189 // We cannot perform a simplifiedLayout() on a dirty grid that | 219 // We cannot perform a simplifiedLayout() on a dirty grid that |
| 190 // has positioned items to be laid out. | 220 // has positioned items to be laid out. |
| 191 if (!relayoutChildren && | 221 if (!relayoutChildren && |
| 192 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && | 222 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && |
| 193 simplifiedLayout()) | 223 simplifiedLayout()) |
| 194 return; | 224 return; |
| 195 | 225 |
| 226 m_rowAxisAlignmentContext.clear(); | |
| 227 m_colAxisAlignmentContext.clear(); | |
| 228 | |
| 196 SubtreeLayoutScope layoutScope(*this); | 229 SubtreeLayoutScope layoutScope(*this); |
| 197 | 230 |
| 198 { | 231 { |
| 199 // LayoutState needs this deliberate scope to pop before updating scroll | 232 // LayoutState needs this deliberate scope to pop before updating scroll |
| 200 // information (which may trigger relayout). | 233 // information (which may trigger relayout). |
| 201 LayoutState state(*this); | 234 LayoutState state(*this); |
| 202 | 235 |
| 203 LayoutSize previousSize = size(); | 236 LayoutSize previousSize = size(); |
| 204 | 237 |
| 205 // We need to clear both own and containingBlock override sizes to | 238 // 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(); | 285 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
| 253 updateLogicalHeight(); | 286 updateLogicalHeight(); |
| 254 | 287 |
| 255 // Once grid's indefinite height is resolved, we can compute the | 288 // Once grid's indefinite height is resolved, we can compute the |
| 256 // available free space for Content Alignment. | 289 // available free space for Content Alignment. |
| 257 if (!cachedHasDefiniteLogicalHeight()) { | 290 if (!cachedHasDefiniteLogicalHeight()) { |
| 258 m_trackSizingAlgorithm.freeSpace(ForRows) = | 291 m_trackSizingAlgorithm.freeSpace(ForRows) = |
| 259 logicalHeight() - trackBasedLogicalHeight; | 292 logicalHeight() - trackBasedLogicalHeight; |
| 260 } | 293 } |
| 261 | 294 |
| 295 // TODO (lajava): We need to compute baselines after step 2 so | |
| 296 // items with a relative size (percentages) can resolve it before | |
| 297 // determining its baseline. However, we only set item's grid area | |
| 298 // (via override sizes) as part of the content-sized tracks sizing | |
| 299 // logic. Hence, items located at fixed or flexible tracks can't | |
| 300 // resolve correctly their size at this stage, which may lead to | |
| 301 // an incorrect computation of their shared context's baseline. | |
| 302 computeBaselineAlignmentContext(); | |
|
svillar
2017/03/24 10:52:05
I have just realized that we do this before applyi
jfernandez
2017/03/24 14:15:18
Yes, indeed. It's a really good point and I admit
| |
| 303 | |
| 262 // 3- If the min-content contribution of any grid items have changed based | 304 // 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 | 305 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with |
| 264 // the new min-content contribution (once only). | 306 // the new min-content contribution (once only). |
| 265 repeatTracksSizingIfNeeded(availableSpaceForColumns, | 307 repeatTracksSizingIfNeeded(availableSpaceForColumns, |
| 266 contentLogicalHeight()); | 308 contentLogicalHeight()); |
| 267 | 309 |
| 268 // Grid container should have the minimum height of a line if it's editable. | 310 // Grid container should have the minimum height of a line if it's editable. |
| 269 // That doesn't affect track sizing though. | 311 // That doesn't affect track sizing though. |
| 270 if (hasLineIfEmpty()) | 312 if (hasLineIfEmpty()) |
| 271 setLogicalHeight( | 313 setLogicalHeight( |
| (...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1573 .toInt(); | 1615 .toInt(); |
| 1574 } | 1616 } |
| 1575 | 1617 |
| 1576 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, | 1618 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, |
| 1577 LineDirectionMode direction) { | 1619 LineDirectionMode direction) { |
| 1578 return (direction == HorizontalLine ? box.size().height() | 1620 return (direction == HorizontalLine ? box.size().height() |
| 1579 : box.size().width()) | 1621 : box.size().width()) |
| 1580 .toInt(); | 1622 .toInt(); |
| 1581 } | 1623 } |
| 1582 | 1624 |
| 1583 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be | |
| 1584 // refactored somehow. | |
| 1585 int LayoutGrid::baselinePosition(FontBaseline, | 1625 int LayoutGrid::baselinePosition(FontBaseline, |
| 1586 bool, | 1626 bool, |
| 1587 LineDirectionMode direction, | 1627 LineDirectionMode direction, |
| 1588 LinePositionMode mode) const { | 1628 LinePositionMode mode) const { |
| 1589 DCHECK_EQ(mode, PositionOnContainingLine); | 1629 DCHECK_EQ(mode, PositionOnContainingLine); |
| 1590 int baseline = firstLineBoxBaseline(); | 1630 int baseline = firstLineBoxBaseline(); |
| 1591 // We take content-box's bottom if no valid baseline. | 1631 // We take content-box's bottom if no valid baseline. |
| 1592 if (baseline == -1) | 1632 if (baseline == -1) |
| 1593 baseline = synthesizedBaselineFromContentBox(*this, direction); | 1633 baseline = synthesizedBaselineFromContentBox(*this, direction); |
| 1594 | 1634 |
| 1595 return baseline + beforeMarginInLineDirection(direction); | 1635 return baseline + beforeMarginInLineDirection(direction); |
| 1596 } | 1636 } |
| 1597 | 1637 |
| 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 { | 1638 int LayoutGrid::firstLineBoxBaseline() const { |
| 1604 if (isWritingModeRoot() || !m_grid.hasGridItems()) | 1639 if (isWritingModeRoot() || !m_grid.hasGridItems()) |
| 1605 return -1; | 1640 return -1; |
| 1606 const LayoutBox* baselineChild = nullptr; | 1641 const LayoutBox* baselineChild = nullptr; |
| 1607 const LayoutBox* firstChild = nullptr; | 1642 const LayoutBox* firstChild = nullptr; |
| 1608 bool isBaselineAligned = false; | 1643 bool isBaselineAligned = false; |
| 1609 // Finding the first grid item in grid order. | 1644 // Finding the first grid item in grid order. |
| 1610 for (size_t column = 0; | 1645 for (size_t column = 0; |
| 1611 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { | 1646 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { |
| 1612 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { | 1647 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { |
| 1613 const LayoutBox* child = m_grid.cell(0, column)[index]; | 1648 const LayoutBox* child = m_grid.cell(0, column)[index]; |
| 1614 DCHECK(!child->isOutOfFlowPositioned()); | 1649 DCHECK(!child->isOutOfFlowPositioned()); |
| 1615 // If an item participates in baseline alignmen, we select such item. | 1650 // If an item participates in baseline alignment, we select such item. |
| 1616 if (isInlineBaselineAlignedChild(child)) { | 1651 if (isBaselineAlignmentForChild(*child)) { |
| 1617 // TODO (lajava): self-baseline and content-baseline alignment | 1652 // TODO (lajava): self-baseline and content-baseline alignment |
| 1618 // still not implemented. | 1653 // still not implemented. |
| 1619 baselineChild = child; | 1654 baselineChild = child; |
| 1620 isBaselineAligned = true; | 1655 isBaselineAligned = true; |
| 1621 break; | 1656 break; |
| 1622 } | 1657 } |
| 1623 if (!baselineChild) { | 1658 if (!baselineChild) { |
| 1624 // Use dom order for items in the same cell. | 1659 // Use dom order for items in the same cell. |
| 1625 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < | 1660 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < |
| 1626 m_grid.gridItemPaintOrder(*firstChild))) | 1661 m_grid.gridItemPaintOrder(*firstChild))) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1656 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { | 1691 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { |
| 1657 int baseline = firstLineBoxBaseline(); | 1692 int baseline = firstLineBoxBaseline(); |
| 1658 if (baseline != -1) | 1693 if (baseline != -1) |
| 1659 return baseline; | 1694 return baseline; |
| 1660 | 1695 |
| 1661 int marginHeight = | 1696 int marginHeight = |
| 1662 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); | 1697 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); |
| 1663 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; | 1698 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; |
| 1664 } | 1699 } |
| 1665 | 1700 |
| 1701 bool LayoutGrid::isHorizontalGridAxis(GridAxis axis) const { | |
| 1702 return axis == GridRowAxis ? isHorizontalWritingMode() | |
| 1703 : !isHorizontalWritingMode(); | |
| 1704 } | |
| 1705 | |
| 1706 bool LayoutGrid::isParallelToBlockAxisForChild(const LayoutBox& child, | |
| 1707 GridAxis axis) const { | |
| 1708 return axis == GridColumnAxis ? !isOrthogonalChild(child) | |
| 1709 : isOrthogonalChild(child); | |
| 1710 } | |
| 1711 | |
| 1712 bool LayoutGrid::isDescentBaselineForChild(const LayoutBox& child, | |
| 1713 GridAxis baselineAxis) const { | |
| 1714 return isHorizontalGridAxis(baselineAxis) && | |
| 1715 !styleRef().isFlippedBlocksWritingMode(); | |
| 1716 } | |
| 1717 | |
| 1718 bool LayoutGrid::isBaselineAlignmentForChild(const LayoutBox& child, | |
| 1719 GridAxis baselineAxis) const { | |
| 1720 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 1721 ItemPosition align = isColumnAxisBaseline | |
| 1722 ? alignSelfForChild(child).position() | |
| 1723 : justifySelfForChild(child).position(); | |
| 1724 bool hasAutoMargins = isColumnAxisBaseline ? hasAutoMarginsInColumnAxis(child) | |
| 1725 : hasAutoMarginsInRowAxis(child); | |
| 1726 return isBaselinePosition(align) && !hasAutoMargins; | |
| 1727 } | |
|
svillar
2017/03/24 10:52:05
I wonder if these four utility methods could be pa
jfernandez
2017/03/24 14:15:18
Yeah, I wondered the same and actually tried to mo
| |
| 1728 | |
| 1729 const BaselineGroup& LayoutGrid::getBaselineGroupForChild( | |
| 1730 const LayoutBox& child, | |
| 1731 GridAxis baselineAxis) const { | |
| 1732 DCHECK(isBaselineAlignmentForChild(child, baselineAxis)); | |
| 1733 auto& grid = m_trackSizingAlgorithm.grid(); | |
| 1734 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 1735 bool isRowAxisContext = isColumnAxisBaseline; | |
| 1736 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) | |
| 1737 : grid.gridItemSpan(child, ForColumns); | |
| 1738 auto& contextsMap = | |
| 1739 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; | |
| 1740 auto* context = contextsMap.at(span.startLine()); | |
| 1741 DCHECK(context); | |
| 1742 ItemPosition align = isColumnAxisBaseline | |
| 1743 ? alignSelfForChild(child).position() | |
| 1744 : justifySelfForChild(child).position(); | |
| 1745 return context->getSharedGroup(child, align); | |
| 1746 } | |
| 1747 | |
| 1748 LayoutUnit LayoutGrid::marginOverForChild(const LayoutBox& child, | |
| 1749 GridAxis axis) const { | |
| 1750 return isHorizontalGridAxis(axis) ? child.marginRight() : child.marginTop(); | |
| 1751 } | |
| 1752 | |
| 1753 LayoutUnit LayoutGrid::logicalAscentForChild(const LayoutBox& child, | |
| 1754 GridAxis baselineAxis) const { | |
| 1755 LayoutUnit ascent = ascentForChild(child, baselineAxis); | |
| 1756 return isDescentBaselineForChild(child, baselineAxis) | |
| 1757 ? descentForChild(child, ascent, baselineAxis) | |
| 1758 : ascent; | |
| 1759 } | |
| 1760 | |
| 1761 LayoutUnit LayoutGrid::ascentForChild(const LayoutBox& child, | |
| 1762 GridAxis baselineAxis) const { | |
| 1763 int baseline = isParallelToBlockAxisForChild(child, baselineAxis) | |
| 1764 ? child.firstLineBoxBaseline() | |
| 1765 : -1; | |
| 1766 // We take border-box's bottom if no valid baseline. | |
| 1767 if (baseline == -1) { | |
| 1768 baseline = isHorizontalGridAxis(baselineAxis) | |
| 1769 ? child.size().width().toInt() | |
| 1770 : child.size().height().toInt(); | |
| 1771 } | |
| 1772 return LayoutUnit(baseline) + marginOverForChild(child, baselineAxis); | |
| 1773 } | |
| 1774 | |
| 1775 LayoutUnit LayoutGrid::descentForChild(const LayoutBox& child, | |
| 1776 LayoutUnit ascent, | |
| 1777 GridAxis baselineAxis) const { | |
| 1778 if (isParallelToBlockAxisForChild(child, baselineAxis)) | |
| 1779 return child.marginLogicalHeight() + child.logicalHeight() - ascent; | |
| 1780 return child.marginLogicalWidth() + child.logicalWidth() - ascent; | |
| 1781 } | |
| 1782 | |
| 1783 bool LayoutGrid::isBaselineContextComputed(GridAxis baselineAxis) const { | |
| 1784 return baselineAxis == GridColumnAxis ? !m_rowAxisAlignmentContext.isEmpty() | |
| 1785 : !m_colAxisAlignmentContext.isEmpty(); | |
| 1786 } | |
| 1787 | |
|
svillar
2017/03/24 10:52:05
Same question here for the above 5 methods. Do you
jfernandez
2017/03/24 14:15:18
Already explained before, but I'd definitively lik
| |
| 1788 bool LayoutGrid::baselineMayAffectIntrinsicWidth() const { | |
| 1789 if (!styleRef().logicalWidth().isIntrinsicOrAuto()) | |
| 1790 return false; | |
| 1791 for (const auto& context : m_colAxisAlignmentContext) { | |
| 1792 for (const auto& group : context.value->sharedGroups()) { | |
| 1793 if (group.size() > 1) | |
| 1794 return true; | |
| 1795 } | |
| 1796 } | |
| 1797 return false; | |
| 1798 } | |
| 1799 | |
| 1800 bool LayoutGrid::baselineMayAffectIntrinsicHeight() const { | |
| 1801 if (!styleRef().logicalHeight().isIntrinsicOrAuto()) | |
| 1802 return false; | |
| 1803 for (const auto& context : m_rowAxisAlignmentContext) { | |
| 1804 for (const auto& group : context.value->sharedGroups()) { | |
| 1805 if (group.size() > 1) | |
| 1806 return true; | |
| 1807 } | |
| 1808 } | |
| 1809 return false; | |
| 1810 } | |
| 1811 | |
| 1812 void LayoutGrid::computeBaselineAlignmentContext() { | |
| 1813 for (auto* child = firstInFlowChildBox(); child; | |
| 1814 child = child->nextInFlowSiblingBox()) { | |
| 1815 updateBaselineAlignmentContextIfNeeded(*child, GridRowAxis); | |
| 1816 updateBaselineAlignmentContextIfNeeded(*child, GridColumnAxis); | |
| 1817 } | |
| 1818 } | |
| 1819 | |
| 1820 void LayoutGrid::updateBaselineAlignmentContextIfNeeded(LayoutBox& child, | |
| 1821 GridAxis baselineAxis) { | |
| 1822 // DCHECK(m_trackSizingAlgorithm.isTrackSizingOperation()); | |
|
svillar
2017/03/24 10:52:05
Remove this check if it does not apply.
jfernandez
2017/03/24 14:15:18
Well, I'd like to have this check. However, unfort
| |
| 1823 if (!isBaselineAlignmentForChild(child, baselineAxis)) | |
| 1824 return; | |
| 1825 | |
| 1826 child.layoutIfNeeded(); | |
| 1827 | |
| 1828 // Determine Ascent and Descent values of this child with respect to | |
| 1829 // its grid container. | |
| 1830 LayoutUnit ascent = ascentForChild(child, baselineAxis); | |
| 1831 LayoutUnit descent = descentForChild(child, ascent, baselineAxis); | |
| 1832 if (isDescentBaselineForChild(child, baselineAxis)) | |
| 1833 std::swap(ascent, descent); | |
| 1834 | |
| 1835 // Looking up for a shared alignment context perpendicular to the | |
| 1836 // baseline axis. | |
| 1837 auto& grid = m_trackSizingAlgorithm.grid(); | |
| 1838 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 1839 bool isRowAxisContext = isColumnAxisBaseline; | |
| 1840 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) | |
| 1841 : grid.gridItemSpan(child, ForColumns); | |
| 1842 auto& contextsMap = | |
| 1843 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; | |
| 1844 auto addResult = contextsMap.insert(span.startLine(), nullptr); | |
| 1845 | |
| 1846 // Looking for a compatible baseline-sharing group. | |
| 1847 ItemPosition align = isColumnAxisBaseline | |
| 1848 ? alignSelfForChild(child).position() | |
| 1849 : justifySelfForChild(child).position(); | |
| 1850 if (addResult.isNewEntry) { | |
| 1851 addResult.storedValue->value = | |
| 1852 WTF::makeUnique<BaselineContext>(child, align, ascent, descent); | |
| 1853 } else { | |
| 1854 auto* context = addResult.storedValue->value.get(); | |
| 1855 context->updateSharedGroup(child, align, ascent, descent); | |
| 1856 } | |
| 1857 } | |
| 1858 | |
| 1859 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild( | |
| 1860 const LayoutBox& child) const { | |
| 1861 if (!isBaselineAlignmentForChild(child, GridColumnAxis)) | |
| 1862 return LayoutUnit(); | |
| 1863 auto& group = getBaselineGroupForChild(child, GridColumnAxis); | |
| 1864 if (group.size() > 1) | |
| 1865 return group.maxAscent() - logicalAscentForChild(child, GridColumnAxis); | |
| 1866 return LayoutUnit(); | |
| 1867 } | |
| 1868 | |
| 1869 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild( | |
| 1870 const LayoutBox& child) const { | |
| 1871 if (!isBaselineAlignmentForChild(child, GridRowAxis)) | |
| 1872 return LayoutUnit(); | |
| 1873 auto& group = getBaselineGroupForChild(child, GridRowAxis); | |
| 1874 if (group.size() > 1) | |
| 1875 return group.maxAscent() - logicalAscentForChild(child, GridRowAxis); | |
| 1876 return LayoutUnit(); | |
| 1877 } | |
| 1878 | |
| 1666 GridAxisPosition LayoutGrid::columnAxisPositionForChild( | 1879 GridAxisPosition LayoutGrid::columnAxisPositionForChild( |
| 1667 const LayoutBox& child) const { | 1880 const LayoutBox& child) const { |
| 1668 bool hasSameWritingMode = | 1881 bool hasSameWritingMode = |
| 1669 child.styleRef().getWritingMode() == styleRef().getWritingMode(); | 1882 child.styleRef().getWritingMode() == styleRef().getWritingMode(); |
| 1670 bool childIsLTR = child.styleRef().isLeftToRightDirection(); | 1883 bool childIsLTR = child.styleRef().isLeftToRightDirection(); |
| 1671 | 1884 |
| 1672 switch (alignSelfForChild(child).position()) { | 1885 switch (alignSelfForChild(child).position()) { |
| 1673 case ItemPositionSelfStart: | 1886 case ItemPositionSelfStart: |
| 1674 // TODO (lajava): Should we implement this logic in a generic utility | 1887 // TODO (lajava): Should we implement this logic in a generic utility |
| 1675 // function? | 1888 // function? |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1725 // Only used in flex layout, otherwise equivalent to 'end'. | 1938 // Only used in flex layout, otherwise equivalent to 'end'. |
| 1726 case ItemPositionFlexEnd: | 1939 case ItemPositionFlexEnd: |
| 1727 // Aligns the alignment subject to be flush with the alignment container's | 1940 // Aligns the alignment subject to be flush with the alignment container's |
| 1728 // 'end' edge (block-end) in the column axis. | 1941 // 'end' edge (block-end) in the column axis. |
| 1729 case ItemPositionEnd: | 1942 case ItemPositionEnd: |
| 1730 return GridAxisEnd; | 1943 return GridAxisEnd; |
| 1731 case ItemPositionStretch: | 1944 case ItemPositionStretch: |
| 1732 return GridAxisStart; | 1945 return GridAxisStart; |
| 1733 case ItemPositionBaseline: | 1946 case ItemPositionBaseline: |
| 1734 case ItemPositionLastBaseline: | 1947 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; | 1948 return GridAxisStart; |
| 1738 case ItemPositionAuto: | 1949 case ItemPositionAuto: |
| 1739 case ItemPositionNormal: | 1950 case ItemPositionNormal: |
| 1740 break; | 1951 break; |
| 1741 } | 1952 } |
| 1742 | 1953 |
| 1743 ASSERT_NOT_REACHED(); | 1954 ASSERT_NOT_REACHED(); |
| 1744 return GridAxisStart; | 1955 return GridAxisStart; |
| 1745 } | 1956 } |
| 1746 | 1957 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1804 // Only used in flex layout, otherwise equivalent to 'end'. | 2015 // Only used in flex layout, otherwise equivalent to 'end'. |
| 1805 case ItemPositionFlexEnd: | 2016 case ItemPositionFlexEnd: |
| 1806 // Aligns the alignment subject to be flush with the alignment container's | 2017 // Aligns the alignment subject to be flush with the alignment container's |
| 1807 // 'end' edge (inline-end) in the row axis. | 2018 // 'end' edge (inline-end) in the row axis. |
| 1808 case ItemPositionEnd: | 2019 case ItemPositionEnd: |
| 1809 return GridAxisEnd; | 2020 return GridAxisEnd; |
| 1810 case ItemPositionStretch: | 2021 case ItemPositionStretch: |
| 1811 return GridAxisStart; | 2022 return GridAxisStart; |
| 1812 case ItemPositionBaseline: | 2023 case ItemPositionBaseline: |
| 1813 case ItemPositionLastBaseline: | 2024 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; | 2025 return GridAxisStart; |
| 1817 case ItemPositionAuto: | 2026 case ItemPositionAuto: |
| 1818 case ItemPositionNormal: | 2027 case ItemPositionNormal: |
| 1819 break; | 2028 break; |
| 1820 } | 2029 } |
| 1821 | 2030 |
| 1822 ASSERT_NOT_REACHED(); | 2031 ASSERT_NOT_REACHED(); |
| 1823 return GridAxisStart; | 2032 return GridAxisStart; |
| 1824 } | 2033 } |
| 1825 | 2034 |
| 1826 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const { | 2035 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const { |
| 1827 const GridSpan& rowsSpan = | 2036 const GridSpan& rowsSpan = |
| 1828 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows); | 2037 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows); |
| 1829 size_t childStartLine = rowsSpan.startLine(); | 2038 size_t childStartLine = rowsSpan.startLine(); |
| 1830 LayoutUnit startOfRow = m_rowPositions[childStartLine]; | 2039 LayoutUnit startOfRow = m_rowPositions[childStartLine]; |
| 1831 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 2040 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
| 1832 if (hasAutoMarginsInColumnAxis(child)) | 2041 if (hasAutoMarginsInColumnAxis(child)) |
| 1833 return startPosition; | 2042 return startPosition; |
| 1834 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 2043 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
| 1835 switch (axisPosition) { | 2044 switch (axisPosition) { |
| 1836 case GridAxisStart: | 2045 case GridAxisStart: |
| 1837 return startPosition; | 2046 return startPosition + columnAxisBaselineOffsetForChild(child); |
| 1838 case GridAxisEnd: | 2047 case GridAxisEnd: |
| 1839 case GridAxisCenter: { | 2048 case GridAxisCenter: { |
| 1840 size_t childEndLine = rowsSpan.endLine(); | 2049 size_t childEndLine = rowsSpan.endLine(); |
| 1841 LayoutUnit endOfRow = m_rowPositions[childEndLine]; | 2050 LayoutUnit endOfRow = m_rowPositions[childEndLine]; |
| 1842 // m_rowPositions include distribution offset (because of content | 2051 // m_rowPositions include distribution offset (because of content |
| 1843 // alignment) and gutters so we need to subtract them to get the actual | 2052 // 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 | 2053 // 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). | 2054 // last track as there are no more m_columnPositions after it). |
| 1846 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing); | 2055 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing); |
| 1847 if (childEndLine < m_rowPositions.size() - 1) { | 2056 if (childEndLine < m_rowPositions.size() - 1) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1869 const GridSpan& columnsSpan = | 2078 const GridSpan& columnsSpan = |
| 1870 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns); | 2079 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns); |
| 1871 size_t childStartLine = columnsSpan.startLine(); | 2080 size_t childStartLine = columnsSpan.startLine(); |
| 1872 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; | 2081 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; |
| 1873 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 2082 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
| 1874 if (hasAutoMarginsInRowAxis(child)) | 2083 if (hasAutoMarginsInRowAxis(child)) |
| 1875 return startPosition; | 2084 return startPosition; |
| 1876 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 2085 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
| 1877 switch (axisPosition) { | 2086 switch (axisPosition) { |
| 1878 case GridAxisStart: | 2087 case GridAxisStart: |
| 1879 return startPosition; | 2088 return startPosition + rowAxisBaselineOffsetForChild(child); |
| 1880 case GridAxisEnd: | 2089 case GridAxisEnd: |
| 1881 case GridAxisCenter: { | 2090 case GridAxisCenter: { |
| 1882 size_t childEndLine = columnsSpan.endLine(); | 2091 size_t childEndLine = columnsSpan.endLine(); |
| 1883 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; | 2092 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; |
| 1884 // m_columnPositions include distribution offset (because of content | 2093 // m_columnPositions include distribution offset (because of content |
| 1885 // alignment) and gutters so we need to subtract them to get the actual | 2094 // 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 | 2095 // 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). | 2096 // last track as there are no more m_columnPositions after it). |
| 1888 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing); | 2097 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing); |
| 1889 if (childEndLine < m_columnPositions.size() - 1) { | 2098 if (childEndLine < m_columnPositions.size() - 1) { |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2103 if (direction == ForRows) | 2312 if (direction == ForRows) |
| 2104 return grid.numTracks(ForRows); | 2313 return grid.numTracks(ForRows); |
| 2105 | 2314 |
| 2106 return grid.numTracks(ForRows) | 2315 return grid.numTracks(ForRows) |
| 2107 ? grid.numTracks(ForColumns) | 2316 ? grid.numTracks(ForColumns) |
| 2108 : GridPositionsResolver::explicitGridColumnCount( | 2317 : GridPositionsResolver::explicitGridColumnCount( |
| 2109 styleRef(), grid.autoRepeatTracks(ForColumns)); | 2318 styleRef(), grid.autoRepeatTracks(ForColumns)); |
| 2110 } | 2319 } |
| 2111 | 2320 |
| 2112 } // namespace blink | 2321 } // namespace blink |
| OLD | NEW |