Ignore:
Timestamp:
Sep 6, 2013, 1:04:33 AM (12 years ago)
Author:
[email protected]
Message:

[CSS Grid Layout] Resolve named grid lines
https://bugs.webkit.org/show_bug.cgi?id=119632

Reviewed by Andreas Kling.

From Blink r152659, r153794 by <[email protected]>

Source/WebCore:

Test: fast/css-grid-layout/grid-item-named-grid-line-resolution.html

This change adds the code which translates from a raw named grid
line (stored in RenderStyle) to its actual grid position. This
even includes named grid resolution for grid lines with the 'span'
keyword.

  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::explicitGridSizeForSide):
(WebCore::adjustGridPositionForRowEndColumnEndSide):
(WebCore::adjustGridPositionForSide):
(WebCore::RenderGrid::resolveNamedGridLinePositionFromStyle):
(WebCore::RenderGrid::resolveGridPositionFromStyle):
(WebCore::RenderGrid::resolveGridPositionAgainstOppositePosition):
(WebCore::RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition):
(WebCore::RenderGrid::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition):
(WebCore::RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition):

  • rendering/RenderGrid.h:

LayoutTests:

Added a new test to check named grid lines resolution. This also
provides some more new test cases with named grid lines and
negative positions.

  • fast/css-grid-layout/grid-item-named-grid-line-resolution-expected.txt: Added.
  • fast/css-grid-layout/grid-item-named-grid-line-resolution.html: Added.
  • fast/css-grid-layout/grid-item-negative-position-resolution-expected.txt:
  • fast/css-grid-layout/grid-item-negative-position-resolution.html:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r154996 r155181  
    338338}
    339339
     340size_t RenderGrid::explicitGridSizeForSide(GridPositionSide side) const
     341{
     342    return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount() : explicitGridRowCount();
     343}
     344
    340345size_t RenderGrid::maximumIndexInDirection(TrackSizingDirection direction) const
    341346{
     
    754759}
    755760
     761inline static size_t adjustGridPositionForRowEndColumnEndSide(size_t resolvedPosition)
     762{
     763    return resolvedPosition ? resolvedPosition - 1 : 0;
     764}
     765
    756766static size_t adjustGridPositionForSide(size_t resolvedPosition, RenderGrid::GridPositionSide side)
    757767{
    758768    // An item finishing on the N-th line belongs to the N-1-th cell.
    759769    if (side == RenderGrid::ColumnEndSide || side == RenderGrid::RowEndSide)
    760         return resolvedPosition ? resolvedPosition - 1 : 0;
     770        return adjustGridPositionForRowEndColumnEndSide(resolvedPosition);
    761771
    762772    return resolvedPosition;
     773}
     774
     775size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& position, GridPositionSide side) const
     776{
     777    ASSERT(!position.namedGridLine().isNull());
     778
     779    const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
     780    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
     781    if (it == gridLinesNames.end()) {
     782        if (position.isPositive())
     783            return 0;
     784        const size_t lastLine = explicitGridSizeForSide(side);
     785        return adjustGridPositionForSide(lastLine, side);
     786    }
     787
     788    size_t namedGridLineIndex;
     789    if (position.isPositive())
     790        namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
     791    else
     792        namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
     793    return adjustGridPositionForSide(it->value[namedGridLineIndex], side);
    763794}
    764795
     
    769800    case ExplicitPosition: {
    770801        ASSERT(position.integerPosition());
     802
     803        if (!position.namedGridLine().isNull())
     804            return resolveNamedGridLinePositionFromStyle(position, side);
     805
     806        // Handle <integer> explicit position.
    771807        if (position.isPositive())
    772808            return adjustGridPositionForSide(position.integerPosition() - 1, side);
    773809
    774810        size_t resolvedPosition = abs(position.integerPosition()) - 1;
    775         const size_t endOfTrack = (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount() : explicitGridRowCount();
     811        const size_t endOfTrack = explicitGridSizeForSide(side);
    776812
    777813        // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
     
    802838    ASSERT(position.spanPosition() > 0);
    803839
     840    if (!position.namedGridLine().isNull()) {
     841        // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
     842        return resolveNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, side);
     843    }
     844
    804845    // 'span 1' is contained inside a single grid track regardless of the direction.
    805846    // That's why the CSS span value is one more than the offset we apply.
     
    811852
    812853    return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
     854}
     855
     856PassOwnPtr<RenderGrid::GridSpan> RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
     857{
     858    ASSERT(position.isSpan());
     859    ASSERT(!position.namedGridLine().isNull());
     860    // Negative positions are not allowed per the specification and should have been handled during parsing.
     861    ASSERT(position.spanPosition() > 0);
     862
     863    const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
     864    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
     865
     866    // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
     867    // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
     868    if (it == gridLinesNames.end())
     869        return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
     870
     871    if (side == RowStartSide || side == ColumnStartSide)
     872        return resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
     873
     874    return resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
     875}
     876
     877PassOwnPtr<RenderGrid::GridSpan> RenderGrid::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
     878{
     879    // The grid line inequality needs to be strict (which doesn't match the after / end case) because |resolvedOppositePosition|
     880    // is already converted to an index in our grid representation (ie one was removed from the grid line to account for the side).
     881    // FIXME: This could be a binary search as |gridLines| is ordered.
     882    int firstLineBeforeOppositePositionIndex = gridLines.size() - 1;
     883    for (; firstLineBeforeOppositePositionIndex >= 0 && gridLines[firstLineBeforeOppositePositionIndex] > resolvedOppositePosition; --firstLineBeforeOppositePositionIndex) { }
     884
     885    size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition() + 1);
     886    size_t resolvedGridLinePosition = gridLines[gridLineIndex];
     887    if (resolvedGridLinePosition > resolvedOppositePosition)
     888        resolvedGridLinePosition = resolvedOppositePosition;
     889    return GridSpan::create(resolvedGridLinePosition, resolvedOppositePosition);
     890}
     891
     892PassOwnPtr<RenderGrid::GridSpan> RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
     893{
     894    // FIXME: This could be a binary search as |gridLines| is ordered.
     895    size_t firstLineAfterOppositePositionIndex = 0;
     896    for (; firstLineAfterOppositePositionIndex < gridLines.size() && gridLines[firstLineAfterOppositePositionIndex] <= resolvedOppositePosition; ++firstLineAfterOppositePositionIndex) { }
     897
     898    size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
     899    size_t resolvedGridLinePosition = adjustGridPositionForRowEndColumnEndSide(gridLines[gridLineIndex]);
     900    if (resolvedGridLinePosition < resolvedOppositePosition)
     901        resolvedGridLinePosition = resolvedOppositePosition;
     902    return GridSpan::create(resolvedOppositePosition, resolvedGridLinePosition);
    813903}
    814904
Note: See TracChangeset for help on using the changeset viewer.