Changeset 182704 in webkit


Ignore:
Timestamp:
Apr 13, 2015, 3:49:43 AM (10 years ago)
Author:
svillar@igalia.com
Message:

[CSS Grid Layout] Support marking/unmarking tracks as infinitely growable
https://bugs.webkit.org/show_bug.cgi?id=141431

Reviewed by Darin Adler.

Source/WebCore:

As explained here
http://lists.w3.org/Archives/Public/www-style/2014Mar/0512.html we
sometimes need to consider that some tracks are infinitely
growable even when they are really not, in order to produce more
"natural" results.

For example the following case:

grid-template-columns: auto auto;
item 1 in column 1 with min-content = max-content = 10px;
item 2 in columns 1-2 with min-content = 30, max-content = 100px;

will produce (45px, 55px) without this patch. But considering the
second column as infinitely growable the result is (10px, 90px), a
more "natural" result because column 1 just needs to be 10px to
accommodate item 1. From now on we can flag GridTracks so that
they can infinitely grow even when the growth limit is finite.

Apart from that distributeSpaceToTracks() is now unconditionally
called even though the extra space is 0. That's because it
computes the plannedSize value.

Test: fast/css-grid-layout/mark-as-infinitely-growable.html

  • rendering/RenderGrid.cpp:

(WebCore::GridTrack::infiniteGrowthPotential):
(WebCore::GridTrack::infinitelyGrowable):
(WebCore::GridTrack::setInfinitelyGrowable):
(WebCore::RenderGrid::computeUsedBreadthOfGridTracks):
(WebCore::RenderGrid::trackSizeForTrackSizeComputationPhase): Updated with new phase.
(WebCore::RenderGrid::shouldProcessTrackForTrackSizeComputationPhase): Ditto.
(WebCore::RenderGrid::trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase): Ditto.
(WebCore::RenderGrid::updateTrackSizeForTrackSizeComputationPhase): Ditto.
(WebCore::RenderGrid::currentItemSizeForTrackSizeComputationPhase): Ditto.
(WebCore::RenderGrid::markAsInfinitelyGrowableForTrackSizeComputationPhase):
New helper method which does the mark/unmark just for growth limits.
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
(WebCore::sortByGridTrackGrowthPotential): Use
infiniteGrowthPotential() for sorting.
(WebCore::RenderGrid::distributeSpaceToTracks):

  • rendering/RenderGrid.h:

LayoutTests:

New test that to check that tracks whose growth limit changes from
infinite to finite when evaluating "intrinsic maximums" are marked
as infinitely growable for the "max-content maximums" step.

  • fast/css-grid-layout/mark-as-infinitely-growable-expected.txt: Added.
  • fast/css-grid-layout/mark-as-infinitely-growable.html: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r182700 r182704  
     12015-04-10  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        [CSS Grid Layout] Support marking/unmarking tracks as infinitely growable
     4        https://bugs.webkit.org/show_bug.cgi?id=141431
     5
     6        Reviewed by Darin Adler.
     7
     8        New test that to check that tracks whose growth limit changes from
     9        infinite to finite when evaluating "intrinsic maximums" are marked
     10        as infinitely growable for the "max-content maximums" step.
     11
     12        * fast/css-grid-layout/mark-as-infinitely-growable-expected.txt: Added.
     13        * fast/css-grid-layout/mark-as-infinitely-growable.html: Added.
     14
    1152015-04-13  Csaba Osztrogonác  <ossy@webkit.org>
    216
  • trunk/Source/WebCore/ChangeLog

    r182677 r182704  
     12015-04-10  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        [CSS Grid Layout] Support marking/unmarking tracks as infinitely growable
     4        https://bugs.webkit.org/show_bug.cgi?id=141431
     5
     6        Reviewed by Darin Adler.
     7
     8        As explained here
     9        http://lists.w3.org/Archives/Public/www-style/2014Mar/0512.html we
     10        sometimes need to consider that some tracks are infinitely
     11        growable even when they are really not, in order to produce more
     12        "natural" results.
     13
     14        For example the following case:
     15          grid-template-columns: auto auto;
     16          item 1 in column 1 with min-content = max-content = 10px;
     17          item 2 in columns 1-2 with min-content = 30, max-content = 100px;
     18
     19        will produce (45px, 55px) without this patch. But considering the
     20        second column as infinitely growable the result is (10px, 90px), a
     21        more "natural" result because column 1 just needs to be 10px to
     22        accommodate item 1. From now on we can flag GridTracks so that
     23        they can infinitely grow even when the growth limit is finite.
     24
     25        Apart from that distributeSpaceToTracks() is now unconditionally
     26        called even though the extra space is 0. That's because it
     27        computes the plannedSize value.
     28
     29        Test: fast/css-grid-layout/mark-as-infinitely-growable.html
     30
     31        * rendering/RenderGrid.cpp:
     32        (WebCore::GridTrack::infiniteGrowthPotential):
     33        (WebCore::GridTrack::infinitelyGrowable):
     34        (WebCore::GridTrack::setInfinitelyGrowable):
     35        (WebCore::RenderGrid::computeUsedBreadthOfGridTracks):
     36        (WebCore::RenderGrid::trackSizeForTrackSizeComputationPhase): Updated with new phase.
     37        (WebCore::RenderGrid::shouldProcessTrackForTrackSizeComputationPhase): Ditto.
     38        (WebCore::RenderGrid::trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase): Ditto.
     39        (WebCore::RenderGrid::updateTrackSizeForTrackSizeComputationPhase): Ditto.
     40        (WebCore::RenderGrid::currentItemSizeForTrackSizeComputationPhase): Ditto.
     41        (WebCore::RenderGrid::markAsInfinitelyGrowableForTrackSizeComputationPhase):
     42        New helper method which does the mark/unmark just for growth limits.
     43        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
     44        (WebCore::sortByGridTrackGrowthPotential): Use
     45        infiniteGrowthPotential() for sorting.
     46        (WebCore::RenderGrid::distributeSpaceToTracks):
     47        * rendering/RenderGrid.h:
     48
    1492015-04-12  Benjamin Poulain  <benjamin@webkit.org>
    250
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r182628 r182704  
    7474    }
    7575
     76    bool infiniteGrowthPotential() const
     77    {
     78        return growthLimitIsInfinite() || m_infinitelyGrowable;
     79    }
     80
    7681    const LayoutUnit& growthLimitIfNotInfinite() const
    7782    {
     
    8893
    8994    LayoutUnit& tempSize() { return m_tempSize; }
     95
     96    bool infinitelyGrowable() const { return m_infinitelyGrowable; }
     97
     98    void setInfinitelyGrowable(bool infinitelyGrowable)
     99    {
     100        m_infinitelyGrowable = infinitelyGrowable;
     101    }
    90102
    91103private:
     
    102114    LayoutUnit m_plannedSize { 0 };
    103115    LayoutUnit m_tempSize { 0 };
     116    bool m_infinitelyGrowable { false };
    104117};
    105118
     
    343356        track.setBaseSize(computeUsedBreadthOfMinLength(direction, minTrackBreadth));
    344357        track.setGrowthLimit(computeUsedBreadthOfMaxLength(direction, maxTrackBreadth, track.baseSize()));
     358        track.setInfinitelyGrowable(false);
    345359
    346360        if (trackSize.isContentSized())
     
    373387        }
    374388
    375         distributeSpaceToTracks<DistributeSpaceToBaseSizes>(tracksForDistribution, nullptr, availableLogicalSpace);
     389        distributeSpaceToTracks<MaximizeTracks>(tracksForDistribution, nullptr, availableLogicalSpace);
    376390
    377391        for (auto* track : tracksForDistribution)
     
    678692    case ResolveIntrinsicMinimums:
    679693    case ResolveMaxContentMinimums:
     694    case MaximizeTracks:
    680695        return track.baseSize();
    681         break;
    682696    case ResolveIntrinsicMaximums:
    683697    case ResolveMaxContentMaximums:
    684698        return restriction == AllowInfinity ? track.growthLimit() : track.growthLimitIfNotInfinite();
    685         break;
    686699    }
    687700
     
    701714    case ResolveMaxContentMaximums:
    702715        return trackSize.hasMaxContentMaxTrackBreadth();
     716    case MaximizeTracks:
     717        ASSERT_NOT_REACHED();
     718        return false;
    703719    }
    704720
     
    717733    case ResolveMaxContentMaximums:
    718734        return true;
     735    case MaximizeTracks:
     736        ASSERT_NOT_REACHED();
     737        return false;
    719738    }
    720739
    721740    ASSERT_NOT_REACHED();
    722741    return false;
     742}
     743
     744void RenderGrid::markAsInfinitelyGrowableForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track)
     745{
     746    switch (phase) {
     747    case ResolveIntrinsicMinimums:
     748    case ResolveMaxContentMinimums:
     749        return;
     750    case ResolveIntrinsicMaximums:
     751        if (trackSizeForTrackSizeComputationPhase(phase, track, AllowInfinity) == infinity  && track.plannedSize() != infinity)
     752            track.setInfinitelyGrowable(true);
     753        return;
     754    case ResolveMaxContentMaximums:
     755        if (track.infinitelyGrowable())
     756            track.setInfinitelyGrowable(false);
     757        return;
     758    case MaximizeTracks:
     759        ASSERT_NOT_REACHED();
     760        return;
     761    }
     762
     763    ASSERT_NOT_REACHED();
    723764}
    724765
     
    734775        track.setGrowthLimit(track.plannedSize());
    735776        return;
     777    case MaximizeTracks:
     778        ASSERT_NOT_REACHED();
     779        return;
    736780    }
    737781
     
    748792    case ResolveMaxContentMaximums:
    749793        return maxContentForChild(gridItem, direction, columnTracks);
     794    case MaximizeTracks:
     795        ASSERT_NOT_REACHED();
     796        return 0;
    750797    }
    751798
     
    789836
    790837        LayoutUnit extraSpace = currentItemSizeForTrackSizeComputationPhase(phase, gridItemWithSpan.gridItem(), direction, sizingData.columnTracks) - spanningTracksSize;
    791         // Specs mandate to floor extraSpace to 0. Instead we directly avoid the function call in those cases as it will be
    792         // a noop in terms of track sizing.
    793         if (extraSpace > 0) {
    794             auto* tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGrowthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBeyondGrowthLimitsTracks;
    795             switch (phase) {
    796             case ResolveIntrinsicMinimums:
    797             case ResolveMaxContentMinimums:
    798                 distributeSpaceToTracks<DistributeSpaceToBaseSizes>(sizingData.filteredTracks, tracksToGrowBeyondGrowthLimits, extraSpace);
    799                 break;
    800             case ResolveIntrinsicMaximums:
    801             case ResolveMaxContentMaximums:
    802                 distributeSpaceToTracks<DistributeSpaceToGrowthLimits>(sizingData.filteredTracks, tracksToGrowBeyondGrowthLimits, extraSpace);
    803                 break;
    804             }
    805         }
     838        extraSpace = std::max<LayoutUnit>(extraSpace, 0);
     839        auto& tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGrowthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBeyondGrowthLimitsTracks;
     840        distributeSpaceToTracks<phase>(sizingData.filteredTracks, &tracksToGrowBeyondGrowthLimits, extraSpace);
    806841    }
    807842
    808843    for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
    809844        GridTrack& track = tracks[trackIndex];
     845        markAsInfinitelyGrowableForTrackSizeComputationPhase(phase, track);
    810846        updateTrackSizeForTrackSizeComputationPhase(phase, track);
    811847    }
     
    816852    // This check ensures that we respect the irreflexivity property of the strict weak ordering required by std::sort
    817853    // (forall x: NOT x < x).
    818     if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite())
     854    if (track1->infiniteGrowthPotential() && track2->infiniteGrowthPotential())
    819855        return false;
    820856
    821     if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite())
    822         return track2->growthLimitIsInfinite();
     857    if (track1->infiniteGrowthPotential() || track2->infiniteGrowthPotential())
     858        return track2->infiniteGrowthPotential();
    823859
    824860    return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize());
    825861}
    826862
    827 template <RenderGrid::DistributeSpacePhase phase>
     863template <RenderGrid::TrackSizeComputationPhase phase>
    828864void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace)
    829865{
    830     ASSERT(availableLogicalSpace > 0);
    831     std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
    832 
    833     unsigned tracksSize = tracks.size();
    834 
    835     for (unsigned i = 0; i < tracksSize; ++i) {
    836         GridTrack& track = *tracks[i];
    837         LayoutUnit trackBreadth;
    838         switch (phase) {
    839         case DistributeSpaceToBaseSizes:
    840             trackBreadth = track.baseSize();
    841             break;
    842         case DistributeSpaceToGrowthLimits:
    843             trackBreadth = track.growthLimitIfNotInfinite();
    844             break;
    845         }
    846         bool infiniteGrowthPotential = track.growthLimitIsInfinite();
    847         LayoutUnit trackGrowthPotential = infiniteGrowthPotential ? track.growthLimit() : track.growthLimit() - trackBreadth;
    848         track.tempSize() = trackBreadth;
    849         // Let's avoid computing availableLogicalSpaceShare as much as possible as it's a hot spot in performance tests.
    850         if (trackGrowthPotential > 0 || infiniteGrowthPotential) {
    851             LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i);
    852             LayoutUnit growthShare = infiniteGrowthPotential ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, trackGrowthPotential);
    853             ASSERT_WITH_MESSAGE(growthShare >= 0, "We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function. We can still have 0 as growthShare if the amount of tracks greatly exceeds the availableLogicalSpace.");
    854             track.tempSize() += growthShare;
    855             availableLogicalSpace -= growthShare;
     866    ASSERT(availableLogicalSpace >= 0);
     867
     868    for (auto* track : tracks)
     869        track->tempSize() = trackSizeForTrackSizeComputationPhase(phase, *track, ForbidInfinity);
     870
     871    if (availableLogicalSpace > 0) {
     872        std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
     873
     874        unsigned tracksSize = tracks.size();
     875        for (unsigned i = 0; i < tracksSize; ++i) {
     876            GridTrack& track = *tracks[i];
     877            const LayoutUnit& trackBreadth = trackSizeForTrackSizeComputationPhase(phase, track, ForbidInfinity);
     878            bool infiniteGrowthPotential = track.infiniteGrowthPotential();
     879            LayoutUnit trackGrowthPotential = infiniteGrowthPotential ? track.growthLimit() : track.growthLimit() - trackBreadth;
     880            // Let's avoid computing availableLogicalSpaceShare as much as possible as it's a hot spot in performance tests.
     881            if (trackGrowthPotential > 0 || infiniteGrowthPotential) {
     882                LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i);
     883                LayoutUnit growthShare = infiniteGrowthPotential ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, trackGrowthPotential);
     884                ASSERT_WITH_MESSAGE(growthShare >= 0, "We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function. We can still have 0 as growthShare if the amount of tracks greatly exceeds the availableLogicalSpace.");
     885                track.tempSize() += growthShare;
     886                availableLogicalSpace -= growthShare;
     887            }
    856888        }
    857889    }
     
    868900
    869901    for (auto* track : tracks)
    870         track->setPlannedSize(std::max(track->plannedSize(), track->tempSize()));
     902        track->setPlannedSize(track->plannedSize() == infinity ? track->tempSize() : std::max(track->plannedSize(), track->tempSize()));
    871903}
    872904
  • trunk/Source/WebCore/rendering/RenderGrid.h

    r182628 r182704  
    9797        ResolveIntrinsicMaximums,
    9898        ResolveMaxContentMaximums,
    99     };
    100     enum DistributeSpacePhase {
    101         DistributeSpaceToBaseSizes,
    102         DistributeSpaceToGrowthLimits,
     99        MaximizeTracks,
    103100    };
    104101    static const LayoutUnit& trackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, GridTrack&, TrackSizeRestriction);
    105102    static bool shouldProcessTrackForTrackSizeComputationPhase(TrackSizeComputationPhase, const GridTrackSize&);
    106103    static bool trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(TrackSizeComputationPhase, const GridTrackSize&);
     104    static void markAsInfinitelyGrowableForTrackSizeComputationPhase(TrackSizeComputationPhase, GridTrack&);
    107105    static void updateTrackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, GridTrack&);
    108106    LayoutUnit currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, RenderBox&, GridTrackSizingDirection, Vector<GridTrack>& columnTracks);
     
    111109    void resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection, const GridCoordinate&, RenderBox& gridItem, GridTrack&, Vector<GridTrack>& columnTracks);
    112110    template <TrackSizeComputationPhase> void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, const GridItemsSpanGroupRange&);
    113     template <DistributeSpacePhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace);
     111    template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace);
    114112
    115113    double computeNormalizedFractionBreadth(Vector<GridTrack>&, const GridSpan& tracksSpan, GridTrackSizingDirection, LayoutUnit availableLogicalSpace) const;
Note: See TracChangeset for help on using the changeset viewer.