Chromium Code Reviews| 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 = 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 double itemFlexFraction = findFlexFactorUnitSize(tracks, span, d irection, 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 ? contentLogicalW idth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize, style()->logicalHeight(), -1))); | 509 return valueForLength(trackLength, direction == ForColumns ? contentLogicalW idth() : 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::computeFlexFactorUnitSize(const Vector<GridTrack>& tracks, Gr idTrackSizingDirection direction, double flexFactorSum, double leftOverSpace, co nst Vector<size_t, 8>& flexibleTracks, PassOwnPtr<TrackIndexSet> tracksToTreatAs Inflexible) const |
|
svillar
2015/09/23 14:57:15
I don't think you need to use specify the initial
| |
| 532 { | 513 { |
| 533 return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue; | 514 // Let flex factor sum be the sum of the flex factors of the flexible tracks . If this value |
| 515 // is less than 1, set it to 1 instead. | |
| 516 double hypotheticalFactorUnitSize = flexFactorSum > 1 ? leftOverSpace / flex FactorSum : leftOverSpace; | |
|
svillar
2015/09/23 14:57:15
Although perhaps slightly less efficient, I think
jfernandez
2015/09/24 08:16:36
I think I'll change the comment so it explains why
| |
| 517 | |
| 518 // product of the hypothetical "flex factor unit" and any flexible track's " flex factor" must be grater than such track's "base size". | |
| 519 OwnPtr<TrackIndexSet> additionalTacksToTreatAsInflexible = tracksToTreatAsIn flexible; | |
|
svillar
2015/09/23 14:57:15
nit: additionalTracks
jfernandez
2015/09/24 08:16:36
Done.
| |
| 520 bool validFlexFactorUnit = true; | |
| 521 for (auto index : flexibleTracks) { | |
| 522 if (additionalTacksToTreatAsInflexible && additionalTacksToTreatAsInflex ible->contains(index)) | |
| 523 continue; | |
| 524 double baseSize = tracks[index].baseSize(); | |
| 525 double flexFactor = gridTrackSize(direction, index).maxTrackBreadth().fl ex(); | |
| 526 // treating all such tracks as inflexible. | |
| 527 if (hypotheticalFactorUnitSize * flexFactor < baseSize) { | |
| 528 leftOverSpace -= baseSize; | |
| 529 flexFactorSum -= flexFactor; | |
| 530 if (!additionalTacksToTreatAsInflexible) | |
| 531 additionalTacksToTreatAsInflexible = adoptPtr(new TrackIndexSet( )); | |
| 532 additionalTacksToTreatAsInflexible->add(index); | |
| 533 validFlexFactorUnit = false; | |
| 534 } | |
| 535 } | |
| 536 return validFlexFactorUnit ? hypotheticalFactorUnitSize : computeFlexFactorU nitSize(tracks, direction, flexFactorSum, leftOverSpace, flexibleTracks, additio nalTacksToTreatAsInflexible.release()); | |
|
svillar
2015/09/23 14:57:15
I know this is nitpicking but I'd prefer this to b
jfernandez
2015/09/24 08:16:36
Done.
| |
| 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 spaceToFil l) const |
| 537 { | 540 { |
| 538 LayoutUnit allocatedSpace; | 541 if (spaceToFill <= 0) |
| 539 Vector<GridTrackForNormalization> tracksForNormalization; | 542 return 0; |
| 543 | |
| 544 double flexFactorSum = 0; | |
| 545 double leftOverSpace = spaceToFill; | |
|
svillar
2015/09/23 14:57:15
Why are you using doubles here? Although the flex
jfernandez
2015/09/24 08:16:36
Well, some operators doesn't allow to mix LayoutUn
| |
| 546 Vector<size_t, 8> flexibleTracks; | |
| 540 for (const auto& resolvedPosition : tracksSpan) { | 547 for (const auto& resolvedPosition : tracksSpan) { |
| 541 GridTrack& track = tracks[resolvedPosition.toInt()]; | 548 size_t trackIndex = resolvedPosition.toInt(); |
| 542 allocatedSpace += track.baseSize(); | 549 GridTrackSize trackSize = gridTrackSize(direction, trackIndex); |
| 543 | 550 double baseSize = tracks[trackIndex].baseSize(); |
| 544 GridTrackSize trackSize = gridTrackSize(direction, resolvedPosition.toIn t()); | 551 if (!trackSize.maxTrackBreadth().isFlex()) { |
| 545 if (!trackSize.maxTrackBreadth().isFlex()) | 552 leftOverSpace -= baseSize; |
| 546 continue; | 553 } else { |
| 547 | 554 double flexFactor = trackSize.maxTrackBreadth().flex(); |
| 548 tracksForNormalization.append(GridTrackForNormalization(track, trackSize .maxTrackBreadth().flex())); | 555 flexibleTracks.append(trackIndex); |
| 556 flexFactorSum += flexFactor; | |
| 557 } | |
| 549 } | 558 } |
| 550 | 559 |
| 551 // The function is not called if we don't have <flex> grid tracks | 560 // The function is not called if we don't have <flex> grid tracks |
| 552 ASSERT(!tracksForNormalization.isEmpty()); | 561 ASSERT(!flexibleTracks.isEmpty()); |
| 553 | 562 |
| 554 std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sort ByGridNormalizedFlexValue); | 563 return computeFlexFactorUnitSize(tracks, direction, flexFactorSum, leftOverS pace, flexibleTracks); |
| 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 } | 564 } |
| 585 | 565 |
| 586 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons t | 566 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons t |
| 587 { | 567 { |
| 588 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi calWidth(); | 568 return (direction == ForRows) ? hasDefiniteLogicalHeight() : hasDefiniteLogi calWidth(); |
| 589 } | 569 } |
| 590 | 570 |
| 591 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size _t i) const | 571 GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size _t i) const |
| 592 { | 572 { |
| 593 bool isForColumns = direction == ForColumns; | 573 bool isForColumns = direction == ForColumns; |
| (...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1926 | 1906 |
| 1927 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); | 1907 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); |
| 1928 } | 1908 } |
| 1929 | 1909 |
| 1930 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) | 1910 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) |
| 1931 { | 1911 { |
| 1932 GridPainter(*this).paintChildren(paintInfo, paintOffset); | 1912 GridPainter(*this).paintChildren(paintInfo, paintOffset); |
| 1933 } | 1913 } |
| 1934 | 1914 |
| 1935 } // namespace blink | 1915 } // namespace blink |
| OLD | NEW |