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 15 matching lines...) Expand all Loading... | |
| 26 #include "core/layout/LayoutGrid.h" | 26 #include "core/layout/LayoutGrid.h" |
| 27 | 27 |
| 28 #include "core/frame/UseCounter.h" | 28 #include "core/frame/UseCounter.h" |
| 29 #include "core/layout/LayoutState.h" | 29 #include "core/layout/LayoutState.h" |
| 30 #include "core/layout/TextAutosizer.h" | 30 #include "core/layout/TextAutosizer.h" |
| 31 #include "core/paint/GridPainter.h" | 31 #include "core/paint/GridPainter.h" |
| 32 #include "core/paint/PaintLayer.h" | 32 #include "core/paint/PaintLayer.h" |
| 33 #include "core/style/ComputedStyle.h" | 33 #include "core/style/ComputedStyle.h" |
| 34 #include "core/style/GridArea.h" | 34 #include "core/style/GridArea.h" |
| 35 #include "platform/LengthFunctions.h" | 35 #include "platform/LengthFunctions.h" |
| 36 #include "platform/text/WritingMode.h" | |
| 36 #include "wtf/PtrUtil.h" | 37 #include "wtf/PtrUtil.h" |
| 37 #include <algorithm> | 38 #include <algorithm> |
| 38 #include <memory> | 39 #include <memory> |
| 39 | 40 |
| 40 namespace blink { | 41 namespace blink { |
| 41 | 42 |
| 42 static const int infinity = -1; | 43 static const int infinity = -1; |
| 43 | 44 |
| 44 class GridItemWithSpan; | 45 class GridItemWithSpan; |
| 45 | 46 |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 growthLimits); | 577 growthLimits); |
| 577 ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); | 578 ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); |
| 578 sizingData.nextState(); | 579 sizingData.nextState(); |
| 579 } | 580 } |
| 580 | 581 |
| 581 void LayoutGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, | 582 void LayoutGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, |
| 582 LayoutUnit availableSpaceForColumns, | 583 LayoutUnit availableSpaceForColumns, |
| 583 LayoutUnit availableSpaceForRows) { | 584 LayoutUnit availableSpaceForRows) { |
| 584 DCHECK(sizingData.sizingState > GridSizingData::RowSizingFirstIteration); | 585 DCHECK(sizingData.sizingState > GridSizingData::RowSizingFirstIteration); |
| 585 | 586 |
| 587 // Baseline alignment may change item's intrinsic size, hence changing its | |
| 588 // min-content contribution. | |
| 589 // https://drafts.csswg.org/css-align-3/#baseline-align-content | |
| 590 // https://drafts.csswg.org/css-align-3/#baseline-align-self | |
| 591 bool baselineAffectIntrinsicWidth = baselineMayAffectIntrinsicWidth(); | |
| 592 bool baselineAffectIntrinsicHeight = baselineMayAffectIntrinsicHeight(); | |
| 593 | |
| 586 // In orthogonal flow cases column track's size is determined by using the | 594 // In orthogonal flow cases column track's size is determined by using the |
| 587 // computed row track's size, which it was estimated during the first cycle of | 595 // computed row track's size, which it was estimated during the first cycle of |
| 588 // the sizing algorithm. | 596 // the sizing algorithm. |
| 597 bool intrinsicSizeMayHaveChanged = | |
| 598 baselineAffectIntrinsicWidth || baselineAffectIntrinsicHeight || | |
| 599 sizingData.grid().hasAnyOrthogonalGridItem(); | |
| 600 | |
|
svillar
2017/02/09 13:10:09
Can't we just early return here if !intrinsicSizeM
jfernandez
2017/02/09 14:16:03
Acknowledged.
| |
| 601 // Compute again the intrinsic size if baseline changed item's min-content | |
| 602 // contribution. | |
| 603 // TODO (lajava): Should we do the same because if orthogonal items ? Perhaps | |
| 604 // after executing again the track sizing algorithm ? | |
|
svillar
2017/02/09 13:10:09
I think we can take advantage of this change and d
jfernandez
2017/02/09 14:16:03
Acknowledged.
| |
| 605 if (baselineAffectIntrinsicWidth) { | |
| 606 setPreferredLogicalWidthsDirty(MarkOnlyThis); | |
|
svillar
2017/02/09 13:10:09
Not sure if MarkOnlyThis is enough for orthogonal
jfernandez
2017/02/09 14:16:03
Umm, I think we must prevent infinite-iterations,
| |
| 607 updateLogicalWidth(); | |
| 608 availableSpaceForColumns = availableLogicalWidth(); | |
| 609 } | |
| 610 | |
| 589 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns | 611 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns |
| 590 // and rows, to determine the final values. | 612 // and rows, to determine the final values. |
| 591 // TODO (lajava): orthogonal flows is just one of the cases which may require | 613 // TODO (lajava): orthogonal flows is just one of the cases which may require |
| 592 // a new cycle of the sizing algorithm; there may be more. In addition, not | 614 // a new cycle of the sizing algorithm; there may be more. In addition, not |
| 593 // all the cases with orthogonal flows require this extra cycle; we need a | 615 // all the cases with orthogonal flows require this extra cycle; we need a |
| 594 // more specific condition to detect whether child's min-content contribution | 616 // more specific condition to detect whether child's min-content contribution |
| 595 // has changed or not. | 617 // has changed or not. |
| 596 if (sizingData.grid().hasAnyOrthogonalGridItem()) { | 618 if (intrinsicSizeMayHaveChanged) { |
| 597 computeTrackSizesForDefiniteSize(ForColumns, sizingData, | 619 computeTrackSizesForDefiniteSize(ForColumns, sizingData, |
| 598 availableSpaceForColumns); | 620 availableSpaceForColumns); |
| 599 computeTrackSizesForDefiniteSize(ForRows, sizingData, | 621 computeTrackSizesForDefiniteSize(ForRows, sizingData, |
| 600 availableSpaceForRows); | 622 availableSpaceForRows); |
| 601 } | 623 } |
| 624 | |
| 625 if (baselineAffectIntrinsicHeight) { | |
| 626 LayoutUnit trackBasedLogicalHeight = | |
| 627 computeTrackBasedLogicalHeight(sizingData) + | |
| 628 borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(); | |
| 629 setLogicalHeight(trackBasedLogicalHeight); | |
|
svillar
2017/02/09 13:10:09
Perhaps you could omit the trackBasedLogicalHeight
jfernandez
2017/02/09 14:16:03
Acknowledged.
| |
| 630 } | |
| 602 } | 631 } |
| 603 | 632 |
| 604 void LayoutGrid::layoutBlock(bool relayoutChildren) { | 633 void LayoutGrid::layoutBlock(bool relayoutChildren) { |
| 605 ASSERT(needsLayout()); | 634 ASSERT(needsLayout()); |
| 606 | 635 |
| 607 // We cannot perform a simplifiedLayout() on a dirty grid that | 636 // We cannot perform a simplifiedLayout() on a dirty grid that |
| 608 // has positioned items to be laid out. | 637 // has positioned items to be laid out. |
| 609 if (!relayoutChildren && | 638 if (!relayoutChildren && |
| 610 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && | 639 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && |
| 611 simplifiedLayout()) | 640 simplifiedLayout()) |
| 612 return; | 641 return; |
| 613 | 642 |
| 643 m_rowAxisAlignmentContext.clear(); | |
| 644 m_colAxisAlignmentContext.clear(); | |
| 645 | |
| 614 SubtreeLayoutScope layoutScope(*this); | 646 SubtreeLayoutScope layoutScope(*this); |
| 615 | 647 |
| 616 { | 648 { |
| 617 // LayoutState needs this deliberate scope to pop before updating scroll | 649 // LayoutState needs this deliberate scope to pop before updating scroll |
| 618 // information (which may trigger relayout). | 650 // information (which may trigger relayout). |
| 619 LayoutState state(*this); | 651 LayoutState state(*this); |
| 620 | 652 |
| 621 LayoutSize previousSize = size(); | 653 LayoutSize previousSize = size(); |
| 622 | 654 |
| 623 // We need to clear both own and containingBlock override sizes to | 655 // We need to clear both own and containingBlock override sizes to |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 setLogicalHeight(trackBasedLogicalHeight); | 706 setLogicalHeight(trackBasedLogicalHeight); |
| 675 | 707 |
| 676 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); | 708 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
| 677 updateLogicalHeight(); | 709 updateLogicalHeight(); |
| 678 | 710 |
| 679 // Once grid's indefinite height is resolved, we can compute the | 711 // Once grid's indefinite height is resolved, we can compute the |
| 680 // available free space for Content Alignment. | 712 // available free space for Content Alignment. |
| 681 if (!cachedHasDefiniteLogicalHeight()) | 713 if (!cachedHasDefiniteLogicalHeight()) |
| 682 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; | 714 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; |
| 683 | 715 |
| 716 // TODO (lajava): We need to compute baselines after step 2 so | |
| 717 // items with a relative size (percentages) can resolve it before | |
| 718 // determining its baseline. However, we only set item's grid area | |
| 719 // (via override sizes) as part of the content-sized tracks sizing | |
| 720 // logic. Hence, items located at fixed or flexible tracks can't | |
| 721 // resolve correctly their size at this stage, which may lead to | |
| 722 // determining incorrect their shared context's baseline. | |
| 723 computeBaselineAlignmentContext(sizingData); | |
|
svillar
2017/02/09 13:10:09
Not sure why you insert the computation in the mid
jfernandez
2017/02/09 14:16:03
We must do it here to so that when repeating the t
svillar
2017/02/13 15:18:46
Sorry about this. Yes it's propertly placed. I was
jfernandez
2017/02/13 23:32:37
I meant step 2 as described here:
https://drafts.
| |
| 724 | |
| 684 // 3- If the min-content contribution of any grid items have changed based | 725 // 3- If the min-content contribution of any grid items have changed based |
| 685 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with | 726 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with |
| 686 // the new min-content contribution (once only). | 727 // the new min-content contribution (once only). |
| 687 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, | 728 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, |
| 688 contentLogicalHeight()); | 729 contentLogicalHeight()); |
| 689 | 730 |
| 690 // Grid container should have the minimum height of a line if it's editable. | 731 // Grid container should have the minimum height of a line if it's editable. |
| 691 // That doesn't affect track sizing though. | 732 // That doesn't affect track sizing though. |
| 692 if (hasLineIfEmpty()) | 733 if (hasLineIfEmpty()) |
| 693 setLogicalHeight( | 734 setLogicalHeight( |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1317 LayoutUnit(-1)); | 1358 LayoutUnit(-1)); |
| 1318 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1359 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
| 1319 } | 1360 } |
| 1320 | 1361 |
| 1321 // We need to clear the stretched height to properly compute logical height | 1362 // We need to clear the stretched height to properly compute logical height |
| 1322 // during layout. | 1363 // during layout. |
| 1323 if (child.needsLayout()) | 1364 if (child.needsLayout()) |
| 1324 child.clearOverrideLogicalContentHeight(); | 1365 child.clearOverrideLogicalContentHeight(); |
| 1325 | 1366 |
| 1326 child.layoutIfNeeded(); | 1367 child.layoutIfNeeded(); |
| 1368 GridAxis baselineAxis = | |
| 1369 isOrthogonalChild(child) ? GridRowAxis : GridColumnAxis; | |
| 1370 if (isBaselineAlignmentForChild(child, baselineAxis) && | |
| 1371 isBaselineContextComputed(baselineAxis)) { | |
| 1372 auto& group = getBaselineGroupForChild(child, sizingData, baselineAxis); | |
| 1373 return group.maxAscent() + group.maxDescent(); | |
| 1374 } | |
| 1327 return child.logicalHeight() + child.marginLogicalHeight(); | 1375 return child.logicalHeight() + child.marginLogicalHeight(); |
| 1328 } | 1376 } |
| 1329 | 1377 |
| 1330 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( | 1378 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( |
| 1331 const LayoutBox& child, | 1379 const LayoutBox& child, |
| 1332 GridTrackSizingDirection direction) const { | 1380 GridTrackSizingDirection direction) const { |
| 1333 return !isOrthogonalChild(child) | 1381 return !isOrthogonalChild(child) |
| 1334 ? direction | 1382 ? direction |
| 1335 : (direction == ForColumns ? ForRows : ForColumns); | 1383 : (direction == ForColumns ? ForRows : ForColumns); |
| 1336 } | 1384 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 | 1468 |
| 1421 // All orthogonal flow boxes were already laid out during an early layout | 1469 // All orthogonal flow boxes were already laid out during an early layout |
| 1422 // phase performed in FrameView::performLayout. | 1470 // phase performed in FrameView::performLayout. |
| 1423 // It's true that grid track sizing was not completed at that time and it may | 1471 // It's true that grid track sizing was not completed at that time and it may |
| 1424 // afffect the final height of a grid item, but since it's forbidden to | 1472 // afffect the final height of a grid item, but since it's forbidden to |
| 1425 // perform a layout during intrinsic width computation, we have to use that | 1473 // perform a layout during intrinsic width computation, we have to use that |
| 1426 // computed height for now. | 1474 // computed height for now. |
| 1427 if (direction == ForColumns && | 1475 if (direction == ForColumns && |
| 1428 sizingData.sizingOperation == IntrinsicSizeComputation) { | 1476 sizingData.sizingOperation == IntrinsicSizeComputation) { |
| 1429 DCHECK(isOrthogonalChild(child)); | 1477 DCHECK(isOrthogonalChild(child)); |
| 1478 if (isBaselineAlignmentForChild(child, GridRowAxis) && | |
| 1479 isBaselineContextComputed(GridRowAxis)) { | |
| 1480 auto& group = getBaselineGroupForChild(child, sizingData, GridRowAxis); | |
| 1481 return group.maxAscent() + group.maxDescent(); | |
| 1482 } | |
| 1430 return child.logicalHeight() + child.marginLogicalHeight(); | 1483 return child.logicalHeight() + child.marginLogicalHeight(); |
| 1431 } | 1484 } |
| 1432 | 1485 |
| 1433 if (updateOverrideContainingBlockContentSizeForChild( | 1486 if (updateOverrideContainingBlockContentSizeForChild( |
| 1434 child, childInlineDirection, sizingData)) | 1487 child, childInlineDirection, sizingData)) |
| 1435 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1488 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
| 1436 return logicalHeightForChild(child, sizingData); | 1489 return logicalHeightForChild(child, sizingData); |
| 1437 } | 1490 } |
| 1438 | 1491 |
| 1439 DISABLE_CFI_PERF | 1492 DISABLE_CFI_PERF |
| (...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3082 .toInt(); | 3135 .toInt(); |
| 3083 } | 3136 } |
| 3084 | 3137 |
| 3085 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, | 3138 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, |
| 3086 LineDirectionMode direction) { | 3139 LineDirectionMode direction) { |
| 3087 return (direction == HorizontalLine ? box.size().height() | 3140 return (direction == HorizontalLine ? box.size().height() |
| 3088 : box.size().width()) | 3141 : box.size().width()) |
| 3089 .toInt(); | 3142 .toInt(); |
| 3090 } | 3143 } |
| 3091 | 3144 |
| 3092 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be | |
| 3093 // refactored somehow. | |
| 3094 int LayoutGrid::baselinePosition(FontBaseline, | 3145 int LayoutGrid::baselinePosition(FontBaseline, |
| 3095 bool, | 3146 bool, |
| 3096 LineDirectionMode direction, | 3147 LineDirectionMode direction, |
| 3097 LinePositionMode mode) const { | 3148 LinePositionMode mode) const { |
| 3098 DCHECK_EQ(mode, PositionOnContainingLine); | 3149 DCHECK_EQ(mode, PositionOnContainingLine); |
| 3099 int baseline = firstLineBoxBaseline(); | 3150 int baseline = firstLineBoxBaseline(); |
| 3100 // We take content-box's bottom if no valid baseline. | 3151 // We take content-box's bottom if no valid baseline. |
| 3101 if (baseline == -1) | 3152 if (baseline == -1) |
| 3102 baseline = synthesizedBaselineFromContentBox(*this, direction); | 3153 baseline = synthesizedBaselineFromContentBox(*this, direction); |
| 3103 | 3154 |
| 3104 return baseline + beforeMarginInLineDirection(direction); | 3155 return baseline + beforeMarginInLineDirection(direction); |
| 3105 } | 3156 } |
| 3106 | 3157 |
| 3107 bool LayoutGrid::isInlineBaselineAlignedChild(const LayoutBox* child) const { | |
| 3108 return alignSelfForChild(*child).position() == ItemPositionBaseline && | |
| 3109 !isOrthogonalChild(*child) && !hasAutoMarginsInColumnAxis(*child); | |
| 3110 } | |
| 3111 | |
| 3112 int LayoutGrid::firstLineBoxBaseline() const { | 3158 int LayoutGrid::firstLineBoxBaseline() const { |
| 3113 if (isWritingModeRoot() || !m_grid.hasGridItems()) | 3159 if (isWritingModeRoot() || !m_grid.hasGridItems()) |
| 3114 return -1; | 3160 return -1; |
| 3115 const LayoutBox* baselineChild = nullptr; | 3161 const LayoutBox* baselineChild = nullptr; |
| 3116 const LayoutBox* firstChild = nullptr; | 3162 const LayoutBox* firstChild = nullptr; |
| 3117 bool isBaselineAligned = false; | 3163 bool isBaselineAligned = false; |
| 3118 // Finding the first grid item in grid order. | 3164 // Finding the first grid item in grid order. |
| 3119 for (size_t column = 0; | 3165 for (size_t column = 0; |
| 3120 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { | 3166 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { |
| 3121 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { | 3167 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { |
| 3122 const LayoutBox* child = m_grid.cell(0, column)[index]; | 3168 const LayoutBox* child = m_grid.cell(0, column)[index]; |
| 3123 DCHECK(!child->isOutOfFlowPositioned()); | 3169 DCHECK(!child->isOutOfFlowPositioned()); |
| 3124 // If an item participates in baseline alignmen, we select such item. | 3170 // If an item participates in baseline alignment, we select such item. |
| 3125 if (isInlineBaselineAlignedChild(child)) { | 3171 if (isBaselineAlignmentForChild(*child)) { |
| 3126 // TODO (lajava): self-baseline and content-baseline alignment | 3172 // TODO (lajava): self-baseline and content-baseline alignment |
| 3127 // still not implemented. | 3173 // still not implemented. |
|
svillar
2017/02/09 13:10:09
Time to remove this comment?
jfernandez
2017/02/09 14:16:03
Umm, I don't think we can do it now. We must imple
svillar
2017/02/13 15:18:46
Acknowledged.
| |
| 3128 baselineChild = child; | 3174 baselineChild = child; |
| 3129 isBaselineAligned = true; | 3175 isBaselineAligned = true; |
| 3130 break; | 3176 break; |
| 3131 } | 3177 } |
| 3132 if (!baselineChild) { | 3178 if (!baselineChild) { |
| 3133 // Use dom order for items in the same cell. | 3179 // Use dom order for items in the same cell. |
| 3134 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < | 3180 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < |
| 3135 m_grid.gridItemPaintOrder(*firstChild))) | 3181 m_grid.gridItemPaintOrder(*firstChild))) |
| 3136 firstChild = child; | 3182 firstChild = child; |
| 3137 } | 3183 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 3165 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { | 3211 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { |
| 3166 int baseline = firstLineBoxBaseline(); | 3212 int baseline = firstLineBoxBaseline(); |
| 3167 if (baseline != -1) | 3213 if (baseline != -1) |
| 3168 return baseline; | 3214 return baseline; |
| 3169 | 3215 |
| 3170 int marginHeight = | 3216 int marginHeight = |
| 3171 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); | 3217 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); |
| 3172 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; | 3218 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; |
| 3173 } | 3219 } |
| 3174 | 3220 |
| 3221 bool LayoutGrid::isHorizontalGridAxis(GridAxis axis) const { | |
| 3222 return axis == GridRowAxis ? isHorizontalWritingMode() | |
| 3223 : !isHorizontalWritingMode(); | |
| 3224 } | |
| 3225 | |
| 3226 bool LayoutGrid::isParallelToBlockAxisForChild(const LayoutBox& child, | |
| 3227 GridAxis axis) const { | |
| 3228 return axis == GridColumnAxis ? !isOrthogonalChild(child) | |
| 3229 : isOrthogonalChild(child); | |
| 3230 } | |
| 3231 | |
| 3232 bool LayoutGrid::isDescentBaselineForChild(const LayoutBox& child, | |
| 3233 GridAxis baselineAxis) const { | |
| 3234 return isHorizontalGridAxis(baselineAxis) && | |
| 3235 !styleRef().isFlippedBlocksWritingMode(); | |
| 3236 } | |
| 3237 | |
| 3238 bool LayoutGrid::isBaselineAlignmentForChild(const LayoutBox& child, | |
| 3239 GridAxis baselineAxis) const { | |
| 3240 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 3241 ItemPosition align = isColumnAxisBaseline | |
| 3242 ? alignSelfForChild(child).position() | |
| 3243 : justifySelfForChild(child).position(); | |
| 3244 bool hasAutoMargins = isColumnAxisBaseline ? hasAutoMarginsInColumnAxis(child) | |
| 3245 : hasAutoMarginsInRowAxis(child); | |
| 3246 return isBaselinePosition(align) && !hasAutoMargins; | |
| 3247 } | |
| 3248 | |
| 3249 const BaselineGroup& LayoutGrid::getBaselineGroupForChild( | |
| 3250 const LayoutBox& child, | |
| 3251 const GridSizingData& sizingData, | |
| 3252 GridAxis baselineAxis) const { | |
| 3253 DCHECK(isBaselineAlignmentForChild(child, baselineAxis)); | |
| 3254 auto& grid = sizingData.grid(); | |
| 3255 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 3256 bool isRowAxisContext = isColumnAxisBaseline; | |
| 3257 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) | |
| 3258 : grid.gridItemSpan(child, ForColumns); | |
| 3259 auto& contextsMap = | |
| 3260 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; | |
| 3261 auto* context = contextsMap.get(span.startLine()); | |
| 3262 DCHECK(context); | |
| 3263 ItemPosition align = isColumnAxisBaseline | |
| 3264 ? alignSelfForChild(child).position() | |
| 3265 : justifySelfForChild(child).position(); | |
| 3266 return context->getSharedGroup(child, align); | |
| 3267 } | |
| 3268 | |
| 3269 LayoutUnit LayoutGrid::marginOverForChild(const LayoutBox& child, | |
| 3270 GridAxis axis) const { | |
| 3271 return isHorizontalGridAxis(axis) ? child.marginRight() : child.marginTop(); | |
| 3272 } | |
| 3273 | |
| 3274 LayoutUnit LayoutGrid::logicalAscentForChild(const LayoutBox& child, | |
| 3275 GridAxis baselineAxis) const { | |
| 3276 LayoutUnit ascent = ascentForChild(child, baselineAxis); | |
| 3277 return isDescentBaselineForChild(child, baselineAxis) | |
| 3278 ? descentForChild(child, ascent, baselineAxis) | |
| 3279 : ascent; | |
| 3280 } | |
| 3281 | |
| 3282 LayoutUnit LayoutGrid::ascentForChild(const LayoutBox& child, | |
| 3283 GridAxis baselineAxis) const { | |
| 3284 int baseline = isParallelToBlockAxisForChild(child, baselineAxis) | |
| 3285 ? child.firstLineBoxBaseline() | |
| 3286 : -1; | |
| 3287 // We take border-box's bottom if no valid baseline. | |
| 3288 if (baseline == -1) { | |
| 3289 baseline = isHorizontalGridAxis(baselineAxis) | |
| 3290 ? child.size().width().toInt() | |
| 3291 : child.size().height().toInt(); | |
| 3292 } | |
| 3293 return LayoutUnit(baseline) + marginOverForChild(child, baselineAxis); | |
| 3294 } | |
| 3295 | |
| 3296 LayoutUnit LayoutGrid::descentForChild(const LayoutBox& child, | |
| 3297 LayoutUnit ascent, | |
| 3298 GridAxis baselineAxis) const { | |
| 3299 if (isParallelToBlockAxisForChild(child, baselineAxis)) | |
| 3300 return child.marginLogicalHeight() + child.logicalHeight() - ascent; | |
| 3301 return child.marginLogicalWidth() + child.logicalWidth() - ascent; | |
| 3302 } | |
| 3303 | |
| 3304 bool LayoutGrid::isBaselineContextComputed(GridAxis baselineAxis) const { | |
| 3305 return baselineAxis == GridColumnAxis ? !m_rowAxisAlignmentContext.isEmpty() | |
| 3306 : !m_colAxisAlignmentContext.isEmpty(); | |
| 3307 } | |
| 3308 | |
| 3309 bool LayoutGrid::baselineMayAffectIntrinsicWidth() const { | |
| 3310 if (!styleRef().logicalWidth().isIntrinsicOrAuto()) | |
| 3311 return false; | |
| 3312 for (const auto& context : m_colAxisAlignmentContext) { | |
| 3313 for (const auto& group : context.value->sharedGroups()) { | |
| 3314 if (group.size() > 1) | |
| 3315 return true; | |
| 3316 } | |
| 3317 } | |
| 3318 return false; | |
| 3319 } | |
| 3320 | |
| 3321 bool LayoutGrid::baselineMayAffectIntrinsicHeight() const { | |
| 3322 if (!styleRef().logicalHeight().isIntrinsicOrAuto()) | |
| 3323 return false; | |
| 3324 for (const auto& context : m_rowAxisAlignmentContext) { | |
| 3325 for (const auto& group : context.value->sharedGroups()) { | |
| 3326 if (group.size() > 1) | |
| 3327 return true; | |
| 3328 } | |
| 3329 } | |
| 3330 return false; | |
| 3331 } | |
| 3332 | |
| 3333 void LayoutGrid::computeBaselineAlignmentContext(GridSizingData& sizingData) { | |
| 3334 for (auto* child = firstInFlowChildBox(); child; | |
| 3335 child = child->nextInFlowSiblingBox()) { | |
| 3336 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridRowAxis); | |
| 3337 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridColumnAxis); | |
| 3338 } | |
| 3339 } | |
| 3340 | |
| 3341 void LayoutGrid::updateBaselineAlignmentContextIfNeeded( | |
| 3342 LayoutBox& child, | |
| 3343 GridSizingData& sizingData, | |
| 3344 GridAxis baselineAxis) { | |
| 3345 DCHECK_EQ(sizingData.sizingOperation, TrackSizing); | |
| 3346 if (!isBaselineAlignmentForChild(child, baselineAxis)) | |
| 3347 return; | |
| 3348 | |
| 3349 child.layoutIfNeeded(); | |
| 3350 | |
| 3351 // Determine Ascent and Descent values of this child with respect to | |
| 3352 // its grid container. | |
| 3353 LayoutUnit ascent = ascentForChild(child, baselineAxis); | |
| 3354 LayoutUnit descent = descentForChild(child, ascent, baselineAxis); | |
| 3355 if (isDescentBaselineForChild(child, baselineAxis)) | |
| 3356 std::swap(ascent, descent); | |
| 3357 | |
| 3358 // Looking up for a shared alignment context perpendicular to the | |
| 3359 // baseline axis. | |
| 3360 auto& grid = sizingData.grid(); | |
| 3361 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; | |
| 3362 bool isRowAxisContext = isColumnAxisBaseline; | |
| 3363 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) | |
| 3364 : grid.gridItemSpan(child, ForColumns); | |
| 3365 auto& contextsMap = | |
| 3366 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; | |
| 3367 auto addResult = contextsMap.add(span.startLine(), nullptr); | |
| 3368 | |
| 3369 // Looking for a compatible baseline-sharing group. | |
| 3370 ItemPosition align = isColumnAxisBaseline | |
| 3371 ? alignSelfForChild(child).position() | |
| 3372 : justifySelfForChild(child).position(); | |
| 3373 if (addResult.isNewEntry) { | |
| 3374 addResult.storedValue->value = | |
| 3375 WTF::makeUnique<BaselineContext>(child, align, ascent, descent); | |
| 3376 } else { | |
| 3377 auto* context = addResult.storedValue->value.get(); | |
| 3378 context->updateSharedGroup(child, align, ascent, descent); | |
| 3379 } | |
| 3380 } | |
| 3381 | |
| 3382 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild( | |
| 3383 const LayoutBox& child, | |
| 3384 const GridSizingData& sizingData) const { | |
| 3385 if (!isBaselineAlignmentForChild(child, GridColumnAxis)) | |
| 3386 return LayoutUnit(); | |
| 3387 auto& group = getBaselineGroupForChild(child, sizingData, GridColumnAxis); | |
| 3388 if (group.size() > 1) | |
| 3389 return group.maxAscent() - logicalAscentForChild(child, GridColumnAxis); | |
| 3390 return LayoutUnit(); | |
| 3391 } | |
| 3392 | |
| 3393 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild( | |
| 3394 const LayoutBox& child, | |
| 3395 const GridSizingData& sizingData) const { | |
| 3396 if (!isBaselineAlignmentForChild(child, GridRowAxis)) | |
| 3397 return LayoutUnit(); | |
| 3398 auto& group = getBaselineGroupForChild(child, sizingData, GridRowAxis); | |
| 3399 if (group.size() > 1) | |
| 3400 return group.maxAscent() - logicalAscentForChild(child, GridRowAxis); | |
| 3401 return LayoutUnit(); | |
| 3402 } | |
| 3403 | |
| 3175 GridAxisPosition LayoutGrid::columnAxisPositionForChild( | 3404 GridAxisPosition LayoutGrid::columnAxisPositionForChild( |
| 3176 const LayoutBox& child) const { | 3405 const LayoutBox& child) const { |
| 3177 bool hasSameWritingMode = | 3406 bool hasSameWritingMode = |
| 3178 child.styleRef().getWritingMode() == styleRef().getWritingMode(); | 3407 child.styleRef().getWritingMode() == styleRef().getWritingMode(); |
| 3179 bool childIsLTR = child.styleRef().isLeftToRightDirection(); | 3408 bool childIsLTR = child.styleRef().isLeftToRightDirection(); |
| 3180 | 3409 |
| 3181 switch (alignSelfForChild(child).position()) { | 3410 switch (alignSelfForChild(child).position()) { |
| 3182 case ItemPositionSelfStart: | 3411 case ItemPositionSelfStart: |
| 3183 // TODO (lajava): Should we implement this logic in a generic utility | 3412 // TODO (lajava): Should we implement this logic in a generic utility |
| 3184 // function? | 3413 // function? |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3234 // Only used in flex layout, otherwise equivalent to 'end'. | 3463 // Only used in flex layout, otherwise equivalent to 'end'. |
| 3235 case ItemPositionFlexEnd: | 3464 case ItemPositionFlexEnd: |
| 3236 // Aligns the alignment subject to be flush with the alignment container's | 3465 // Aligns the alignment subject to be flush with the alignment container's |
| 3237 // 'end' edge (block-end) in the column axis. | 3466 // 'end' edge (block-end) in the column axis. |
| 3238 case ItemPositionEnd: | 3467 case ItemPositionEnd: |
| 3239 return GridAxisEnd; | 3468 return GridAxisEnd; |
| 3240 case ItemPositionStretch: | 3469 case ItemPositionStretch: |
| 3241 return GridAxisStart; | 3470 return GridAxisStart; |
| 3242 case ItemPositionBaseline: | 3471 case ItemPositionBaseline: |
| 3243 case ItemPositionLastBaseline: | 3472 case ItemPositionLastBaseline: |
| 3244 // FIXME: These two require implementing Baseline Alignment. For now, we | |
| 3245 // always 'start' align the child. crbug.com/234191 | |
| 3246 return GridAxisStart; | 3473 return GridAxisStart; |
| 3247 case ItemPositionAuto: | 3474 case ItemPositionAuto: |
| 3248 case ItemPositionNormal: | 3475 case ItemPositionNormal: |
| 3249 break; | 3476 break; |
| 3250 } | 3477 } |
| 3251 | 3478 |
| 3252 ASSERT_NOT_REACHED(); | 3479 ASSERT_NOT_REACHED(); |
| 3253 return GridAxisStart; | 3480 return GridAxisStart; |
| 3254 } | 3481 } |
| 3255 | 3482 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3313 // Only used in flex layout, otherwise equivalent to 'end'. | 3540 // Only used in flex layout, otherwise equivalent to 'end'. |
| 3314 case ItemPositionFlexEnd: | 3541 case ItemPositionFlexEnd: |
| 3315 // Aligns the alignment subject to be flush with the alignment container's | 3542 // Aligns the alignment subject to be flush with the alignment container's |
| 3316 // 'end' edge (inline-end) in the row axis. | 3543 // 'end' edge (inline-end) in the row axis. |
| 3317 case ItemPositionEnd: | 3544 case ItemPositionEnd: |
| 3318 return GridAxisEnd; | 3545 return GridAxisEnd; |
| 3319 case ItemPositionStretch: | 3546 case ItemPositionStretch: |
| 3320 return GridAxisStart; | 3547 return GridAxisStart; |
| 3321 case ItemPositionBaseline: | 3548 case ItemPositionBaseline: |
| 3322 case ItemPositionLastBaseline: | 3549 case ItemPositionLastBaseline: |
| 3323 // FIXME: These two require implementing Baseline Alignment. For now, we | |
| 3324 // always 'start' align the child. crbug.com/234191 | |
| 3325 return GridAxisStart; | 3550 return GridAxisStart; |
| 3326 case ItemPositionAuto: | 3551 case ItemPositionAuto: |
| 3327 case ItemPositionNormal: | 3552 case ItemPositionNormal: |
| 3328 break; | 3553 break; |
| 3329 } | 3554 } |
| 3330 | 3555 |
| 3331 ASSERT_NOT_REACHED(); | 3556 ASSERT_NOT_REACHED(); |
| 3332 return GridAxisStart; | 3557 return GridAxisStart; |
| 3333 } | 3558 } |
| 3334 | 3559 |
| 3335 LayoutUnit LayoutGrid::columnAxisOffsetForChild( | 3560 LayoutUnit LayoutGrid::columnAxisOffsetForChild( |
| 3336 const LayoutBox& child, | 3561 const LayoutBox& child, |
| 3337 GridSizingData& sizingData) const { | 3562 GridSizingData& sizingData) const { |
| 3338 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows); | 3563 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows); |
| 3339 size_t childStartLine = rowsSpan.startLine(); | 3564 size_t childStartLine = rowsSpan.startLine(); |
| 3340 LayoutUnit startOfRow = m_rowPositions[childStartLine]; | 3565 LayoutUnit startOfRow = m_rowPositions[childStartLine]; |
| 3341 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 3566 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
| 3342 if (hasAutoMarginsInColumnAxis(child)) | 3567 if (hasAutoMarginsInColumnAxis(child)) |
| 3343 return startPosition; | 3568 return startPosition; |
| 3344 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 3569 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
| 3345 switch (axisPosition) { | 3570 switch (axisPosition) { |
| 3346 case GridAxisStart: | 3571 case GridAxisStart: |
| 3347 return startPosition; | 3572 return startPosition + |
| 3573 columnAxisBaselineOffsetForChild(child, sizingData); | |
|
svillar
2017/02/09 13:10:09
Maybe this is an stupid question, but why just on
jfernandez
2017/02/09 14:16:03
because 'baseline' value is managed as 'start', in
| |
| 3348 case GridAxisEnd: | 3574 case GridAxisEnd: |
| 3349 case GridAxisCenter: { | 3575 case GridAxisCenter: { |
| 3350 size_t childEndLine = rowsSpan.endLine(); | 3576 size_t childEndLine = rowsSpan.endLine(); |
| 3351 LayoutUnit endOfRow = m_rowPositions[childEndLine]; | 3577 LayoutUnit endOfRow = m_rowPositions[childEndLine]; |
| 3352 // m_rowPositions include distribution offset (because of content | 3578 // m_rowPositions include distribution offset (because of content |
| 3353 // alignment) and gutters so we need to subtract them to get the actual | 3579 // alignment) and gutters so we need to subtract them to get the actual |
| 3354 // end position for a given row (this does not have to be done for the | 3580 // end position for a given row (this does not have to be done for the |
| 3355 // last track as there are no more m_columnPositions after it). | 3581 // last track as there are no more m_columnPositions after it). |
| 3356 LayoutUnit trackGap = | 3582 LayoutUnit trackGap = |
| 3357 gridGapForDirection(ForRows, sizingData.sizingOperation); | 3583 gridGapForDirection(ForRows, sizingData.sizingOperation); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 3381 const GridSpan& columnsSpan = | 3607 const GridSpan& columnsSpan = |
| 3382 sizingData.grid().gridItemSpan(child, ForColumns); | 3608 sizingData.grid().gridItemSpan(child, ForColumns); |
| 3383 size_t childStartLine = columnsSpan.startLine(); | 3609 size_t childStartLine = columnsSpan.startLine(); |
| 3384 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; | 3610 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; |
| 3385 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 3611 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
| 3386 if (hasAutoMarginsInRowAxis(child)) | 3612 if (hasAutoMarginsInRowAxis(child)) |
| 3387 return startPosition; | 3613 return startPosition; |
| 3388 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 3614 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
| 3389 switch (axisPosition) { | 3615 switch (axisPosition) { |
| 3390 case GridAxisStart: | 3616 case GridAxisStart: |
| 3391 return startPosition; | 3617 return startPosition + rowAxisBaselineOffsetForChild(child, sizingData); |
| 3392 case GridAxisEnd: | 3618 case GridAxisEnd: |
| 3393 case GridAxisCenter: { | 3619 case GridAxisCenter: { |
| 3394 size_t childEndLine = columnsSpan.endLine(); | 3620 size_t childEndLine = columnsSpan.endLine(); |
| 3395 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; | 3621 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; |
| 3396 // m_columnPositions include distribution offset (because of content | 3622 // m_columnPositions include distribution offset (because of content |
| 3397 // alignment) and gutters so we need to subtract them to get the actual | 3623 // alignment) and gutters so we need to subtract them to get the actual |
| 3398 // end position for a given column (this does not have to be done for the | 3624 // end position for a given column (this does not have to be done for the |
| 3399 // last track as there are no more m_columnPositions after it). | 3625 // last track as there are no more m_columnPositions after it). |
| 3400 LayoutUnit trackGap = | 3626 LayoutUnit trackGap = |
| 3401 gridGapForDirection(ForColumns, sizingData.sizingOperation); | 3627 gridGapForDirection(ForColumns, sizingData.sizingOperation); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3618 if (direction == ForRows) | 3844 if (direction == ForRows) |
| 3619 return grid.numTracks(ForRows); | 3845 return grid.numTracks(ForRows); |
| 3620 | 3846 |
| 3621 return grid.numTracks(ForRows) | 3847 return grid.numTracks(ForRows) |
| 3622 ? grid.numTracks(ForColumns) | 3848 ? grid.numTracks(ForColumns) |
| 3623 : GridPositionsResolver::explicitGridColumnCount( | 3849 : GridPositionsResolver::explicitGridColumnCount( |
| 3624 styleRef(), grid.autoRepeatTracks(ForColumns)); | 3850 styleRef(), grid.autoRepeatTracks(ForColumns)); |
| 3625 } | 3851 } |
| 3626 | 3852 |
| 3627 } // namespace blink | 3853 } // namespace blink |
| OLD | NEW |