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

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: Update intrinsic size and compute baseline after step 2 to deal with percentage items. 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutGrid.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutGrid.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698