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 flexFactor > 1 ? track.baseSize() / flexFactor : track.baseSize().toD ouble(); | |
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 = findFrUnitSize(tracks, GridSpan(0, tracks.size() - 1), di rection, 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 double itemFlexFraction = findFrUnitSize(tracks, span, direction , maxContentForChild(*gridItem, direction, sizingData.columnTracks)); |
479 normalizedFractionBreadth = std::max(normalizedFractionBreadth, itemNormalizedFlexBreadth); | 460 flexFraction = std::max(flexFraction, itemFlexFraction); |
480 } | 461 } |
481 } | 462 } |
482 } | 463 } |
483 | 464 |
484 for (const auto& trackIndex : flexibleSizedTracksIndex) { | 465 for (const auto& trackIndex : flexibleSizedTracksIndex) { |
485 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); | 466 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); |
486 | 467 |
487 LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize() , normalizedFractionBreadth * trackSize.maxTrackBreadth().flex()); | 468 LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize() , flexFraction * trackSize.maxTrackBreadth().flex()); |
488 tracks[trackIndex].setBaseSize(baseSize); | 469 tracks[trackIndex].setBaseSize(baseSize); |
489 freeSpace -= baseSize; | 470 freeSpace -= baseSize; |
490 } | 471 } |
491 | 472 |
492 // FIXME: Should ASSERT flexible tracks exhaust the freeSpace ? (see issue 7 39613002). | 473 // FIXME: Should ASSERT flexible tracks exhaust the freeSpace ? (see issue 7 39613002). |
493 } | 474 } |
494 | 475 |
495 LayoutUnit LayoutGrid::computeUsedBreadthOfMinLength(GridTrackSizingDirection di rection, const GridLength& gridLength) const | 476 LayoutUnit LayoutGrid::computeUsedBreadthOfMinLength(GridTrackSizingDirection di rection, const GridLength& gridLength) const |
496 { | 477 { |
497 if (gridLength.isFlex()) | 478 if (gridLength.isFlex()) |
(...skipping 23 matching lines...) Expand all Loading... | |
521 return infinity; | 502 return infinity; |
522 } | 503 } |
523 | 504 |
524 LayoutUnit LayoutGrid::computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirect ion direction, const Length& trackLength) const | 505 LayoutUnit LayoutGrid::computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirect ion direction, const Length& trackLength) const |
525 { | 506 { |
526 ASSERT(trackLength.isSpecified()); | 507 ASSERT(trackLength.isSpecified()); |
527 // FIXME: The -1 here should be replaced by whatever the intrinsic height of the grid is. | 508 // FIXME: The -1 here should be replaced by whatever the intrinsic height of the grid is. |
528 return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize, style( )->logicalHeight(), -1))); | 509 return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize, style( )->logicalHeight(), -1))); |
529 } | 510 } |
530 | 511 |
531 static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track 1, const GridTrackForNormalization& track2) | 512 double LayoutGrid::findFrUnitSize(Vector<GridTrack>& tracks, const GridSpan& tra cksSpan, GridTrackSizingDirection direction, LayoutUnit spaceToFill, TrackIndexS et tracksToTreatAsInflexible) const |
532 { | 513 { |
533 return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue; | 514 if (spaceToFill <= 0) |
534 } | 515 return 0; |
535 | 516 |
536 double LayoutGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, c onst GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit spaceT oFill) const | 517 double flexFactorSum = 0; |
537 { | 518 LayoutUnit leftOverSpace = spaceToFill; |
538 LayoutUnit allocatedSpace; | 519 Vector<size_t> flexibleSizedTracksIndex; |
539 Vector<GridTrackForNormalization> tracksForNormalization; | |
540 for (const auto& resolvedPosition : tracksSpan) { | 520 for (const auto& resolvedPosition : tracksSpan) { |
541 GridTrack& track = tracks[resolvedPosition.toInt()]; | 521 size_t trackIndex = resolvedPosition.toInt(); |
542 allocatedSpace += track.baseSize(); | 522 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); |
543 | 523 if (!trackSize.maxTrackBreadth().isFlex() || tracksToTreatAsInflexible.c ontains(trackIndex)) { |
544 GridTrackSize trackSize = gridTrackSize(direction, resolvedPosition.toIn t()); | 524 leftOverSpace -= tracks[trackIndex].baseSize(); |
545 if (!trackSize.maxTrackBreadth().isFlex()) | 525 } else { |
546 continue; | 526 flexibleSizedTracksIndex.append(trackIndex); |
547 | 527 flexFactorSum += trackSize.maxTrackBreadth().flex(); |
548 tracksForNormalization.append(GridTrackForNormalization(track, trackSize .maxTrackBreadth().flex())); | |
549 } | |
550 | |
551 // The function is not called if we don't have <flex> grid tracks | |
552 ASSERT(!tracksForNormalization.isEmpty()); | |
553 | |
554 std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sort ByGridNormalizedFlexValue); | |
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 } | 528 } |
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 } | 529 } |
577 | 530 |
578 // Let flex factor sum be the sum of the flex factors of the flexible tracks . If this value | 531 // 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. | 532 // is less than 1, set it to 1 instead. |
580 if (accumulatedFractions < 1) | 533 double hypotheticalFrSize = flexFactorSum > 1 ? leftOverSpace / flexFactorSu m : leftOverSpace.toDouble(); |
581 return availableLogicalSpaceIgnoringFractionTracks; | |
582 | 534 |
583 return availableLogicalSpaceIgnoringFractionTracks / accumulatedFractions; | 535 // If the product of the hypothetical fr size and a flexible track's flex fa ctor is less |
536 // than the track's base size, restart this algorithm treating all such trac ks as inflexible | |
537 bool succeed = true; | |
538 for (size_t trackIndex : flexibleSizedTracksIndex) { | |
539 if (hypotheticalFrSize * gridTrackSize(direction, trackIndex).maxTrackBr eadth().flex() < tracks[trackIndex].baseSize().toDouble()) { | |
540 tracksToTreatAsInflexible.add(trackIndex); | |
541 succeed = false; | |
542 } | |
543 } | |
544 | |
545 return succeed ? hypotheticalFrSize : findFrUnitSize(tracks, tracksSpan, dir ection, spaceToFill, tracksToTreatAsInflexible); | |
esprehn
2015/09/10 01:03:14
This recursion keeps creating more copies of the s
| |
584 } | 546 } |
585 | 547 |
586 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons t | 548 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons t |
587 { | 549 { |
588 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi calWidth(); | 550 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi calWidth(); |
589 } | 551 } |
590 | 552 |
591 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size _t i) const | 553 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size _t i) const |
592 { | 554 { |
593 bool isForColumns = direction == ForColumns; | 555 bool isForColumns = direction == ForColumns; |
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1923 | 1885 |
1924 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); | 1886 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); |
1925 } | 1887 } |
1926 | 1888 |
1927 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) | 1889 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) |
1928 { | 1890 { |
1929 GridPainter(*this).paintChildren(paintInfo, paintOffset); | 1891 GridPainter(*this).paintChildren(paintInfo, paintOffset); |
1930 } | 1892 } |
1931 | 1893 |
1932 } // namespace blink | 1894 } // namespace blink |
OLD | NEW |