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

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: Patch rebased and applied several refactoring and code clean up. Created 3 years, 11 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
47 static inline bool isBaselinePosition(ItemPosition position) {
48 return position == ItemPositionBaseline ||
49 position == ItemPositionLastBaseline;
50 }
51
46 size_t LayoutGrid::Grid::numTracks(GridTrackSizingDirection direction) const { 52 size_t LayoutGrid::Grid::numTracks(GridTrackSizingDirection direction) const {
47 if (direction == ForRows) 53 if (direction == ForRows)
48 return m_grid.size(); 54 return m_grid.size();
49 return m_grid.size() ? m_grid[0].size() : 0; 55 return m_grid.size() ? m_grid[0].size() : 0;
50 } 56 }
51 57
52 void LayoutGrid::Grid::ensureGridSize(size_t maximumRowSize, 58 void LayoutGrid::Grid::ensureGridSize(size_t maximumRowSize,
53 size_t maximumColumnSize) { 59 size_t maximumColumnSize) {
54 const size_t oldRowSize = numTracks(ForRows); 60 const size_t oldRowSize = numTracks(ForRows);
55 if (maximumRowSize > oldRowSize) { 61 if (maximumRowSize > oldRowSize) {
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 ContentAlignmentData(){}; 281 ContentAlignmentData(){};
276 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) 282 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution)
277 : positionOffset(position), distributionOffset(distribution) {} 283 : positionOffset(position), distributionOffset(distribution) {}
278 284
279 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } 285 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; }
280 286
281 LayoutUnit positionOffset = LayoutUnit(-1); 287 LayoutUnit positionOffset = LayoutUnit(-1);
282 LayoutUnit distributionOffset = LayoutUnit(-1); 288 LayoutUnit distributionOffset = LayoutUnit(-1);
283 }; 289 };
284 290
291 class BaselineGroup {
292 public:
293 BaselineGroup(WritingMode blockFlow, ItemPosition childPreference)
294 : m_maxAscent(0), m_maxDescent(0), m_items() {
295 m_blockFlow = blockFlow;
296 m_preference = childPreference;
297 }
298
299 void update(const LayoutBox& child, LayoutUnit ascent, LayoutUnit descent) {
300 if (m_items.add(&child).isNewEntry) {
301 m_maxAscent = std::max(m_maxAscent, ascent);
302 m_maxDescent = std::max(m_maxDescent, descent);
303 }
304 }
305 bool isCompatible(WritingMode childBlockFlow,
306 ItemPosition childPreference) const {
307 DCHECK(isBaselinePosition(childPreference));
308 DCHECK_GT(size(), 0);
309 return ((m_blockFlow == childBlockFlow ||
310 isOrthogonalBlockFlow(childBlockFlow)) &&
311 m_preference == childPreference) ||
312 (isOppositeBlockFlow(childBlockFlow) &&
313 m_preference != childPreference);
314 }
315
316 LayoutUnit maxAscent() const { return m_maxAscent; }
317 LayoutUnit maxDescent() const { return m_maxDescent; }
318 int size() const { return m_items.size(); }
319
320 private:
321 bool isOppositeBlockFlow(WritingMode blockFlow) const {
322 switch (blockFlow) {
323 case WritingMode::kHorizontalTb:
324 return false;
325 case WritingMode::kVerticalLr:
326 return m_blockFlow == WritingMode::kVerticalRl;
327 case WritingMode::kVerticalRl:
328 return m_blockFlow == WritingMode::kVerticalLr;
329 default:
330 NOTREACHED();
331 return false;
332 }
333 }
334 bool isOrthogonalBlockFlow(WritingMode blockFlow) const {
335 switch (blockFlow) {
336 case WritingMode::kHorizontalTb:
337 return m_blockFlow != WritingMode::kHorizontalTb;
338 case WritingMode::kVerticalLr:
339 case WritingMode::kVerticalRl:
340 return m_blockFlow == WritingMode::kHorizontalTb;
341 default:
342 NOTREACHED();
343 return false;
344 }
345 }
346
347 WritingMode m_blockFlow;
348 ItemPosition m_preference;
349 LayoutUnit m_maxAscent;
350 LayoutUnit m_maxDescent;
351 HashSet<const LayoutBox*> m_items;
352 };
353
354 class BaselineContext {
355 public:
356 BaselineContext(const LayoutBox& child,
357 ItemPosition preference,
358 LayoutUnit ascent,
359 LayoutUnit descent) {
360 DCHECK(isBaselinePosition(preference));
361 updateSharedGroup(child, preference, ascent, descent);
362 }
363 const BaselineGroup& getSharedGroup(const LayoutBox& child,
364 ItemPosition preference) const {
365 DCHECK(isBaselinePosition(preference));
366 return const_cast<BaselineContext*>(this)->findCompatibleSharedGroup(
367 child, preference);
368 }
369 void updateSharedGroup(const LayoutBox& child,
370 ItemPosition preference,
371 LayoutUnit ascent,
372 LayoutUnit descent) {
373 DCHECK(isBaselinePosition(preference));
374 BaselineGroup& group = findCompatibleSharedGroup(child, preference);
375 group.update(child, ascent, descent);
376 }
377
378 private:
379 // TODO Properly implement baseline-group compatibility
380 // See https://github.com/w3c/csswg-drafts/issues/721
381 BaselineGroup& findCompatibleSharedGroup(const LayoutBox& child,
382 ItemPosition preference) {
383 WritingMode blockDirection = child.styleRef().getWritingMode();
384 for (auto& group : m_sharedGroups) {
385 if (group.isCompatible(blockDirection, preference))
386 return group;
387 }
388 m_sharedGroups.prepend(BaselineGroup(blockDirection, preference));
389 return m_sharedGroups[0];
390 }
391
392 Vector<BaselineGroup> m_sharedGroups;
393 };
svillar 2017/01/19 09:41:25 These two classes have nothing to do with Grid, th
jfernandez 2017/01/19 16:31:48 Acknowledged.
394
285 enum TrackSizeRestriction { 395 enum TrackSizeRestriction {
286 AllowInfinity, 396 AllowInfinity,
287 ForbidInfinity, 397 ForbidInfinity,
288 }; 398 };
289 399
290 class LayoutGrid::GridIterator { 400 class LayoutGrid::GridIterator {
291 WTF_MAKE_NONCOPYABLE(GridIterator); 401 WTF_MAKE_NONCOPYABLE(GridIterator);
292 402
293 public: 403 public:
294 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g 404 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 } 492 }
383 493
384 private: 494 private:
385 const GridAsMatrix& m_grid; 495 const GridAsMatrix& m_grid;
386 GridTrackSizingDirection m_direction; 496 GridTrackSizingDirection m_direction;
387 size_t m_rowIndex; 497 size_t m_rowIndex;
388 size_t m_columnIndex; 498 size_t m_columnIndex;
389 size_t m_childIndex; 499 size_t m_childIndex;
390 }; 500 };
391 501
502 typedef HashMap<unsigned,
503 std::unique_ptr<BaselineContext>,
504 DefaultHash<unsigned>::Hash,
505 WTF::UnsignedWithZeroKeyHashTraits<unsigned>>
506 BaselineContextsMap;
507
392 struct LayoutGrid::GridSizingData { 508 struct LayoutGrid::GridSizingData {
393 WTF_MAKE_NONCOPYABLE(GridSizingData); 509 WTF_MAKE_NONCOPYABLE(GridSizingData);
394 STACK_ALLOCATED(); 510 STACK_ALLOCATED();
395 511
396 public: 512 public:
397 GridSizingData(size_t gridColumnCount, size_t gridRowCount, Grid& grid) 513 GridSizingData(size_t gridColumnCount, size_t gridRowCount, Grid& grid)
398 : columnTracks(gridColumnCount), rowTracks(gridRowCount), m_grid(grid) {} 514 : columnTracks(gridColumnCount), rowTracks(gridRowCount), m_grid(grid) {}
399 515
400 Vector<GridTrack> columnTracks; 516 Vector<GridTrack> columnTracks;
401 Vector<GridTrack> rowTracks; 517 Vector<GridTrack> rowTracks;
402 Vector<size_t> contentSizedTracksIndex; 518 Vector<size_t> contentSizedTracksIndex;
403 519
520 BaselineContextsMap rowAxisAlignmentContext;
521 BaselineContextsMap colAxisAlignmentContext;
522
404 // Performance optimization: hold onto these Vectors until the end of Layout 523 // Performance optimization: hold onto these Vectors until the end of Layout
405 // to avoid repeated malloc / free. 524 // to avoid repeated malloc / free.
406 Vector<GridTrack*> filteredTracks; 525 Vector<GridTrack*> filteredTracks;
407 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; 526 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan;
408 Vector<GridTrack*> growBeyondGrowthLimitsTracks; 527 Vector<GridTrack*> growBeyondGrowthLimitsTracks;
409 528
410 LayoutUnit& freeSpace(GridTrackSizingDirection direction) { 529 LayoutUnit& freeSpace(GridTrackSizingDirection direction) {
411 return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; 530 return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows;
412 } 531 }
413 532
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 updateLogicalWidth(); 757 updateLogicalWidth();
639 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight(); 758 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight();
640 759
641 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope); 760 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope);
642 761
643 placeItemsOnGrid(m_grid, TrackSizing); 762 placeItemsOnGrid(m_grid, TrackSizing);
644 763
645 GridSizingData sizingData(numTracks(ForColumns, m_grid), 764 GridSizingData sizingData(numTracks(ForColumns, m_grid),
646 numTracks(ForRows, m_grid), m_grid); 765 numTracks(ForRows, m_grid), m_grid);
647 766
767 computeBaselineAlignmentContext(sizingData);
768
648 // 1- First, the track sizing algorithm is used to resolve the sizes of the 769 // 1- First, the track sizing algorithm is used to resolve the sizes of the
649 // grid columns. 770 // grid columns.
650 // At this point the logical width is always definite as the above call to 771 // At this point the logical width is always definite as the above call to
651 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the 772 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the
652 // same for heights though because many code paths inside 773 // same for heights though because many code paths inside
653 // updateLogicalHeight() require a previous call to setLogicalHeight() to 774 // updateLogicalHeight() require a previous call to setLogicalHeight() to
654 // resolve heights properly (like for positioned items for example). 775 // resolve heights properly (like for positioned items for example).
655 LayoutUnit availableSpaceForColumns = availableLogicalWidth(); 776 LayoutUnit availableSpaceForColumns = availableLogicalWidth();
656 computeTrackSizesForDefiniteSize(ForColumns, sizingData, 777 computeTrackSizesForDefiniteSize(ForColumns, sizingData,
657 availableSpaceForColumns); 778 availableSpaceForColumns);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 920
800 void LayoutGrid::computeIntrinsicLogicalWidths( 921 void LayoutGrid::computeIntrinsicLogicalWidths(
801 LayoutUnit& minLogicalWidth, 922 LayoutUnit& minLogicalWidth,
802 LayoutUnit& maxLogicalWidth) const { 923 LayoutUnit& maxLogicalWidth) const {
803 Grid grid(this); 924 Grid grid(this);
804 placeItemsOnGrid(grid, IntrinsicSizeComputation); 925 placeItemsOnGrid(grid, IntrinsicSizeComputation);
805 926
806 GridSizingData sizingData(numTracks(ForColumns, grid), 927 GridSizingData sizingData(numTracks(ForColumns, grid),
807 numTracks(ForRows, grid), grid); 928 numTracks(ForRows, grid), grid);
808 929
930 computeBaselineAlignmentContext(sizingData);
809 computeTrackSizesForIndefiniteSize(ForColumns, sizingData, minLogicalWidth, 931 computeTrackSizesForIndefiniteSize(ForColumns, sizingData, minLogicalWidth,
810 maxLogicalWidth); 932 maxLogicalWidth);
811 933
812 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth()); 934 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth());
813 minLogicalWidth += scrollbarWidth; 935 minLogicalWidth += scrollbarWidth;
814 maxLogicalWidth += scrollbarWidth; 936 maxLogicalWidth += scrollbarWidth;
815 } 937 }
816 938
817 void LayoutGrid::computeTrackSizesForIndefiniteSize( 939 void LayoutGrid::computeTrackSizesForIndefiniteSize(
818 GridTrackSizingDirection direction, 940 GridTrackSizingDirection direction,
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 LayoutUnit(-1)); 1439 LayoutUnit(-1));
1318 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); 1440 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1319 } 1441 }
1320 1442
1321 // We need to clear the stretched height to properly compute logical height 1443 // We need to clear the stretched height to properly compute logical height
1322 // during layout. 1444 // during layout.
1323 if (child.needsLayout()) 1445 if (child.needsLayout())
1324 child.clearOverrideLogicalContentHeight(); 1446 child.clearOverrideLogicalContentHeight();
1325 1447
1326 child.layoutIfNeeded(); 1448 child.layoutIfNeeded();
1449 GridAxis baselineAxis =
1450 isOrthogonalChild(child) ? GridRowAxis : GridColumnAxis;
1451 if (isBaselineAlignmentForChild(child, baselineAxis)) {
1452 auto group = getBaselineGroupForChild(child, sizingData, baselineAxis);
1453 return group.maxAscent() + group.maxDescent();
1454 }
1327 return child.logicalHeight() + child.marginLogicalHeight(); 1455 return child.logicalHeight() + child.marginLogicalHeight();
1328 } 1456 }
1329 1457
1330 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( 1458 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild(
1331 const LayoutBox& child, 1459 const LayoutBox& child,
1332 GridTrackSizingDirection direction) const { 1460 GridTrackSizingDirection direction) const {
1333 return !isOrthogonalChild(child) 1461 return !isOrthogonalChild(child)
1334 ? direction 1462 ? direction
1335 : (direction == ForColumns ? ForRows : ForColumns); 1463 : (direction == ForColumns ? ForRows : ForColumns);
1336 } 1464 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1420 1548
1421 // All orthogonal flow boxes were already laid out during an early layout 1549 // All orthogonal flow boxes were already laid out during an early layout
1422 // phase performed in FrameView::performLayout. 1550 // phase performed in FrameView::performLayout.
1423 // It's true that grid track sizing was not completed at that time and it may 1551 // 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 1552 // 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 1553 // perform a layout during intrinsic width computation, we have to use that
1426 // computed height for now. 1554 // computed height for now.
1427 if (direction == ForColumns && 1555 if (direction == ForColumns &&
1428 sizingData.sizingOperation == IntrinsicSizeComputation) { 1556 sizingData.sizingOperation == IntrinsicSizeComputation) {
1429 DCHECK(isOrthogonalChild(child)); 1557 DCHECK(isOrthogonalChild(child));
1558 if (isBaselineAlignmentForChild(child, GridRowAxis)) {
1559 auto group = getBaselineGroupForChild(child, sizingData, GridRowAxis);
1560 return group.maxAscent() + group.maxDescent();
1561 }
1430 return child.logicalHeight() + child.marginLogicalHeight(); 1562 return child.logicalHeight() + child.marginLogicalHeight();
1431 } 1563 }
1432 1564
1433 if (updateOverrideContainingBlockContentSizeForChild( 1565 if (updateOverrideContainingBlockContentSizeForChild(
1434 child, childInlineDirection, sizingData)) 1566 child, childInlineDirection, sizingData))
1435 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); 1567 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1436 return logicalHeightForChild(child, sizingData); 1568 return logicalHeightForChild(child, sizingData);
1437 } 1569 }
1438 1570
1439 DISABLE_CFI_PERF 1571 DISABLE_CFI_PERF
(...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3081 .toInt(); 3213 .toInt();
3082 } 3214 }
3083 3215
3084 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, 3216 static int synthesizedBaselineFromBorderBox(const LayoutBox& box,
3085 LineDirectionMode direction) { 3217 LineDirectionMode direction) {
3086 return (direction == HorizontalLine ? box.size().height() 3218 return (direction == HorizontalLine ? box.size().height()
3087 : box.size().width()) 3219 : box.size().width())
3088 .toInt(); 3220 .toInt();
3089 } 3221 }
3090 3222
3091 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be
3092 // refactored somehow.
3093 int LayoutGrid::baselinePosition(FontBaseline, 3223 int LayoutGrid::baselinePosition(FontBaseline,
3094 bool, 3224 bool,
3095 LineDirectionMode direction, 3225 LineDirectionMode direction,
3096 LinePositionMode mode) const { 3226 LinePositionMode mode) const {
3097 DCHECK_EQ(mode, PositionOnContainingLine); 3227 DCHECK_EQ(mode, PositionOnContainingLine);
3098 int baseline = firstLineBoxBaseline(); 3228 int baseline = firstLineBoxBaseline();
3099 // We take content-box's bottom if no valid baseline. 3229 // We take content-box's bottom if no valid baseline.
3100 if (baseline == -1) 3230 if (baseline == -1)
3101 baseline = synthesizedBaselineFromContentBox(*this, direction); 3231 baseline = synthesizedBaselineFromContentBox(*this, direction);
3102 3232
3103 return baseline + beforeMarginInLineDirection(direction); 3233 return baseline + beforeMarginInLineDirection(direction);
3104 } 3234 }
3105 3235
3106 bool LayoutGrid::isInlineBaselineAlignedChild(const LayoutBox* child) const {
3107 return alignSelfForChild(*child).position() == ItemPositionBaseline &&
3108 !isOrthogonalChild(*child) && !hasAutoMarginsInColumnAxis(*child);
3109 }
3110
3111 int LayoutGrid::firstLineBoxBaseline() const { 3236 int LayoutGrid::firstLineBoxBaseline() const {
3112 if (isWritingModeRoot() || !m_grid.hasGridItems()) 3237 if (isWritingModeRoot() || !m_grid.hasGridItems())
3113 return -1; 3238 return -1;
3114 const LayoutBox* baselineChild = nullptr; 3239 const LayoutBox* baselineChild = nullptr;
3115 const LayoutBox* firstChild = nullptr; 3240 const LayoutBox* firstChild = nullptr;
3116 bool isBaselineAligned = false; 3241 bool isBaselineAligned = false;
3117 // Finding the first grid item in grid order. 3242 // Finding the first grid item in grid order.
3118 for (size_t column = 0; 3243 for (size_t column = 0;
3119 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) { 3244 !isBaselineAligned && column < m_grid.numTracks(ForColumns); column++) {
3120 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) { 3245 for (size_t index = 0; index < m_grid.cell(0, column).size(); index++) {
3121 const LayoutBox* child = m_grid.cell(0, column)[index]; 3246 const LayoutBox* child = m_grid.cell(0, column)[index];
3122 DCHECK(!child->isOutOfFlowPositioned()); 3247 DCHECK(!child->isOutOfFlowPositioned());
3123 // If an item participates in baseline alignmen, we select such item. 3248 // If an item participates in baseline alignment, we select such item.
3124 if (isInlineBaselineAlignedChild(child)) { 3249 if (isBaselineAlignmentForChild(*child)) {
3125 // TODO (lajava): self-baseline and content-baseline alignment 3250 // TODO (lajava): self-baseline and content-baseline alignment
3126 // still not implemented. 3251 // still not implemented.
3127 baselineChild = child; 3252 baselineChild = child;
3128 isBaselineAligned = true; 3253 isBaselineAligned = true;
3129 break; 3254 break;
3130 } 3255 }
3131 if (!baselineChild) { 3256 if (!baselineChild) {
3132 // Use dom order for items in the same cell. 3257 // Use dom order for items in the same cell.
3133 if (!firstChild || (m_grid.gridItemPaintOrder(*child) < 3258 if (!firstChild || (m_grid.gridItemPaintOrder(*child) <
3134 m_grid.gridItemPaintOrder(*firstChild))) 3259 m_grid.gridItemPaintOrder(*firstChild)))
(...skipping 29 matching lines...) Expand all
3164 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const { 3289 int LayoutGrid::inlineBlockBaseline(LineDirectionMode direction) const {
3165 int baseline = firstLineBoxBaseline(); 3290 int baseline = firstLineBoxBaseline();
3166 if (baseline != -1) 3291 if (baseline != -1)
3167 return baseline; 3292 return baseline;
3168 3293
3169 int marginHeight = 3294 int marginHeight =
3170 (direction == HorizontalLine ? marginTop() : marginRight()).toInt(); 3295 (direction == HorizontalLine ? marginTop() : marginRight()).toInt();
3171 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight; 3296 return synthesizedBaselineFromContentBox(*this, direction) + marginHeight;
3172 } 3297 }
3173 3298
3299 bool LayoutGrid::isHorizontalGridAxis(GridAxis axis) const {
3300 return axis == GridRowAxis ? isHorizontalWritingMode()
3301 : !isHorizontalWritingMode();
3302 }
3303
3304 bool LayoutGrid::isParallelToBlockAxisForChild(const LayoutBox& child,
3305 GridAxis axis) const {
3306 return axis == GridColumnAxis ? !isOrthogonalChild(child)
3307 : isOrthogonalChild(child);
3308 }
3309
3310 bool LayoutGrid::isDescentBaselineForChild(const LayoutBox& child,
3311 GridAxis baselineAxis) const {
3312 return isHorizontalGridAxis(baselineAxis) &&
3313 !styleRef().isFlippedBlocksWritingMode();
3314 }
3315
3316 bool LayoutGrid::isBaselineAlignmentForChild(const LayoutBox& child,
3317 GridAxis baselineAxis) const {
3318 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis;
3319 ItemPosition align = isColumnAxisBaseline
3320 ? alignSelfForChild(child).position()
3321 : justifySelfForChild(child).position();
3322 bool hasAutoMargins = isColumnAxisBaseline ? hasAutoMarginsInColumnAxis(child)
3323 : hasAutoMarginsInRowAxis(child);
3324 return isBaselinePosition(align) && !hasAutoMargins;
3325 }
3326
3327 const BaselineGroup& LayoutGrid::getBaselineGroupForChild(
3328 const LayoutBox& child,
3329 const GridSizingData& sizingData,
3330 GridAxis baselineAxis) const {
3331 DCHECK(isBaselineAlignmentForChild(child, baselineAxis));
3332 auto& grid = sizingData.grid();
3333 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis;
3334 bool isRowAxisContext = isColumnAxisBaseline;
3335 auto&& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows)
svillar 2017/01/19 09:41:25 auto&& ???
jfernandez 2017/01/19 16:31:48 Since gridItemSpan returns a temporary object, we
3336 : grid.gridItemSpan(child, ForColumns);
3337 auto& contextsMap = isRowAxisContext ? sizingData.rowAxisAlignmentContext
3338 : sizingData.colAxisAlignmentContext;
3339 auto* context = contextsMap.get(span.startLine());
3340 DCHECK(context);
3341 ItemPosition align = isColumnAxisBaseline
3342 ? alignSelfForChild(child).position()
3343 : justifySelfForChild(child).position();
3344 return context->getSharedGroup(child, align);
3345 }
3346
3347 LayoutUnit LayoutGrid::marginOverForChild(const LayoutBox& child,
3348 GridAxis axis) const {
3349 return isHorizontalGridAxis(axis) ? child.marginRight() : child.marginTop();
3350 }
3351
3352 LayoutUnit LayoutGrid::logicalAscentForChild(const LayoutBox& child,
3353 GridAxis baselineAxis) const {
3354 LayoutUnit ascent = ascentForChild(child, baselineAxis);
3355 return isDescentBaselineForChild(child, baselineAxis)
3356 ? descentForChild(child, ascent, baselineAxis)
3357 : ascent;
3358 }
3359
3360 LayoutUnit LayoutGrid::ascentForChild(const LayoutBox& child,
3361 GridAxis baselineAxis) const {
3362 int baseline = isParallelToBlockAxisForChild(child, baselineAxis)
3363 ? child.firstLineBoxBaseline()
3364 : -1;
3365 // We take border-box's bottom if no valid baseline.
3366 if (baseline == -1) {
svillar 2017/01/19 09:41:25 Unfortunate that we use the magic -1 but I guess i
jfernandez 2017/01/19 16:31:48 Yes, we can implement optional, as we do in WebKit
3367 baseline = isHorizontalGridAxis(baselineAxis)
3368 ? child.size().width().toInt()
3369 : child.size().height().toInt();
3370 }
3371 return LayoutUnit(baseline) + marginOverForChild(child, baselineAxis);
3372 }
3373
3374 LayoutUnit LayoutGrid::descentForChild(const LayoutBox& child,
3375 LayoutUnit ascent,
3376 GridAxis baselineAxis) const {
3377 if (isParallelToBlockAxisForChild(child, baselineAxis))
3378 return child.marginLogicalHeight() + child.logicalHeight() - ascent;
3379 return child.marginLogicalWidth() + child.logicalWidth() - ascent;
3380 }
3381
3382 void LayoutGrid::computeBaselineAlignmentContext(
3383 GridSizingData& sizingData) const {
3384 for (auto* child = firstInFlowChildBox(); child;
3385 child = child->nextInFlowSiblingBox()) {
3386 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridRowAxis);
3387 updateBaselineAlignmentContextIfNeeded(*child, sizingData, GridColumnAxis);
3388 }
3389 }
3390
3391 void LayoutGrid::updateBaselineAlignmentContextIfNeeded(
3392 LayoutBox& child,
3393 GridSizingData& sizingData,
3394 GridAxis baselineAxis) const {
3395 if (!isBaselineAlignmentForChild(child, baselineAxis))
3396 return;
3397
3398 child.layoutIfNeeded();
svillar 2017/01/19 09:41:25 This method is called by computeBaselineAlignmentC
jfernandez 2017/01/19 16:31:48 I don't know why it doesn't. Anyway, what I can d
3399
3400 // Determine Ascent and Descent values of this child with respect to
3401 // its grid container.
3402 LayoutUnit ascent = ascentForChild(child, baselineAxis);
3403 LayoutUnit descent = descentForChild(child, ascent, baselineAxis);
3404 if (isDescentBaselineForChild(child, baselineAxis)) {
3405 LayoutUnit temp(ascent);
3406 ascent = descent;
3407 descent = temp;
3408 }
3409
3410 // Looking up for a shared alignment context perpendicular to the
3411 // baseline axis.
3412 auto& grid = sizingData.grid();
3413 bool isColumnAxisBaseline = baselineAxis == GridColumnAxis;
3414 bool isRowAxisContext = isColumnAxisBaseline;
3415 auto&& span = isRowAxisContext ? grid.gridItemSpan(child, ForRows)
svillar 2017/01/19 09:41:25 auto&& ?
jfernandez 2017/01/19 16:31:48 Already replied before.
3416 : grid.gridItemSpan(child, ForColumns);
3417 auto& contextsMap = isRowAxisContext ? sizingData.rowAxisAlignmentContext
3418 : sizingData.colAxisAlignmentContext;
3419 auto addResult = contextsMap.add(span.startLine(), nullptr);
3420
3421 // Looking for a compatible baseline-sharing group.
3422 ItemPosition align = isColumnAxisBaseline
3423 ? alignSelfForChild(child).position()
3424 : justifySelfForChild(child).position();
3425 if (addResult.isNewEntry) {
3426 addResult.storedValue->value =
3427 WTF::makeUnique<BaselineContext>(child, align, ascent, descent);
3428 } else {
3429 auto* context = addResult.storedValue->value.get();
3430 context->updateSharedGroup(child, align, ascent, descent);
3431 }
3432 }
3433
3434 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild(
3435 const LayoutBox& child,
3436 const GridSizingData& sizingData) const {
3437 if (!isBaselineAlignmentForChild(child, GridColumnAxis))
3438 return LayoutUnit();
3439 auto& group = getBaselineGroupForChild(child, sizingData, GridColumnAxis);
3440 if (group.size() > 1)
3441 return group.maxAscent() - logicalAscentForChild(child, GridColumnAxis);
3442 return LayoutUnit();
3443 }
3444
3445 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild(
3446 const LayoutBox& child,
3447 const GridSizingData& sizingData) const {
3448 if (!isBaselineAlignmentForChild(child, GridRowAxis))
3449 return LayoutUnit();
3450 auto& group = getBaselineGroupForChild(child, sizingData, GridRowAxis);
3451 if (group.size() > 1)
3452 group.maxAscent() - logicalAscentForChild(child, GridRowAxis);
3453 return LayoutUnit();
3454 }
3455
3174 GridAxisPosition LayoutGrid::columnAxisPositionForChild( 3456 GridAxisPosition LayoutGrid::columnAxisPositionForChild(
3175 const LayoutBox& child) const { 3457 const LayoutBox& child) const {
3176 bool hasSameWritingMode = 3458 bool hasSameWritingMode =
3177 child.styleRef().getWritingMode() == styleRef().getWritingMode(); 3459 child.styleRef().getWritingMode() == styleRef().getWritingMode();
3178 bool childIsLTR = child.styleRef().isLeftToRightDirection(); 3460 bool childIsLTR = child.styleRef().isLeftToRightDirection();
3179 3461
3180 switch (alignSelfForChild(child).position()) { 3462 switch (alignSelfForChild(child).position()) {
3181 case ItemPositionSelfStart: 3463 case ItemPositionSelfStart:
3182 // TODO (lajava): Should we implement this logic in a generic utility 3464 // TODO (lajava): Should we implement this logic in a generic utility
3183 // function? 3465 // function?
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3233 // Only used in flex layout, otherwise equivalent to 'end'. 3515 // Only used in flex layout, otherwise equivalent to 'end'.
3234 case ItemPositionFlexEnd: 3516 case ItemPositionFlexEnd:
3235 // Aligns the alignment subject to be flush with the alignment container's 3517 // Aligns the alignment subject to be flush with the alignment container's
3236 // 'end' edge (block-end) in the column axis. 3518 // 'end' edge (block-end) in the column axis.
3237 case ItemPositionEnd: 3519 case ItemPositionEnd:
3238 return GridAxisEnd; 3520 return GridAxisEnd;
3239 case ItemPositionStretch: 3521 case ItemPositionStretch:
3240 return GridAxisStart; 3522 return GridAxisStart;
3241 case ItemPositionBaseline: 3523 case ItemPositionBaseline:
3242 case ItemPositionLastBaseline: 3524 case ItemPositionLastBaseline:
3243 // FIXME: These two require implementing Baseline Alignment. For now, we
3244 // always 'start' align the child. crbug.com/234191
3245 return GridAxisStart; 3525 return GridAxisStart;
3246 case ItemPositionAuto: 3526 case ItemPositionAuto:
3247 case ItemPositionNormal: 3527 case ItemPositionNormal:
3248 break; 3528 break;
3249 } 3529 }
3250 3530
3251 ASSERT_NOT_REACHED(); 3531 ASSERT_NOT_REACHED();
3252 return GridAxisStart; 3532 return GridAxisStart;
3253 } 3533 }
3254 3534
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3312 // Only used in flex layout, otherwise equivalent to 'end'. 3592 // Only used in flex layout, otherwise equivalent to 'end'.
3313 case ItemPositionFlexEnd: 3593 case ItemPositionFlexEnd:
3314 // Aligns the alignment subject to be flush with the alignment container's 3594 // Aligns the alignment subject to be flush with the alignment container's
3315 // 'end' edge (inline-end) in the row axis. 3595 // 'end' edge (inline-end) in the row axis.
3316 case ItemPositionEnd: 3596 case ItemPositionEnd:
3317 return GridAxisEnd; 3597 return GridAxisEnd;
3318 case ItemPositionStretch: 3598 case ItemPositionStretch:
3319 return GridAxisStart; 3599 return GridAxisStart;
3320 case ItemPositionBaseline: 3600 case ItemPositionBaseline:
3321 case ItemPositionLastBaseline: 3601 case ItemPositionLastBaseline:
3322 // FIXME: These two require implementing Baseline Alignment. For now, we
3323 // always 'start' align the child. crbug.com/234191
3324 return GridAxisStart; 3602 return GridAxisStart;
3325 case ItemPositionAuto: 3603 case ItemPositionAuto:
3326 case ItemPositionNormal: 3604 case ItemPositionNormal:
3327 break; 3605 break;
3328 } 3606 }
3329 3607
3330 ASSERT_NOT_REACHED(); 3608 ASSERT_NOT_REACHED();
3331 return GridAxisStart; 3609 return GridAxisStart;
3332 } 3610 }
3333 3611
3334 LayoutUnit LayoutGrid::columnAxisOffsetForChild( 3612 LayoutUnit LayoutGrid::columnAxisOffsetForChild(
3335 const LayoutBox& child, 3613 const LayoutBox& child,
3336 GridSizingData& sizingData) const { 3614 GridSizingData& sizingData) const {
3337 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows); 3615 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows);
3338 size_t childStartLine = rowsSpan.startLine(); 3616 size_t childStartLine = rowsSpan.startLine();
3339 LayoutUnit startOfRow = m_rowPositions[childStartLine]; 3617 LayoutUnit startOfRow = m_rowPositions[childStartLine];
3340 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); 3618 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
3341 if (hasAutoMarginsInColumnAxis(child)) 3619 if (hasAutoMarginsInColumnAxis(child))
3342 return startPosition; 3620 return startPosition;
3343 GridAxisPosition axisPosition = columnAxisPositionForChild(child); 3621 GridAxisPosition axisPosition = columnAxisPositionForChild(child);
3344 switch (axisPosition) { 3622 switch (axisPosition) {
3345 case GridAxisStart: 3623 case GridAxisStart:
3346 return startPosition; 3624 return startPosition +
3625 columnAxisBaselineOffsetForChild(child, sizingData);
3347 case GridAxisEnd: 3626 case GridAxisEnd:
3348 case GridAxisCenter: { 3627 case GridAxisCenter: {
3349 size_t childEndLine = rowsSpan.endLine(); 3628 size_t childEndLine = rowsSpan.endLine();
3350 LayoutUnit endOfRow = m_rowPositions[childEndLine]; 3629 LayoutUnit endOfRow = m_rowPositions[childEndLine];
3351 // m_rowPositions include distribution offset (because of content 3630 // m_rowPositions include distribution offset (because of content
3352 // alignment) and gutters so we need to subtract them to get the actual 3631 // alignment) and gutters so we need to subtract them to get the actual
3353 // end position for a given row (this does not have to be done for the 3632 // end position for a given row (this does not have to be done for the
3354 // last track as there are no more m_columnPositions after it). 3633 // last track as there are no more m_columnPositions after it).
3355 LayoutUnit trackGap = 3634 LayoutUnit trackGap =
3356 gridGapForDirection(ForRows, sizingData.sizingOperation); 3635 gridGapForDirection(ForRows, sizingData.sizingOperation);
(...skipping 23 matching lines...) Expand all
3380 const GridSpan& columnsSpan = 3659 const GridSpan& columnsSpan =
3381 sizingData.grid().gridItemSpan(child, ForColumns); 3660 sizingData.grid().gridItemSpan(child, ForColumns);
3382 size_t childStartLine = columnsSpan.startLine(); 3661 size_t childStartLine = columnsSpan.startLine();
3383 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; 3662 LayoutUnit startOfColumn = m_columnPositions[childStartLine];
3384 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); 3663 LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
3385 if (hasAutoMarginsInRowAxis(child)) 3664 if (hasAutoMarginsInRowAxis(child))
3386 return startPosition; 3665 return startPosition;
3387 GridAxisPosition axisPosition = rowAxisPositionForChild(child); 3666 GridAxisPosition axisPosition = rowAxisPositionForChild(child);
3388 switch (axisPosition) { 3667 switch (axisPosition) {
3389 case GridAxisStart: 3668 case GridAxisStart:
3390 return startPosition; 3669 return startPosition + rowAxisBaselineOffsetForChild(child, sizingData);
3391 case GridAxisEnd: 3670 case GridAxisEnd:
3392 case GridAxisCenter: { 3671 case GridAxisCenter: {
3393 size_t childEndLine = columnsSpan.endLine(); 3672 size_t childEndLine = columnsSpan.endLine();
3394 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; 3673 LayoutUnit endOfColumn = m_columnPositions[childEndLine];
3395 // m_columnPositions include distribution offset (because of content 3674 // m_columnPositions include distribution offset (because of content
3396 // alignment) and gutters so we need to subtract them to get the actual 3675 // alignment) and gutters so we need to subtract them to get the actual
3397 // end position for a given column (this does not have to be done for the 3676 // end position for a given column (this does not have to be done for the
3398 // last track as there are no more m_columnPositions after it). 3677 // last track as there are no more m_columnPositions after it).
3399 LayoutUnit trackGap = 3678 LayoutUnit trackGap =
3400 gridGapForDirection(ForColumns, sizingData.sizingOperation); 3679 gridGapForDirection(ForColumns, sizingData.sizingOperation);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
3617 if (direction == ForRows) 3896 if (direction == ForRows)
3618 return grid.numTracks(ForRows); 3897 return grid.numTracks(ForRows);
3619 3898
3620 return grid.numTracks(ForRows) 3899 return grid.numTracks(ForRows)
3621 ? grid.numTracks(ForColumns) 3900 ? grid.numTracks(ForColumns)
3622 : GridPositionsResolver::explicitGridColumnCount( 3901 : GridPositionsResolver::explicitGridColumnCount(
3623 styleRef(), grid.autoRepeatTracks(ForColumns)); 3902 styleRef(), grid.autoRepeatTracks(ForColumns));
3624 } 3903 }
3625 3904
3626 } // namespace blink 3905 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698