Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutGrid.cpp

Issue 1407633003: [css-grid] Implementation of Baseline Self-Alignment (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Get advantage of recomputing the intrinsic size to solve the issues with orthogonal flows. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698