OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "core/layout/LayoutGrid.h" | 26 #include "core/layout/LayoutGrid.h" |
27 | 27 |
28 #include "core/frame/UseCounter.h" | 28 #include "core/frame/UseCounter.h" |
29 #include "core/layout/LayoutState.h" | 29 #include "core/layout/LayoutState.h" |
30 #include "core/layout/TextAutosizer.h" | 30 #include "core/layout/TextAutosizer.h" |
31 #include "core/paint/GridPainter.h" | 31 #include "core/paint/GridPainter.h" |
32 #include "core/paint/PaintLayer.h" | 32 #include "core/paint/PaintLayer.h" |
33 #include "core/style/ComputedStyle.h" | 33 #include "core/style/ComputedStyle.h" |
34 #include "core/style/GridArea.h" | 34 #include "core/style/GridArea.h" |
35 #include "platform/LengthFunctions.h" | 35 #include "platform/LengthFunctions.h" |
36 #include "platform/text/WritingMode.h" | |
36 #include "wtf/PtrUtil.h" | 37 #include "wtf/PtrUtil.h" |
37 #include <algorithm> | 38 #include <algorithm> |
38 #include <memory> | 39 #include <memory> |
39 | 40 |
40 namespace blink { | 41 namespace blink { |
41 | 42 |
42 static const int infinity = -1; | 43 static const int infinity = -1; |
43 | 44 |
44 class GridItemWithSpan; | 45 class GridItemWithSpan; |
45 | 46 |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |