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 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 , distributionOffset(distribution) | 135 , distributionOffset(distribution) |
136 { | 136 { |
137 } | 137 } |
138 | 138 |
139 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } | 139 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } |
140 | 140 |
141 LayoutUnit positionOffset = -1; | 141 LayoutUnit positionOffset = -1; |
142 LayoutUnit distributionOffset = -1; | 142 LayoutUnit distributionOffset = -1; |
143 }; | 143 }; |
144 | 144 |
145 struct GridTrackForNormalization { | |
146 GridTrackForNormalization(const GridTrack& track, double flex) | |
147 : m_track(&track) | |
148 , m_flex(flex) | |
149 , m_normalizedFlexValue(track.baseSize() / flex) | |
150 { | |
151 } | |
152 | |
153 // Required by std::sort. | |
154 GridTrackForNormalization& operator=(const GridTrackForNormalization& o) | |
155 { | |
156 m_track = o.m_track; | |
157 m_flex = o.m_flex; | |
158 m_normalizedFlexValue = o.m_normalizedFlexValue; | |
159 return *this; | |
160 } | |
161 | |
162 const GridTrack* m_track; | |
163 double m_flex; | |
164 LayoutUnit m_normalizedFlexValue; | |
165 }; | |
166 | |
167 enum TrackSizeRestriction { | 145 enum TrackSizeRestriction { |
168 AllowInfinity, | 146 AllowInfinity, |
169 ForbidInfinity, | 147 ForbidInfinity, |
170 }; | 148 }; |
171 | 149 |
172 class LayoutGrid::GridIterator { | 150 class LayoutGrid::GridIterator { |
173 WTF_MAKE_NONCOPYABLE(GridIterator); | 151 WTF_MAKE_NONCOPYABLE(GridIterator); |
174 public: | 152 public: |
175 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g | 153 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g |
176 // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd co
lumn. | 154 // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd co
lumn. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth(); | 367 LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth(); |
390 minLogicalWidth += scrollbarWidth; | 368 minLogicalWidth += scrollbarWidth; |
391 maxLogicalWidth += scrollbarWidth; | 369 maxLogicalWidth += scrollbarWidth; |
392 } | 370 } |
393 | 371 |
394 bool LayoutGrid::gridElementIsShrinkToFit() | 372 bool LayoutGrid::gridElementIsShrinkToFit() |
395 { | 373 { |
396 return isFloatingOrOutOfFlowPositioned(); | 374 return isFloatingOrOutOfFlowPositioned(); |
397 } | 375 } |
398 | 376 |
| 377 static inline double normalizedFlexFraction(const GridTrack& track, double flexF
actor) |
| 378 { |
| 379 return track.baseSize() / std::max<double>(1, flexFactor); |
| 380 } |
| 381 |
399 void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
on, GridSizingData& sizingData, LayoutUnit& freeSpace) | 382 void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
on, GridSizingData& sizingData, LayoutUnit& freeSpace) |
400 { | 383 { |
401 const LayoutUnit initialFreeSpace = freeSpace; | 384 const LayoutUnit initialFreeSpace = freeSpace; |
402 Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTra
cks : sizingData.rowTracks; | 385 Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTra
cks : sizingData.rowTracks; |
403 Vector<size_t> flexibleSizedTracksIndex; | 386 Vector<size_t> flexibleSizedTracksIndex; |
404 sizingData.contentSizedTracksIndex.shrink(0); | 387 sizingData.contentSizedTracksIndex.shrink(0); |
405 | 388 |
406 // 1. Initialize per Grid track variables. | 389 // 1. Initialize per Grid track variables. |
407 for (size_t i = 0; i < tracks.size(); ++i) { | 390 for (size_t i = 0; i < tracks.size(); ++i) { |
408 GridTrack& track = tracks[i]; | 391 GridTrack& track = tracks[i]; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 track->setBaseSize(track->plannedSize()); | 432 track->setBaseSize(track->plannedSize()); |
450 } else { | 433 } else { |
451 for (auto& track : tracks) | 434 for (auto& track : tracks) |
452 track.setBaseSize(track.growthLimit()); | 435 track.setBaseSize(track.growthLimit()); |
453 } | 436 } |
454 | 437 |
455 if (flexibleSizedTracksIndex.isEmpty()) | 438 if (flexibleSizedTracksIndex.isEmpty()) |
456 return; | 439 return; |
457 | 440 |
458 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction. | 441 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction. |
459 double normalizedFractionBreadth = 0; | 442 double flexFraction = 0; |
460 if (!hasUndefinedRemainingSpace) { | 443 if (!hasUndefinedRemainingSpace) { |
461 normalizedFractionBreadth = computeNormalizedFractionBreadth(tracks, Gri
dSpan(0, tracks.size() - 1), direction, initialFreeSpace); | 444 flexFraction = findFlexFactorUnitSize(tracks, GridSpan(0, tracks.size()
- 1), direction, initialFreeSpace); |
462 } else { | 445 } else { |
463 for (const auto& trackIndex : flexibleSizedTracksIndex) { | 446 for (const auto& trackIndex : flexibleSizedTracksIndex) |
464 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); | 447 flexFraction = std::max(flexFraction, normalizedFlexFraction(tracks[
trackIndex], gridTrackSize(direction, trackIndex).maxTrackBreadth().flex())); |
465 normalizedFractionBreadth = std::max(normalizedFractionBreadth, trac
ks[trackIndex].baseSize() / trackSize.maxTrackBreadth().flex()); | |
466 } | |
467 | 448 |
468 for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) { | 449 for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) { |
469 GridIterator iterator(m_grid, direction, flexibleSizedTracksIndex[i]
); | 450 GridIterator iterator(m_grid, direction, flexibleSizedTracksIndex[i]
); |
470 while (LayoutBox* gridItem = iterator.nextGridItem()) { | 451 while (LayoutBox* gridItem = iterator.nextGridItem()) { |
471 const GridCoordinate coordinate = cachedGridCoordinate(*gridItem
); | 452 const GridCoordinate coordinate = cachedGridCoordinate(*gridItem
); |
472 const GridSpan span = (direction == ForColumns) ? coordinate.col
umns : coordinate.rows; | 453 const GridSpan span = (direction == ForColumns) ? coordinate.col
umns : coordinate.rows; |
473 | 454 |
474 // Do not include already processed items. | 455 // Do not include already processed items. |
475 if (i > 0 && span.resolvedInitialPosition.toInt() <= flexibleSiz
edTracksIndex[i - 1]) | 456 if (i > 0 && span.resolvedInitialPosition.toInt() <= flexibleSiz
edTracksIndex[i - 1]) |
476 continue; | 457 continue; |
477 | 458 |
478 double itemNormalizedFlexBreadth = computeNormalizedFractionBrea
dth(tracks, span, direction, maxContentForChild(*gridItem, direction, sizingData
.columnTracks)); | 459 flexFraction = std::max(flexFraction, findFlexFactorUnitSize(tra
cks, span, direction, maxContentForChild(*gridItem, direction, sizingData.column
Tracks))); |
479 normalizedFractionBreadth = std::max(normalizedFractionBreadth,
itemNormalizedFlexBreadth); | |
480 } | 460 } |
481 } | 461 } |
482 } | 462 } |
483 | 463 |
484 for (const auto& trackIndex : flexibleSizedTracksIndex) { | 464 for (const auto& trackIndex : flexibleSizedTracksIndex) { |
485 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); | 465 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); |
486 | 466 |
487 LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize()
, normalizedFractionBreadth * trackSize.maxTrackBreadth().flex()); | 467 LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize()
, flexFraction * trackSize.maxTrackBreadth().flex()); |
488 tracks[trackIndex].setBaseSize(baseSize); | 468 tracks[trackIndex].setBaseSize(baseSize); |
489 freeSpace -= baseSize; | 469 freeSpace -= baseSize; |
490 } | 470 } |
491 | 471 |
492 // FIXME: Should ASSERT flexible tracks exhaust the freeSpace ? (see issue 7
39613002). | 472 // FIXME: Should ASSERT flexible tracks exhaust the freeSpace ? (see issue 7
39613002). |
493 } | 473 } |
494 | 474 |
495 LayoutUnit LayoutGrid::computeUsedBreadthOfMinLength(GridTrackSizingDirection di
rection, const GridLength& gridLength) const | 475 LayoutUnit LayoutGrid::computeUsedBreadthOfMinLength(GridTrackSizingDirection di
rection, const GridLength& gridLength) const |
496 { | 476 { |
497 if (gridLength.isFlex()) | 477 if (gridLength.isFlex()) |
(...skipping 23 matching lines...) Expand all Loading... |
521 return infinity; | 501 return infinity; |
522 } | 502 } |
523 | 503 |
524 LayoutUnit LayoutGrid::computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirect
ion direction, const Length& trackLength) const | 504 LayoutUnit LayoutGrid::computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirect
ion direction, const Length& trackLength) const |
525 { | 505 { |
526 ASSERT(trackLength.isSpecified()); | 506 ASSERT(trackLength.isSpecified()); |
527 // FIXME: The -1 here should be replaced by whatever the intrinsic height of
the grid is. | 507 // FIXME: The -1 here should be replaced by whatever the intrinsic height of
the grid is. |
528 return valueForLength(trackLength, direction == ForColumns ? contentLogicalW
idth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize,
style()->logicalHeight(), -1))); | 508 return valueForLength(trackLength, direction == ForColumns ? contentLogicalW
idth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize,
style()->logicalHeight(), -1))); |
529 } | 509 } |
530 | 510 |
531 static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track
1, const GridTrackForNormalization& track2) | 511 double LayoutGrid::computeFlexFactorUnitSize(const Vector<GridTrack>& tracks, Gr
idTrackSizingDirection direction, double flexFactorSum, LayoutUnit& leftOverSpac
e, const Vector<size_t, 8>& flexibleTracksIndexes, PassOwnPtr<TrackIndexSet> tra
cksToTreatAsInflexible) const |
532 { | 512 { |
533 return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue; | 513 // We want to avoid the effect of flex factors sum below 1 making the factor
unit size to grow exponentially. |
| 514 double hypotheticalFactorUnitSize = leftOverSpace / std::max<double>(1, flex
FactorSum); |
| 515 |
| 516 // product of the hypothetical "flex factor unit" and any flexible track's "
flex factor" must be grater than such track's "base size". |
| 517 OwnPtr<TrackIndexSet> additionalTracksToTreatAsInflexible = tracksToTreatAsI
nflexible; |
| 518 bool validFlexFactorUnit = true; |
| 519 for (auto index : flexibleTracksIndexes) { |
| 520 if (additionalTracksToTreatAsInflexible && additionalTracksToTreatAsInfl
exible->contains(index)) |
| 521 continue; |
| 522 LayoutUnit baseSize = tracks[index].baseSize(); |
| 523 double flexFactor = gridTrackSize(direction, index).maxTrackBreadth().fl
ex(); |
| 524 // treating all such tracks as inflexible. |
| 525 if (baseSize > hypotheticalFactorUnitSize * flexFactor) { |
| 526 leftOverSpace -= baseSize; |
| 527 flexFactorSum -= flexFactor; |
| 528 if (!additionalTracksToTreatAsInflexible) |
| 529 additionalTracksToTreatAsInflexible = adoptPtr(new TrackIndexSet
()); |
| 530 additionalTracksToTreatAsInflexible->add(index); |
| 531 validFlexFactorUnit = false; |
| 532 } |
| 533 } |
| 534 if (!validFlexFactorUnit) |
| 535 return computeFlexFactorUnitSize(tracks, direction, flexFactorSum, leftO
verSpace, flexibleTracksIndexes, additionalTracksToTreatAsInflexible.release()); |
| 536 return hypotheticalFactorUnitSize; |
534 } | 537 } |
535 | 538 |
536 double LayoutGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, c
onst GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit spaceT
oFill) const | 539 double LayoutGrid::findFlexFactorUnitSize(const Vector<GridTrack>& tracks, const
GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit leftOverSp
ace) const |
537 { | 540 { |
538 LayoutUnit allocatedSpace; | 541 if (leftOverSpace <= 0) |
539 Vector<GridTrackForNormalization> tracksForNormalization; | 542 return 0; |
| 543 |
| 544 double flexFactorSum = 0; |
| 545 Vector<size_t, 8> flexibleTracksIndexes; |
540 for (const auto& resolvedPosition : tracksSpan) { | 546 for (const auto& resolvedPosition : tracksSpan) { |
541 GridTrack& track = tracks[resolvedPosition.toInt()]; | 547 size_t trackIndex = resolvedPosition.toInt(); |
542 allocatedSpace += track.baseSize(); | 548 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); |
543 | 549 if (!trackSize.maxTrackBreadth().isFlex()) { |
544 GridTrackSize trackSize = gridTrackSize(direction, resolvedPosition.toIn
t()); | 550 leftOverSpace -= tracks[trackIndex].baseSize(); |
545 if (!trackSize.maxTrackBreadth().isFlex()) | 551 } else { |
546 continue; | 552 flexibleTracksIndexes.append(trackIndex); |
547 | 553 flexFactorSum += trackSize.maxTrackBreadth().flex(); |
548 tracksForNormalization.append(GridTrackForNormalization(track, trackSize
.maxTrackBreadth().flex())); | 554 } |
549 } | 555 } |
550 | 556 |
551 // The function is not called if we don't have <flex> grid tracks | 557 // The function is not called if we don't have <flex> grid tracks |
552 ASSERT(!tracksForNormalization.isEmpty()); | 558 ASSERT(!flexibleTracksIndexes.isEmpty()); |
553 | 559 |
554 std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sort
ByGridNormalizedFlexValue); | 560 return computeFlexFactorUnitSize(tracks, direction, flexFactorSum, leftOverS
pace, flexibleTracksIndexes); |
555 | |
556 // These values work together: as we walk over our grid tracks, we increase
fractionValueBasedOnGridItemsRatio | |
557 // to match a grid track's usedBreadth to <flex> ratio until the total fract
ions sized grid tracks wouldn't | |
558 // fit into availableLogicalSpaceIgnoringFractionTracks. | |
559 double accumulatedFractions = 0; | |
560 LayoutUnit fractionValueBasedOnGridItemsRatio = 0; | |
561 LayoutUnit availableLogicalSpaceIgnoringFractionTracks = spaceToFill - alloc
atedSpace; | |
562 | |
563 for (const auto& track : tracksForNormalization) { | |
564 if (track.m_normalizedFlexValue > fractionValueBasedOnGridItemsRatio) { | |
565 // If the normalized flex value (we ordered |tracksForNormalization|
by increasing normalized flex value) | |
566 // will make us overflow our container, then stop. We have the previ
ous step's ratio is the best fit. | |
567 if (track.m_normalizedFlexValue * accumulatedFractions > availableLo
gicalSpaceIgnoringFractionTracks) | |
568 break; | |
569 | |
570 fractionValueBasedOnGridItemsRatio = track.m_normalizedFlexValue; | |
571 } | |
572 | |
573 accumulatedFractions += track.m_flex; | |
574 // This item was processed so we re-add its used breadth to the availabl
e space to accurately count the remaining space. | |
575 availableLogicalSpaceIgnoringFractionTracks += track.m_track->baseSize()
; | |
576 } | |
577 | |
578 // Let flex factor sum be the sum of the flex factors of the flexible tracks
. If this value | |
579 // is less than 1, set it to 1 instead. | |
580 if (accumulatedFractions < 1) | |
581 return availableLogicalSpaceIgnoringFractionTracks; | |
582 | |
583 return availableLogicalSpaceIgnoringFractionTracks / accumulatedFractions; | |
584 } | 561 } |
585 | 562 |
586 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons
t | 563 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons
t |
587 { | 564 { |
588 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi
calWidth(); | 565 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi
calWidth(); |
589 } | 566 } |
590 | 567 |
591 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size
_t i) const | 568 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size
_t i) const |
592 { | 569 { |
593 bool isForColumns = direction == ForColumns; | 570 bool isForColumns = direction == ForColumns; |
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 | 1903 |
1927 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); | 1904 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); |
1928 } | 1905 } |
1929 | 1906 |
1930 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) | 1907 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) |
1931 { | 1908 { |
1932 GridPainter(*this).paintChildren(paintInfo, paintOffset); | 1909 GridPainter(*this).paintChildren(paintInfo, paintOffset); |
1933 } | 1910 } |
1934 | 1911 |
1935 } // namespace blink | 1912 } // namespace blink |
OLD | NEW |