99#include < yoga/algorithm/grid/GridLayout.h>
1010#include < yoga/numeric/Comparison.h>
1111#include < yoga/style/StyleSizeLength.h>
12- #include < set >
12+ #include < unordered_set >
1313
1414namespace facebook ::yoga {
1515
16+ // Used in distributeSpaceToTracksBaseSize and distributeSpaceToTracksGrowthLimit
1617enum SpaceDistributionPhase {
1718 AccommodateMinimumContribution,
1819 AccommodateMaxContentContribution,
@@ -145,11 +146,10 @@ struct TrackSizing {
145146 if (includesFlexibleTrack (spannedTracks)) {
146147 continue ;
147148 }
148- int32_t span = dimension == Dimension::Width ? (item.columnEnd - item.columnStart ) : (item.rowEnd - item.rowStart );
149+ size_t span = dimension == Dimension::Width ? (item.columnEnd - item.columnStart ) : (item.rowEnd - item.rowStart );
149150 itemsGroupedByIncreasingSpan[span].push_back ({item, spannedTracks});
150151 }
151152
152- // auto sizingMode = dimension == Dimension::Width ? widthSizingMode : heightSizingMode;
153153 auto containerSize = dimension == Dimension::Width ? containerInnerWidth : containerInnerHeight;
154154 auto sizingMode = dimension == Dimension::Width ? widthSizingMode : heightSizingMode;
155155
@@ -181,10 +181,10 @@ struct TrackSizing {
181181 }
182182
183183 // 2. For content-based minimums
184- // Unimplemented
185-
184+ // TODO: Implement when we support min-content
185+
186186 // 3. For max-content minimums
187- // Unimplemented
187+ // TODO: Implement when we support max-content
188188
189189 // 4. If at this point any track’s growth limit is now less than its base size, increase its growth limit to match its base size.
190190 for (auto & track: spannedTracks) {
@@ -233,12 +233,12 @@ struct TrackSizing {
233233 auto minimumContribution = sizingMode == SizingMode::MaxContent ? getLimitedMinimumContentContribution (item, dimension) : getMinimumContribution (item, dimension);
234234 distributeSpaceToFlexibleTracks (dimension, intrinsicMinimumSizingFunctionTracks, spannedTracks, minimumContribution, SpaceDistributionPhase::AccommodateMinimumContribution);
235235 }
236- // 2, 3, 4, 5, 6 Unimplemented
236+ // 2, 3, 4, 5, 6 does not seem to be needed since max-sizing function is flexible kind and we do not support min-content, max-content yet
237237 }
238238 };
239239
240240 // https://www.w3.org/TR/css-grid-1/#extra-space
241- // Handles for distributing space to track's base size
241+ // Distribute space to tracks' where affected size is base size
242242 void distributeSpaceToTracksBaseSize (
243243 Dimension dimension,
244244 std::vector<GridTrackSize*>& affectedTracks,
@@ -257,12 +257,18 @@ struct TrackSizing {
257257
258258 // 2.1 Find the space to distribute
259259 float totalSpannedTracksSize = 0 .0f ;
260- for (auto & track: spannedTracks) {
261- totalSpannedTracksSize += track->baseSize ;
260+ auto gap = node->style ().computeGapForDimension (dimension, containerSize);
261+ for (size_t i = 0 ; i < spannedTracks.size (); i++) {
262+ totalSpannedTracksSize += spannedTracks[i]->baseSize ;
263+ // gaps are treated as tracks of fixed size. Item can span over gaps.
264+ if (i < spannedTracks.size () - 1 ) {
265+ totalSpannedTracksSize += gap;
266+ }
262267 }
263268 float spaceToDistribute = std::max (0 .0f , sizeContribution - totalSpannedTracksSize);
264- std::set<GridTrackSize*> frozenTracks;
265-
269+ std::unordered_set<GridTrackSize*> frozenTracks;
270+ frozenTracks.reserve (affectedTracks.size ());
271+
266272 // 2.2. Distribute space up to limits
267273 while (frozenTracks.size () < affectedTracks.size () && spaceToDistribute > 0 .0f && !yoga::inexactEquals (spaceToDistribute, 0 .0f )) {
268274 auto unfrozenTrackCount = affectedTracks.size () - frozenTracks.size ();
@@ -289,7 +295,7 @@ struct TrackSizing {
289295 }
290296
291297 // 2.3. Distribute space to non-affected tracks:
292- // Currently, browsers do not implement this step.
298+ // Currently, browsers do not implement this step. So we avoid it to match with browsers
293299 // https://github.com/w3c/csswg-drafts/issues/3648
294300
295301 // 2.4. Distribute space beyond limits
@@ -316,14 +322,10 @@ struct TrackSizing {
316322 }
317323 }
318324
319- frozenTracks.clear ();
320- while (spaceToDistribute > 0 .0f && !yoga::inexactEquals (spaceToDistribute, 0 .0f ) && tracksToGrowBeyondLimits.size () > 0 ) {
321- auto unfrozenTrackCount = tracksToGrowBeyondLimits.size () - frozenTracks.size ();
325+ auto unfrozenTrackCount = tracksToGrowBeyondLimits.size ();
326+ while (spaceToDistribute > 0 .0f && !yoga::inexactEquals (spaceToDistribute, 0 .0f ) && unfrozenTrackCount > 0 ) {
322327 auto distributionPerTrack = spaceToDistribute / unfrozenTrackCount;
323328 for (auto & track: tracksToGrowBeyondLimits) {
324- if (frozenTracks.contains (track)) {
325- continue ;
326- }
327329 itemIncurredIncrease[track] += distributionPerTrack;
328330 spaceToDistribute -= distributionPerTrack;
329331 }
@@ -343,6 +345,8 @@ struct TrackSizing {
343345 }
344346 }
345347
348+ // https://www.w3.org/TR/css-grid-1/#extra-space
349+ // Distribute space to tracks' where affected size is growth limit
346350 void distributeSpaceToTracksGrowthLimit (
347351 Dimension dimension,
348352 std::vector<GridTrackSize*>& affectedTracks,
@@ -361,23 +365,25 @@ struct TrackSizing {
361365
362366 // 2.1 Find the space to distribute
363367 float totalSpannedTracksSize = 0 .0f ;
364- for (auto & track: spannedTracks) {
365- totalSpannedTracksSize += track->growthLimit == INFINITY ? track->baseSize : track->growthLimit ;
368+ auto gap = node->style ().computeGapForDimension (dimension, containerSize);
369+ for (size_t i = 0 ; i < spannedTracks.size (); i++) {
370+ totalSpannedTracksSize += spannedTracks[i]->growthLimit == INFINITY ? spannedTracks[i]->baseSize : spannedTracks[i]->growthLimit ;
371+ if (i < spannedTracks.size () - 1 ) {
372+ // gaps are treated as tracks of fixed size. Item can span over gaps.
373+ totalSpannedTracksSize += gap;
374+ }
366375 }
367376 float spaceToDistribute = std::max (0 .0f , sizeContribution - totalSpannedTracksSize);
368- std::set<GridTrackSize*> frozenTracks;
369-
370- // Freeze tracks that are not infinitely growable before distribution
371- // Per spec: "If the affected size was a growth limit and the track is not marked infinitely growable,
372- // then each item-incurred increase will be zero."
377+ std::unordered_set<GridTrackSize*> frozenTracks;
378+ frozenTracks.reserve (affectedTracks.size ());
373379
374380 // 2.2. Distribute space up to limits
375381 while (frozenTracks.size () < affectedTracks.size () && spaceToDistribute > 0 .0f && !yoga::inexactEquals (spaceToDistribute, 0 .0f )) {
376382 auto unfrozenTrackCount = affectedTracks.size () - frozenTracks.size ();
377383 auto distributionPerTrack = spaceToDistribute / unfrozenTrackCount;
378384
379385 for (auto & track: affectedTracks) {
380- if (frozenTracks.find (track) != frozenTracks. end ( )) {
386+ if (frozenTracks.contains (track)) {
381387 continue ;
382388 }
383389 auto limit = INFINITY;
@@ -417,15 +423,11 @@ struct TrackSizing {
417423 tracksToGrowBeyondLimits.push_back (track);
418424 }
419425 }
420- frozenTracks. clear ();
426+
421427 while (spaceToDistribute > 0 .0f && !yoga::inexactEquals (spaceToDistribute, 0 .0f ) && tracksToGrowBeyondLimits.size () > 0 ) {
422- // TODO: handle fit-content check here
423428 auto unfrozenTrackCount = tracksToGrowBeyondLimits.size () - frozenTracks.size ();
424429 auto distributionPerTrack = spaceToDistribute / unfrozenTrackCount;
425430 for (auto & track: tracksToGrowBeyondLimits) {
426- if (frozenTracks.find (track) != frozenTracks.end ()) {
427- continue ;
428- }
429431 itemIncurredIncrease[track] += distributionPerTrack;
430432 spaceToDistribute -= distributionPerTrack;
431433 }
@@ -449,17 +451,25 @@ struct TrackSizing {
449451 }
450452 }
451453 }
452-
454+ // https://www.w3.org/TR/css-grid-1/#extra-space
455+ // We keep affected size as base size because growth limit distribution step does not apply to flexible max sizing functions.
456+ // Also there is no use of limit here since growth limit is INFINITY for flexible tracks
453457 void distributeSpaceToFlexibleTracks (
454458 Dimension dimension,
455459 std::vector<GridTrackSize*>& affectedTracks,
456460 const std::vector<GridTrackSize*>& spannedTracks,
457461 float sizeContribution,
458462 SpaceDistributionPhase sizeContributionPhase
459463 ) {
464+ auto containerSize = dimension == Dimension::Width ? containerInnerWidth : containerInnerHeight;
460465 float totalSpannedTracksSize = 0 .0f ;
461- for (auto & track: spannedTracks) {
462- totalSpannedTracksSize += track->baseSize ;
466+ auto gap = node->style ().computeGapForDimension (dimension, containerSize);
467+ for (size_t i = 0 ; i < spannedTracks.size (); i++) {
468+ totalSpannedTracksSize += spannedTracks[i]->baseSize ;
469+ if (i < spannedTracks.size () - 1 ) {
470+ // gaps are treated as tracks of fixed size. Item can span over gaps.
471+ totalSpannedTracksSize += gap;
472+ }
463473 }
464474
465475 float sumOfFlexFactors = 0 .0f ;
@@ -513,10 +523,11 @@ struct TrackSizing {
513523 freeSpace = INFINITY;
514524 }
515525
516- // If the free space is positive, distribute it equally to the base sizes of all tracks,
526+ // If the free space is positive, distribute it equally to the base sizes of all tracks,
517527 // freezing tracks as they reach their growth limits (and continuing to grow the unfrozen tracks as needed).
518528 if (freeSpace > 0 .0f && !yoga::inexactEquals (freeSpace, 0 .0f )) {
519- std::set<GridTrackSize*> frozenTracks;
529+ std::unordered_set<GridTrackSize*> frozenTracks;
530+ frozenTracks.reserve (tracks.size ());
520531 auto extraSpace = freeSpace;
521532
522533 while (frozenTracks.size () < tracks.size () && extraSpace > 0 .0f && !yoga::inexactEquals (extraSpace, 0 .0f )) {
@@ -595,8 +606,8 @@ struct TrackSizing {
595606 trackPointers.push_back (&track);
596607 }
597608
598- std::function<float (const std::vector<GridTrackSize*>&, float , std::set <GridTrackSize*>)> findFrSize;
599- findFrSize = [&](const std::vector<GridTrackSize*>& tracks, float spaceToFill, std::set <GridTrackSize*> inflexibleTracks) -> float {
609+ std::function<float (const std::vector<GridTrackSize*>&, float , std::unordered_set <GridTrackSize*>)> findFrSize;
610+ findFrSize = [&](const std::vector<GridTrackSize*>& tracks, float spaceToFill, std::unordered_set <GridTrackSize*> inflexibleTracks) -> float {
600611 auto leftoverSpace = spaceToFill;
601612 auto flexFactorSum = 0 .0f ;
602613 std::vector<GridTrackSize*> flexibleTracks;
@@ -625,7 +636,7 @@ struct TrackSizing {
625636 // Let the hypothetical fr size be the leftover space divided by the flex factor sum.
626637 auto hypotheticalFrSize = leftoverSpace / flexFactorSum;
627638 // If the product of the hypothetical fr size and a flexible track's flex factor is less than the track's base size
628- std::set <GridTrackSize*> _inflexibleTracks;
639+ std::unordered_set <GridTrackSize*> _inflexibleTracks;
629640 for (auto & track : flexibleTracks) {
630641 if (track->maxSizingFunction .isStretch () && track->maxSizingFunction .value ().isDefined ()) {
631642 float flexFactor = track->maxSizingFunction .value ().unwrap ();
@@ -662,7 +673,7 @@ struct TrackSizing {
662673 // Otherwise, if the free space is a definite length:
663674 // The used flex fraction is the result of finding the size of an fr using all of the grid tracks and a space to fill of the available grid space.
664675 else if (freeSpace != YGUndefined) {
665- usedFlexFraction = findFrSize (trackPointers, containerSize, std::set <GridTrackSize*>());
676+ usedFlexFraction = findFrSize (trackPointers, containerSize, std::unordered_set <GridTrackSize*>());
666677 }
667678 // Otherwise, if the free space is an indefinite length:
668679 // The used flex fraction is the maximum of:
@@ -689,7 +700,7 @@ struct TrackSizing {
689700 spannedTrackPointers.push_back (track);
690701 }
691702 auto itemMaxContentContribution = getMaxContentContribution (item, dimension);
692- usedFlexFraction = std::max (usedFlexFraction, findFrSize (spannedTrackPointers, itemMaxContentContribution, std::set <GridTrackSize*>()));
703+ usedFlexFraction = std::max (usedFlexFraction, findFrSize (spannedTrackPointers, itemMaxContentContribution, std::unordered_set <GridTrackSize*>()));
693704 }
694705 }
695706
@@ -729,7 +740,7 @@ struct TrackSizing {
729740 if (yoga::isDefined (minContainerSize)) {
730741 if (newTotalSize < minContainerSize) {
731742 // Redo with min constraint
732- usedFlexFraction = findFrSize (trackPointers, minContainerSize, std::set <GridTrackSize*>());
743+ usedFlexFraction = findFrSize (trackPointers, minContainerSize, std::unordered_set <GridTrackSize*>());
733744 }
734745 }
735746
@@ -747,7 +758,7 @@ struct TrackSizing {
747758 if (yoga::isDefined (maxContainerSize)) {
748759 if (newTotalSize > maxContainerSize) {
749760 // Redo with max constraint
750- usedFlexFraction = findFrSize (trackPointers, maxContainerSize, std::set <GridTrackSize*>());
761+ usedFlexFraction = findFrSize (trackPointers, maxContainerSize, std::unordered_set <GridTrackSize*>());
751762 }
752763 }
753764
0 commit comments