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 hasAnyOrthogonal = sizingData.grid().hasAnyOrthogonalGridItem(); |
| 598 |
| 599 bool intrinsicWidthMayHaveChanged = |
| 600 baselineAffectIntrinsicWidth || hasAnyOrthogonal; |
| 601 if (!intrinsicWidthMayHaveChanged && !baselineAffectIntrinsicHeight) |
| 602 return; |
| 603 |
| 604 // Compute again the intrinsic size if baseline changed item's min-content |
| 605 // contribution. |
| 606 if (intrinsicWidthMayHaveChanged) { |
| 607 if (hasAnyOrthogonal) { |
| 608 for (auto* child = firstInFlowChildBox(); child; |
| 609 child = child->nextInFlowSiblingBox()) { |
| 610 if (isOrthogonalChild(*child) && |
| 611 updateOverrideContainingBlockContentSizeForChild(*child, ForRows, |
| 612 sizingData)) |
| 613 child->forceLayout(); |
| 614 } |
| 615 } |
| 616 setPreferredLogicalWidthsDirty(MarkContainerChain); |
| 617 updateLogicalWidth(); |
| 618 availableSpaceForColumns = availableLogicalWidth(); |
| 619 } |
| 620 |
589 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns | 621 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns |
590 // and rows, to determine the final values. | 622 // and rows, to determine the final values. |
591 // TODO (lajava): orthogonal flows is just one of the cases which may require | 623 // 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 | 624 // 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 | 625 // 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 | 626 // more specific condition to detect whether child's min-content contribution |
595 // has changed or not. | 627 // has changed or not. |
596 if (sizingData.grid().hasAnyOrthogonalGridItem()) { | 628 computeTrackSizesForDefiniteSize(ForColumns, sizingData, |
597 computeTrackSizesForDefiniteSize(ForColumns, sizingData, | 629 availableSpaceForColumns); |
598 availableSpaceForColumns); | 630 computeTrackSizesForDefiniteSize(ForRows, sizingData, availableSpaceForRows); |
599 computeTrackSizesForDefiniteSize(ForRows, sizingData, | 631 |
600 availableSpaceForRows); | 632 if (baselineAffectIntrinsicHeight) { |
| 633 setLogicalHeight(computeTrackBasedLogicalHeight(sizingData) + |
| 634 borderAndPaddingLogicalHeight() + |
| 635 scrollbarLogicalHeight()); |
601 } | 636 } |
602 } | 637 } |
603 | 638 |
604 void LayoutGrid::layoutBlock(bool relayoutChildren) { | 639 void LayoutGrid::layoutBlock(bool relayoutChildren) { |
605 ASSERT(needsLayout()); | 640 ASSERT(needsLayout()); |
606 | 641 |
607 // We cannot perform a simplifiedLayout() on a dirty grid that | 642 // We cannot perform a simplifiedLayout() on a dirty grid that |
608 // has positioned items to be laid out. | 643 // has positioned items to be laid out. |
609 if (!relayoutChildren && | 644 if (!relayoutChildren && |
610 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && | 645 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && |
611 simplifiedLayout()) | 646 simplifiedLayout()) |
612 return; | 647 return; |
613 | 648 |
| 649 m_rowAxisAlignmentContext.clear(); |
| 650 m_colAxisAlignmentContext.clear(); |
| 651 |
614 SubtreeLayoutScope layoutScope(*this); | 652 SubtreeLayoutScope layoutScope(*this); |
615 | 653 |
616 { | 654 { |
617 // LayoutState needs this deliberate scope to pop before updating scroll | 655 // LayoutState needs this deliberate scope to pop before updating scroll |
618 // information (which may trigger relayout). | 656 // information (which may trigger relayout). |
619 LayoutState state(*this); | 657 LayoutState state(*this); |
620 | 658 |
621 LayoutSize previousSize = size(); | 659 LayoutSize previousSize = size(); |
622 | 660 |
623 // We need to clear both own and containingBlock override sizes to | 661 // 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); | 712 setLogicalHeight(trackBasedLogicalHeight); |
675 | 713 |
676 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); | 714 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); |
677 updateLogicalHeight(); | 715 updateLogicalHeight(); |
678 | 716 |
679 // Once grid's indefinite height is resolved, we can compute the | 717 // Once grid's indefinite height is resolved, we can compute the |
680 // available free space for Content Alignment. | 718 // available free space for Content Alignment. |
681 if (!cachedHasDefiniteLogicalHeight()) | 719 if (!cachedHasDefiniteLogicalHeight()) |
682 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; | 720 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; |
683 | 721 |
| 722 // TODO (lajava): We need to compute baselines after step 2 so |
| 723 // items with a relative size (percentages) can resolve it before |
| 724 // determining its baseline. However, we only set item's grid area |
| 725 // (via override sizes) as part of the content-sized tracks sizing |
| 726 // logic. Hence, items located at fixed or flexible tracks can't |
| 727 // resolve correctly their size at this stage, which may lead to |
| 728 // an incorrect computation of their shared context's baseline. |
| 729 computeBaselineAlignmentContext(sizingData); |
| 730 |
684 // 3- If the min-content contribution of any grid items have changed based | 731 // 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 | 732 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with |
686 // the new min-content contribution (once only). | 733 // the new min-content contribution (once only). |
687 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, | 734 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, |
688 contentLogicalHeight()); | 735 contentLogicalHeight()); |
689 | 736 |
690 // Grid container should have the minimum height of a line if it's editable. | 737 // Grid container should have the minimum height of a line if it's editable. |
691 // That doesn't affect track sizing though. | 738 // That doesn't affect track sizing though. |
692 if (hasLineIfEmpty()) | 739 if (hasLineIfEmpty()) |
693 setLogicalHeight( | 740 setLogicalHeight( |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 LayoutUnit(-1)); | 1364 LayoutUnit(-1)); |
1318 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1365 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
1319 } | 1366 } |
1320 | 1367 |
1321 // We need to clear the stretched height to properly compute logical height | 1368 // We need to clear the stretched height to properly compute logical height |
1322 // during layout. | 1369 // during layout. |
1323 if (child.needsLayout()) | 1370 if (child.needsLayout()) |
1324 child.clearOverrideLogicalContentHeight(); | 1371 child.clearOverrideLogicalContentHeight(); |
1325 | 1372 |
1326 child.layoutIfNeeded(); | 1373 child.layoutIfNeeded(); |
| 1374 GridAxis baselineAxis = |
| 1375 isOrthogonalChild(child) ? GridRowAxis : GridColumnAxis; |
| 1376 if (isBaselineAlignmentForChild(child, baselineAxis) && |
| 1377 isBaselineContextComputed(baselineAxis)) { |
| 1378 auto& group = getBaselineGroupForChild(child, sizingData, baselineAxis); |
| 1379 return group.maxAscent() + group.maxDescent(); |
| 1380 } |
1327 return child.logicalHeight() + child.marginLogicalHeight(); | 1381 return child.logicalHeight() + child.marginLogicalHeight(); |
1328 } | 1382 } |
1329 | 1383 |
1330 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( | 1384 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( |
1331 const LayoutBox& child, | 1385 const LayoutBox& child, |
1332 GridTrackSizingDirection direction) const { | 1386 GridTrackSizingDirection direction) const { |
1333 return !isOrthogonalChild(child) | 1387 return !isOrthogonalChild(child) |
1334 ? direction | 1388 ? direction |
1335 : (direction == ForColumns ? ForRows : ForColumns); | 1389 : (direction == ForColumns ? ForRows : ForColumns); |
1336 } | 1390 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 | 1474 |
1421 // All orthogonal flow boxes were already laid out during an early layout | 1475 // All orthogonal flow boxes were already laid out during an early layout |
1422 // phase performed in FrameView::performLayout. | 1476 // phase performed in FrameView::performLayout. |
1423 // It's true that grid track sizing was not completed at that time and it may | 1477 // 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 | 1478 // 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 | 1479 // perform a layout during intrinsic width computation, we have to use that |
1426 // computed height for now. | 1480 // computed height for now. |
1427 if (direction == ForColumns && | 1481 if (direction == ForColumns && |
1428 sizingData.sizingOperation == IntrinsicSizeComputation) { | 1482 sizingData.sizingOperation == IntrinsicSizeComputation) { |
1429 DCHECK(isOrthogonalChild(child)); | 1483 DCHECK(isOrthogonalChild(child)); |
| 1484 if (isBaselineAlignmentForChild(child, GridRowAxis) && |
| 1485 isBaselineContextComputed(GridRowAxis)) { |
| 1486 auto& group = getBaselineGroupForChild(child, sizingData, GridRowAxis); |
| 1487 return group.maxAscent() + group.maxDescent(); |
| 1488 } |
1430 return child.logicalHeight() + child.marginLogicalHeight(); | 1489 return child.logicalHeight() + child.marginLogicalHeight(); |
1431 } | 1490 } |
1432 | 1491 |
1433 if (updateOverrideContainingBlockContentSizeForChild( | 1492 if (updateOverrideContainingBlockContentSizeForChild( |
1434 child, childInlineDirection, sizingData)) | 1493 child, childInlineDirection, sizingData)) |
1435 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1494 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
1436 return logicalHeightForChild(child, sizingData); | 1495 return logicalHeightForChild(child, sizingData); |
1437 } | 1496 } |
1438 | 1497 |
1439 DISABLE_CFI_PERF | 1498 DISABLE_CFI_PERF |
(...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3082 .toInt(); | 3141 .toInt(); |
3083 } | 3142 } |
3084 | 3143 |
3085 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, | 3144 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, |
3086 LineDirectionMode direction) { | 3145 LineDirectionMode direction) { |
3087 return (direction == HorizontalLine ? box.size().height() | 3146 return (direction == HorizontalLine ? box.size().height() |
3088 : box.size().width()) | 3147 : box.size().width()) |
3089 .toInt(); | 3148 .toInt(); |
3090 } | 3149 } |
3091 | 3150 |
3092 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be | |
3093 // refactored somehow. | |
3094 int LayoutGrid::baselinePosition(FontBaseline, | 3151 int LayoutGrid::baselinePosition(FontBaseline, |
3095 bool, | 3152 bool, |
3096 LineDirectionMode direction, | 3153 LineDirectionMode direction, |
3097 LinePositionMode mode) const { | 3154 LinePositionMode mode) const { |
3098 DCHECK_EQ(mode, PositionOnContainingLine); | 3155 DCHECK_EQ(mode, PositionOnContainingLine); |
3099 int baseline = firstLineBoxBaseline(); | 3156 int baseline = firstLineBoxBaseline(); |
3100 // We take content-box's bottom if no valid baseline. | 3157 // We take content-box's bottom if no valid baseline. |
3101 if (baseline == -1) | 3158 if (baseline == -1) |
3102 baseline = synthesizedBaselineFromContentBox(*this, direction); | 3159 baseline = synthesizedBaselineFromContentBox(*this, direction); |
3103 | 3160 |
3104 return baseline + beforeMarginInLineDirection(direction); | 3161 return baseline + beforeMarginInLineDirection(direction); |
3105 } | 3162 } |
3106 | 3163 |
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 { | 3164 int LayoutGrid::firstLineBoxBaseline() const { |
3113 if (isWritingModeRoot() || !m_grid.hasGridItems()) | 3165 if (isWritingModeRoot() || !m_grid.hasGridItems()) |
3114 return -1; | 3166 return -1; |
3115 const LayoutBox* baselineChild = nullptr; | 3167 const LayoutBox* baselineChild = nullptr; |
3116 const LayoutBox* firstChild = nullptr; | 3168 const LayoutBox* firstChild = nullptr; |
3117 bool isBaselineAligned = false; | 3169 bool isBaselineAligned = false; |
3118 // Finding the first grid item in grid order. | 3170 // Finding the first grid item in grid order. |
3119 for (size_t column = 0; | 3171 for (size_t column = 0; |
3120 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { | 3172 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { |
3121 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { | 3173 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { |
3122 const LayoutBox* child = m_grid.cell(0, column)[index]; | 3174 const LayoutBox* child = m_grid.cell(0, column)[index]; |
3123 DCHECK(!child->isOutOfFlowPositioned()); | 3175 DCHECK(!child->isOutOfFlowPositioned()); |
3124 // If an item participates in baseline alignmen, we select such item. | 3176 // If an item participates in baseline alignment, we select such item. |
3125 if (isInlineBaselineAlignedChild(child)) { | 3177 if (isBaselineAlignmentForChild(*child)) { |
3126 // TODO (lajava): self-baseline and content-baseline alignment | 3178 // TODO (lajava): self-baseline and content-baseline alignment |
3127 // still not implemented. | 3179 // still not implemented. |
3128 baselineChild = child; | 3180 baselineChild = child; |
3129 isBaselineAligned = true; | 3181 isBaselineAligned = true; |
3130 break; | 3182 break; |
3131 } | 3183 } |
3132 if (!baselineChild) { | 3184 if (!baselineChild) { |
3133 // Use dom order for items in the same cell. | 3185 // Use dom order for items in the same cell. |
3134 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < | 3186 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < |
3135 m_grid.gridItemPaintOrder(*firstChild))) | 3187 m_grid.gridItemPaintOrder(*firstChild))) |
(...skipping 29 matching lines...) Expand all Loading... |
3165 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { | 3217 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { |
3166 int baseline = firstLineBoxBaseline(); | 3218 int baseline = firstLineBoxBaseline(); |
3167 if (baseline != -1) | 3219 if (baseline != -1) |
3168 return baseline; | 3220 return baseline; |
3169 | 3221 |
3170 int marginHeight = | 3222 int marginHeight = |
3171 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); | 3223 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); |
3172 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; | 3224 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; |
3173 } | 3225 } |
3174 | 3226 |
| 3227 bool LayoutGrid::isHorizontalGridAxis(GridAxis axis) const { |
| 3228 return axis == GridRowAxis ? isHorizontalWritingMode() |
| 3229 : !isHorizontalWritingMode(); |
| 3230 } |
| 3231 |
| 3232 bool LayoutGrid::isParallelToBlockAxisForChild(const LayoutBox& child, |
| 3233 GridAxis axis) const { |
| 3234 return axis == GridColumnAxis ? !isOrthogonalChild(child) |
| 3235 : isOrthogonalChild(child); |
| 3236 } |
| 3237 |
| 3238 bool LayoutGrid::isDescentBaselineForChild(const LayoutBox& child, |
| 3239 GridAxis baselineAxis) const { |
| 3240 return isHorizontalGridAxis(baselineAxis) && |
| 3241 !styleRef().isFlippedBlocksWritingMode(); |
| 3242 } |
| 3243 |
| 3244 bool LayoutGrid::isBaselineAlignmentForChild(const LayoutBox& child, |
| 3245 GridAxis baselineAxis) const { |
| 3246 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 3247 ItemPosition align = isColumnAxisBaseline |
| 3248 ? alignSelfForChild(child).position() |
| 3249 : justifySelfForChild(child).position(); |
| 3250 bool hasAutoMargins = isColumnAxisBaseline ? hasAutoMarginsInColumnAxis(child) |
| 3251 : hasAutoMarginsInRowAxis(child); |
| 3252 return isBaselinePosition(align) && !hasAutoMargins; |
| 3253 } |
| 3254 |
| 3255 const BaselineGroup& LayoutGrid::getBaselineGroupForChild( |
| 3256 const LayoutBox& child, |
| 3257 const GridSizingData& sizingData, |
| 3258 GridAxis baselineAxis) const { |
| 3259 DCHECK(isBaselineAlignmentForChild(child, baselineAxis)); |
| 3260 auto& grid = sizingData.grid(); |
| 3261 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 3262 bool isRowAxisContext = isColumnAxisBaseline; |
| 3263 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) |
| 3264 : grid.gridItemSpan(child, ForColumns); |
| 3265 auto& contextsMap = |
| 3266 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; |
| 3267 auto* context = contextsMap.get(span.startLine()); |
| 3268 DCHECK(context); |
| 3269 ItemPosition align = isColumnAxisBaseline |
| 3270 ? alignSelfForChild(child).position() |
| 3271 : justifySelfForChild(child).position(); |
| 3272 return context->getSharedGroup(child, align); |
| 3273 } |
| 3274 |
| 3275 LayoutUnit LayoutGrid::marginOverForChild(const LayoutBox& child, |
| 3276 GridAxis axis) const { |
| 3277 return isHorizontalGridAxis(axis) ? child.marginRight() : child.marginTop(); |
| 3278 } |
| 3279 |
| 3280 LayoutUnit LayoutGrid::logicalAscentForChild(const LayoutBox& child, |
| 3281 GridAxis baselineAxis) const { |
| 3282 LayoutUnit ascent = ascentForChild(child, baselineAxis); |
| 3283 return isDescentBaselineForChild(child, baselineAxis) |
| 3284 ? descentForChild(child, ascent, baselineAxis) |
| 3285 : ascent; |
| 3286 } |
| 3287 |
| 3288 LayoutUnit LayoutGrid::ascentForChild(const LayoutBox& child, |
| 3289 GridAxis baselineAxis) const { |
| 3290 int baseline = isParallelToBlockAxisForChild(child, baselineAxis) |
| 3291 ? child.firstLineBoxBaseline() |
| 3292 : -1; |
| 3293 // We take border-box's bottom if no valid baseline. |
| 3294 if (baseline == -1) { |
| 3295 baseline = isHorizontalGridAxis(baselineAxis) |
| 3296 ? child.size().width().toInt() |
| 3297 : child.size().height().toInt(); |
| 3298 } |
| 3299 return LayoutUnit(baseline) + marginOverForChild(child, baselineAxis); |
| 3300 } |
| 3301 |
| 3302 LayoutUnit LayoutGrid::descentForChild(const LayoutBox& child, |
| 3303 LayoutUnit ascent, |
| 3304 GridAxis baselineAxis) const { |
| 3305 if (isParallelToBlockAxisForChild(child, baselineAxis)) |
| 3306 return child.marginLogicalHeight() + child.logicalHeight() - ascent; |
| 3307 return child.marginLogicalWidth() + child.logicalWidth() - ascent; |
| 3308 } |
| 3309 |
| 3310 bool LayoutGrid::isBaselineContextComputed(GridAxis baselineAxis) const { |
| 3311 return baselineAxis == GridColumnAxis ? !m_rowAxisAlignmentContext.isEmpty() |
| 3312 : !m_colAxisAlignmentContext.isEmpty(); |
| 3313 } |
| 3314 |
| 3315 bool LayoutGrid::baselineMayAffectIntrinsicWidth() const { |
| 3316 if (!styleRef().logicalWidth().isIntrinsicOrAuto()) |
| 3317 return false; |
| 3318 for (const auto& context : m_colAxisAlignmentContext) { |
| 3319 for (const auto& group : context.value->sharedGroups()) { |
| 3320 if (group.size() > 1) |
| 3321 return true; |
| 3322 } |
| 3323 } |
| 3324 return false; |
| 3325 } |
| 3326 |
| 3327 bool LayoutGrid::baselineMayAffectIntrinsicHeight() const { |
| 3328 if (!styleRef().logicalHeight().isIntrinsicOrAuto()) |
| 3329 return false; |
| 3330 for (const auto& context : m_rowAxisAlignmentContext) { |
| 3331 for (const auto& group : context.value->sharedGroups()) { |
| 3332 if (group.size() > 1) |
| 3333 return true; |
| 3334 } |
| 3335 } |
| 3336 return false; |
| 3337 } |
| 3338 |
| 3339 void LayoutGrid::computeBaselineAlignmentContext(GridSizingData& sizingData) { |
| 3340 for (auto* child = firstInFlowChildBox(); child; |
| 3341 child = child->nextInFlowSiblingBox()) { |
| 3342 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridRowAxis); |
| 3343 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridColumnAxis); |
| 3344 } |
| 3345 } |
| 3346 |
| 3347 void LayoutGrid::updateBaselineAlignmentContextIfNeeded( |
| 3348 LayoutBox& child, |
| 3349 GridSizingData& sizingData, |
| 3350 GridAxis baselineAxis) { |
| 3351 DCHECK_EQ(sizingData.sizingOperation, TrackSizing); |
| 3352 if (!isBaselineAlignmentForChild(child, baselineAxis)) |
| 3353 return; |
| 3354 |
| 3355 child.layoutIfNeeded(); |
| 3356 |
| 3357 // Determine Ascent and Descent values of this child with respect to |
| 3358 // its grid container. |
| 3359 LayoutUnit ascent = ascentForChild(child, baselineAxis); |
| 3360 LayoutUnit descent = descentForChild(child, ascent, baselineAxis); |
| 3361 if (isDescentBaselineForChild(child, baselineAxis)) |
| 3362 std::swap(ascent, descent); |
| 3363 |
| 3364 // Looking up for a shared alignment context perpendicular to the |
| 3365 // baseline axis. |
| 3366 auto& grid = sizingData.grid(); |
| 3367 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis; |
| 3368 bool isRowAxisContext = isColumnAxisBaseline; |
| 3369 const auto& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows) |
| 3370 : grid.gridItemSpan(child, ForColumns); |
| 3371 auto& contextsMap = |
| 3372 isRowAxisContext ? m_rowAxisAlignmentContext : m_colAxisAlignmentContext; |
| 3373 auto addResult = contextsMap.add(span.startLine(), nullptr); |
| 3374 |
| 3375 // Looking for a compatible baseline-sharing group. |
| 3376 ItemPosition align = isColumnAxisBaseline |
| 3377 ? alignSelfForChild(child).position() |
| 3378 : justifySelfForChild(child).position(); |
| 3379 if (addResult.isNewEntry) { |
| 3380 addResult.storedValue->value = |
| 3381 WTF::makeUnique<BaselineContext>(child, align, ascent, descent); |
| 3382 } else { |
| 3383 auto* context = addResult.storedValue->value.get(); |
| 3384 context->updateSharedGroup(child, align, ascent, descent); |
| 3385 } |
| 3386 } |
| 3387 |
| 3388 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild( |
| 3389 const LayoutBox& child, |
| 3390 const GridSizingData& sizingData) const { |
| 3391 if (!isBaselineAlignmentForChild(child, GridColumnAxis)) |
| 3392 return LayoutUnit(); |
| 3393 auto& group = getBaselineGroupForChild(child, sizingData, GridColumnAxis); |
| 3394 if (group.size() > 1) |
| 3395 return group.maxAscent() - logicalAscentForChild(child, GridColumnAxis); |
| 3396 return LayoutUnit(); |
| 3397 } |
| 3398 |
| 3399 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild( |
| 3400 const LayoutBox& child, |
| 3401 const GridSizingData& sizingData) const { |
| 3402 if (!isBaselineAlignmentForChild(child, GridRowAxis)) |
| 3403 return LayoutUnit(); |
| 3404 auto& group = getBaselineGroupForChild(child, sizingData, GridRowAxis); |
| 3405 if (group.size() > 1) |
| 3406 return group.maxAscent() - logicalAscentForChild(child, GridRowAxis); |
| 3407 return LayoutUnit(); |
| 3408 } |
| 3409 |
3175 GridAxisPosition LayoutGrid::columnAxisPositionForChild( | 3410 GridAxisPosition LayoutGrid::columnAxisPositionForChild( |
3176 const LayoutBox& child) const { | 3411 const LayoutBox& child) const { |
3177 bool hasSameWritingMode = | 3412 bool hasSameWritingMode = |
3178 child.styleRef().getWritingMode() == styleRef().getWritingMode(); | 3413 child.styleRef().getWritingMode() == styleRef().getWritingMode(); |
3179 bool childIsLTR = child.styleRef().isLeftToRightDirection(); | 3414 bool childIsLTR = child.styleRef().isLeftToRightDirection(); |
3180 | 3415 |
3181 switch (alignSelfForChild(child).position()) { | 3416 switch (alignSelfForChild(child).position()) { |
3182 case ItemPositionSelfStart: | 3417 case ItemPositionSelfStart: |
3183 // TODO (lajava): Should we implement this logic in a generic utility | 3418 // TODO (lajava): Should we implement this logic in a generic utility |
3184 // function? | 3419 // function? |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3234 // Only used in flex layout, otherwise equivalent to 'end'. | 3469 // Only used in flex layout, otherwise equivalent to 'end'. |
3235 case ItemPositionFlexEnd: | 3470 case ItemPositionFlexEnd: |
3236 // Aligns the alignment subject to be flush with the alignment container's | 3471 // Aligns the alignment subject to be flush with the alignment container's |
3237 // 'end' edge (block-end) in the column axis. | 3472 // 'end' edge (block-end) in the column axis. |
3238 case ItemPositionEnd: | 3473 case ItemPositionEnd: |
3239 return GridAxisEnd; | 3474 return GridAxisEnd; |
3240 case ItemPositionStretch: | 3475 case ItemPositionStretch: |
3241 return GridAxisStart; | 3476 return GridAxisStart; |
3242 case ItemPositionBaseline: | 3477 case ItemPositionBaseline: |
3243 case ItemPositionLastBaseline: | 3478 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; | 3479 return GridAxisStart; |
3247 case ItemPositionAuto: | 3480 case ItemPositionAuto: |
3248 case ItemPositionNormal: | 3481 case ItemPositionNormal: |
3249 break; | 3482 break; |
3250 } | 3483 } |
3251 | 3484 |
3252 ASSERT_NOT_REACHED(); | 3485 ASSERT_NOT_REACHED(); |
3253 return GridAxisStart; | 3486 return GridAxisStart; |
3254 } | 3487 } |
3255 | 3488 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3313 // Only used in flex layout, otherwise equivalent to 'end'. | 3546 // Only used in flex layout, otherwise equivalent to 'end'. |
3314 case ItemPositionFlexEnd: | 3547 case ItemPositionFlexEnd: |
3315 // Aligns the alignment subject to be flush with the alignment container's | 3548 // Aligns the alignment subject to be flush with the alignment container's |
3316 // 'end' edge (inline-end) in the row axis. | 3549 // 'end' edge (inline-end) in the row axis. |
3317 case ItemPositionEnd: | 3550 case ItemPositionEnd: |
3318 return GridAxisEnd; | 3551 return GridAxisEnd; |
3319 case ItemPositionStretch: | 3552 case ItemPositionStretch: |
3320 return GridAxisStart; | 3553 return GridAxisStart; |
3321 case ItemPositionBaseline: | 3554 case ItemPositionBaseline: |
3322 case ItemPositionLastBaseline: | 3555 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; | 3556 return GridAxisStart; |
3326 case ItemPositionAuto: | 3557 case ItemPositionAuto: |
3327 case ItemPositionNormal: | 3558 case ItemPositionNormal: |
3328 break; | 3559 break; |
3329 } | 3560 } |
3330 | 3561 |
3331 ASSERT_NOT_REACHED(); | 3562 ASSERT_NOT_REACHED(); |
3332 return GridAxisStart; | 3563 return GridAxisStart; |
3333 } | 3564 } |
3334 | 3565 |
3335 LayoutUnit LayoutGrid::columnAxisOffsetForChild( | 3566 LayoutUnit LayoutGrid::columnAxisOffsetForChild( |
3336 const LayoutBox& child, | 3567 const LayoutBox& child, |
3337 GridSizingData& sizingData) const { | 3568 GridSizingData& sizingData) const { |
3338 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows); | 3569 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows); |
3339 size_t childStartLine = rowsSpan.startLine(); | 3570 size_t childStartLine = rowsSpan.startLine(); |
3340 LayoutUnit startOfRow = m_rowPositions[childStartLine]; | 3571 LayoutUnit startOfRow = m_rowPositions[childStartLine]; |
3341 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 3572 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
3342 if (hasAutoMarginsInColumnAxis(child)) | 3573 if (hasAutoMarginsInColumnAxis(child)) |
3343 return startPosition; | 3574 return startPosition; |
3344 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 3575 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
3345 switch (axisPosition) { | 3576 switch (axisPosition) { |
3346 case GridAxisStart: | 3577 case GridAxisStart: |
3347 return startPosition; | 3578 return startPosition + |
| 3579 columnAxisBaselineOffsetForChild(child, sizingData); |
3348 case GridAxisEnd: | 3580 case GridAxisEnd: |
3349 case GridAxisCenter: { | 3581 case GridAxisCenter: { |
3350 size_t childEndLine = rowsSpan.endLine(); | 3582 size_t childEndLine = rowsSpan.endLine(); |
3351 LayoutUnit endOfRow = m_rowPositions[childEndLine]; | 3583 LayoutUnit endOfRow = m_rowPositions[childEndLine]; |
3352 // m_rowPositions include distribution offset (because of content | 3584 // m_rowPositions include distribution offset (because of content |
3353 // alignment) and gutters so we need to subtract them to get the actual | 3585 // 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 | 3586 // 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). | 3587 // last track as there are no more m_columnPositions after it). |
3356 LayoutUnit trackGap = | 3588 LayoutUnit trackGap = |
3357 gridGapForDirection(ForRows, sizingData.sizingOperation); | 3589 gridGapForDirection(ForRows, sizingData.sizingOperation); |
(...skipping 23 matching lines...) Expand all Loading... |
3381 const GridSpan& columnsSpan = | 3613 const GridSpan& columnsSpan = |
3382 sizingData.grid().gridItemSpan(child, ForColumns); | 3614 sizingData.grid().gridItemSpan(child, ForColumns); |
3383 size_t childStartLine = columnsSpan.startLine(); | 3615 size_t childStartLine = columnsSpan.startLine(); |
3384 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; | 3616 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; |
3385 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 3617 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
3386 if (hasAutoMarginsInRowAxis(child)) | 3618 if (hasAutoMarginsInRowAxis(child)) |
3387 return startPosition; | 3619 return startPosition; |
3388 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 3620 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
3389 switch (axisPosition) { | 3621 switch (axisPosition) { |
3390 case GridAxisStart: | 3622 case GridAxisStart: |
3391 return startPosition; | 3623 return startPosition + rowAxisBaselineOffsetForChild(child, sizingData); |
3392 case GridAxisEnd: | 3624 case GridAxisEnd: |
3393 case GridAxisCenter: { | 3625 case GridAxisCenter: { |
3394 size_t childEndLine = columnsSpan.endLine(); | 3626 size_t childEndLine = columnsSpan.endLine(); |
3395 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; | 3627 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; |
3396 // m_columnPositions include distribution offset (because of content | 3628 // m_columnPositions include distribution offset (because of content |
3397 // alignment) and gutters so we need to subtract them to get the actual | 3629 // 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 | 3630 // 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). | 3631 // last track as there are no more m_columnPositions after it). |
3400 LayoutUnit trackGap = | 3632 LayoutUnit trackGap = |
3401 gridGapForDirection(ForColumns, sizingData.sizingOperation); | 3633 gridGapForDirection(ForColumns, sizingData.sizingOperation); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3618 if (direction == ForRows) | 3850 if (direction == ForRows) |
3619 return grid.numTracks(ForRows); | 3851 return grid.numTracks(ForRows); |
3620 | 3852 |
3621 return grid.numTracks(ForRows) | 3853 return grid.numTracks(ForRows) |
3622 ? grid.numTracks(ForColumns) | 3854 ? grid.numTracks(ForColumns) |
3623 : GridPositionsResolver::explicitGridColumnCount( | 3855 : GridPositionsResolver::explicitGridColumnCount( |
3624 styleRef(), grid.autoRepeatTracks(ForColumns)); | 3856 styleRef(), grid.autoRepeatTracks(ForColumns)); |
3625 } | 3857 } |
3626 | 3858 |
3627 } // namespace blink | 3859 } // namespace blink |
OLD | NEW |