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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 void ensureGrowthLimitIsBiggerThanBaseSize() | 112 void ensureGrowthLimitIsBiggerThanBaseSize() |
113 { | 113 { |
114 if (m_growthLimit != infinity && m_growthLimit < m_baseSize) | 114 if (m_growthLimit != infinity && m_growthLimit < m_baseSize) |
115 m_growthLimit = m_baseSize; | 115 m_growthLimit = m_baseSize; |
116 } | 116 } |
117 | 117 |
118 LayoutUnit m_baseSize; | 118 LayoutUnit m_baseSize; |
119 LayoutUnit m_growthLimit; | 119 LayoutUnit m_growthLimit; |
120 }; | 120 }; |
121 | 121 |
| 122 struct ContentAlignmentData { |
| 123 STACK_ALLOCATED(); |
| 124 public: |
| 125 ContentAlignmentData() {}; |
| 126 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) |
| 127 : positionOffset(position) |
| 128 , distributionOffset(distribution) |
| 129 { |
| 130 } |
| 131 |
| 132 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } |
| 133 |
| 134 LayoutUnit positionOffset = -1; |
| 135 LayoutUnit distributionOffset = -1; |
| 136 }; |
| 137 |
122 struct GridTrackForNormalization { | 138 struct GridTrackForNormalization { |
123 GridTrackForNormalization(const GridTrack& track, double flex) | 139 GridTrackForNormalization(const GridTrack& track, double flex) |
124 : m_track(&track) | 140 : m_track(&track) |
125 , m_flex(flex) | 141 , m_flex(flex) |
126 , m_normalizedFlexValue(track.baseSize() / flex) | 142 , m_normalizedFlexValue(track.baseSize() / flex) |
127 { | 143 { |
128 } | 144 } |
129 | 145 |
130 // Required by std::sort. | 146 // Required by std::sort. |
131 GridTrackForNormalization& operator=(const GridTrackForNormalization& o) | 147 GridTrackForNormalization& operator=(const GridTrackForNormalization& o) |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 } | 252 } |
237 | 253 |
238 Vector<GridTrack> columnTracks; | 254 Vector<GridTrack> columnTracks; |
239 Vector<GridTrack> rowTracks; | 255 Vector<GridTrack> rowTracks; |
240 Vector<size_t> contentSizedTracksIndex; | 256 Vector<size_t> contentSizedTracksIndex; |
241 | 257 |
242 // Performance optimization: hold onto these Vectors until the end of Layout
to avoid repeated malloc / free. | 258 // Performance optimization: hold onto these Vectors until the end of Layout
to avoid repeated malloc / free. |
243 Vector<GridTrack*> filteredTracks; | 259 Vector<GridTrack*> filteredTracks; |
244 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; | 260 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; |
245 Vector<GridTrack*> growBeyondGrowthLimitsTracks; | 261 Vector<GridTrack*> growBeyondGrowthLimitsTracks; |
246 | |
247 LayoutUnit rowsPositionOffset; | |
248 LayoutUnit rowsDistributionOffset; | |
249 LayoutUnit columnsPositionOffset; | |
250 LayoutUnit columnsDistributionOffset; | |
251 }; | 262 }; |
252 | 263 |
253 struct GridItemsSpanGroupRange { | 264 struct GridItemsSpanGroupRange { |
254 Vector<GridItemWithSpan>::iterator rangeStart; | 265 Vector<GridItemWithSpan>::iterator rangeStart; |
255 Vector<GridItemWithSpan>::iterator rangeEnd; | 266 Vector<GridItemWithSpan>::iterator rangeEnd; |
256 }; | 267 }; |
257 | 268 |
258 LayoutGrid::LayoutGrid(Element* element) | 269 LayoutGrid::LayoutGrid(Element* element) |
259 : LayoutBlock(element) | 270 : LayoutBlock(element) |
260 , m_gridIsDirty(true) | 271 , m_gridIsDirty(true) |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 ASSERT(!track.growthLimitIsInfinite()); | 443 ASSERT(!track.growthLimitIsInfinite()); |
433 freeSpace -= track.baseSize(); | 444 freeSpace -= track.baseSize(); |
434 } | 445 } |
435 | 446 |
436 const bool hasUndefinedRemainingSpace = (direction == ForRows) ? style()->lo
gicalHeight().isAuto() : gridElementIsShrinkToFit(); | 447 const bool hasUndefinedRemainingSpace = (direction == ForRows) ? style()->lo
gicalHeight().isAuto() : gridElementIsShrinkToFit(); |
437 | 448 |
438 if (!hasUndefinedRemainingSpace && freeSpace <= 0) | 449 if (!hasUndefinedRemainingSpace && freeSpace <= 0) |
439 return; | 450 return; |
440 | 451 |
441 // 3. Grow all Grid tracks in GridTracks from their baseSize up to their gro
wthLimit value until freeSpace is exhausted. | 452 // 3. Grow all Grid tracks in GridTracks from their baseSize up to their gro
wthLimit value until freeSpace is exhausted. |
442 // Any 'auto-sized' (content based) track will be 'stretched' over their Max
Breadth if required | |
443 // and there is space available, except if there are flexible track, which w
ill occupy the whole | |
444 // available space. | |
445 bool needToStretch = flexibleSizedTracksIndex.isEmpty() && !sizingData.conte
ntSizedTracksIndex.isEmpty() | |
446 && ((direction == ForColumns && style()->justifyContentDistribution() ==
ContentDistributionStretch) | |
447 || (direction == ForRows && style()->alignContentDistribution() == C
ontentDistributionStretch)); | |
448 const size_t tracksSize = tracks.size(); | 453 const size_t tracksSize = tracks.size(); |
449 if (!hasUndefinedRemainingSpace) { | 454 if (!hasUndefinedRemainingSpace) { |
450 Vector<GridTrack*> tracksForDistribution(tracksSize); | 455 Vector<GridTrack*> tracksForDistribution(tracksSize); |
451 for (size_t i = 0; i < tracksSize; ++i) { | 456 for (size_t i = 0; i < tracksSize; ++i) { |
452 tracksForDistribution[i] = tracks.data() + i; | 457 tracksForDistribution[i] = tracks.data() + i; |
453 tracksForDistribution[i]->m_plannedIncrease = 0; | 458 tracksForDistribution[i]->m_plannedIncrease = 0; |
454 } | 459 } |
455 | 460 |
456 Vector<GridTrack*> tracksToStretch(sizingData.contentSizedTracksIndex.si
ze()); | 461 distributeSpaceToTracks<MaximizeTracks>(tracksForDistribution, nullptr,
sizingData, freeSpace); |
457 if (needToStretch) { | |
458 unsigned i = 0; | |
459 for (const auto& trackIndex : sizingData.contentSizedTracksIndex) { | |
460 tracksToStretch[i++] = tracks.data() + trackIndex; | |
461 } | |
462 } | |
463 | |
464 distributeSpaceToTracks<MaximizeTracks>(tracksForDistribution, needToStr
etch ? &tracksToStretch : nullptr, sizingData, freeSpace); | |
465 | 462 |
466 for (auto* track : tracksForDistribution) | 463 for (auto* track : tracksForDistribution) |
467 track->growBaseSize(track->m_plannedIncrease); | 464 track->growBaseSize(track->m_plannedIncrease); |
468 } else { | 465 } else { |
469 for (auto& track : tracks) | 466 for (auto& track : tracks) |
470 track.setBaseSize(track.growthLimit()); | 467 track.setBaseSize(track.growthLimit()); |
471 } | 468 } |
472 | 469 |
473 if (flexibleSizedTracksIndex.isEmpty()) | 470 if (flexibleSizedTracksIndex.isEmpty()) |
474 return; | 471 return; |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1226 // the grid and its children are correctly laid out according to the new sty
le rules. | 1223 // the grid and its children are correctly laid out according to the new sty
le rules. |
1227 setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1224 setNeedsLayout(LayoutInvalidationReason::GridChanged); |
1228 | 1225 |
1229 m_grid.resize(0); | 1226 m_grid.resize(0); |
1230 m_gridItemCoordinate.clear(); | 1227 m_gridItemCoordinate.clear(); |
1231 m_gridItemsOverflowingGridArea.resize(0); | 1228 m_gridItemsOverflowingGridArea.resize(0); |
1232 m_gridItemsIndexesMap.clear(); | 1229 m_gridItemsIndexesMap.clear(); |
1233 m_gridIsDirty = true; | 1230 m_gridIsDirty = true; |
1234 } | 1231 } |
1235 | 1232 |
| 1233 void LayoutGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection
direction, GridSizingData& sizingData, LayoutUnit availableSpace) |
| 1234 { |
| 1235 if (availableSpace <= 0 |
| 1236 || (direction == ForColumns && styleRef().justifyContentDistribution() !
= ContentDistributionStretch) |
| 1237 || (direction == ForRows && styleRef().alignContentDistribution() != Con
tentDistributionStretch)) |
| 1238 return; |
| 1239 |
| 1240 // We consider auto-sized tracks as content-sized (min-content, max-content,
auto). |
| 1241 Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTra
cks : sizingData.rowTracks; |
| 1242 Vector<unsigned> autoSizedTracksIndex; |
| 1243 for (unsigned i = 0; i < tracks.size(); ++i) { |
| 1244 const GridTrackSize& trackSize = gridTrackSize(direction, i); |
| 1245 // If there is some flexible-sized track, they should have exhausted ava
ilable space during sizing algorithm. |
| 1246 ASSERT(!trackSize.maxTrackBreadth().isFlex()); |
| 1247 if (trackSize.isContentSized()) |
| 1248 autoSizedTracksIndex.append(i); |
| 1249 } |
| 1250 |
| 1251 unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size(); |
| 1252 if (numberOfAutoSizedTracks < 1) |
| 1253 return; |
| 1254 |
| 1255 LayoutUnit sizeToIncrease = availableSpace / numberOfAutoSizedTracks; |
| 1256 for (const auto& trackIndex : autoSizedTracksIndex) { |
| 1257 GridTrack* track = tracks.data() + trackIndex; |
| 1258 // FIXME: Respecting the constraints imposed by max-height/max-width. |
| 1259 LayoutUnit baseSize = track->baseSize() + sizeToIncrease; |
| 1260 track->setBaseSize(baseSize); |
| 1261 } |
| 1262 } |
| 1263 |
1236 void LayoutGrid::layoutGridItems() | 1264 void LayoutGrid::layoutGridItems() |
1237 { | 1265 { |
1238 placeItemsOnGrid(); | 1266 placeItemsOnGrid(); |
1239 | 1267 |
1240 LayoutUnit availableSpaceForColumns = availableLogicalWidth(); | 1268 LayoutUnit availableSpaceForColumns = availableLogicalWidth(); |
1241 LayoutUnit availableSpaceForRows = availableLogicalHeight(IncludeMarginBorde
rPadding); | 1269 LayoutUnit availableSpaceForRows = availableLogicalHeight(IncludeMarginBorde
rPadding); |
1242 GridSizingData sizingData(gridColumnCount(), gridRowCount()); | 1270 GridSizingData sizingData(gridColumnCount(), gridRowCount()); |
1243 computeUsedBreadthOfGridTracks(ForColumns, sizingData, availableSpaceForColu
mns); | 1271 computeUsedBreadthOfGridTracks(ForColumns, sizingData, availableSpaceForColu
mns); |
1244 ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks
)); | 1272 ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks
)); |
1245 computeUsedBreadthOfGridTracks(ForRows, sizingData, availableSpaceForRows); | 1273 computeUsedBreadthOfGridTracks(ForRows, sizingData, availableSpaceForRows); |
1246 ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks)); | 1274 ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks)); |
1247 | 1275 |
1248 computeContentPositionAndDistributionColumnOffset(availableSpaceForColumns,
sizingData); | 1276 applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData, availableSpace
ForColumns); |
1249 computeContentPositionAndDistributionRowOffset(availableSpaceForRows, sizing
Data); | 1277 applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData, availableSpaceFor
Rows); |
1250 | 1278 |
1251 populateGridPositions(sizingData); | 1279 populateGridPositions(sizingData, availableSpaceForColumns, availableSpaceFo
rRows); |
1252 m_gridItemsOverflowingGridArea.resize(0); | 1280 m_gridItemsOverflowingGridArea.resize(0); |
1253 | 1281 |
1254 for (LayoutBox* child = firstChildBox(); child; child = child->nextSiblingBo
x()) { | 1282 for (LayoutBox* child = firstChildBox(); child; child = child->nextSiblingBo
x()) { |
1255 if (child->isOutOfFlowPositioned()) { | 1283 if (child->isOutOfFlowPositioned()) { |
1256 child->containingBlock()->insertPositionedObject(child); | 1284 child->containingBlock()->insertPositionedObject(child); |
1257 continue; | 1285 continue; |
1258 } | 1286 } |
1259 | 1287 |
1260 // Because the grid area cannot be styled, we don't need to adjust | 1288 // Because the grid area cannot be styled, we don't need to adjust |
1261 // the grid breadth to account for 'box-sizing'. | 1289 // the grid breadth to account for 'box-sizing'. |
1262 LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOve
rrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogica
lWidth() : LayoutUnit(); | 1290 LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOve
rrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogica
lWidth() : LayoutUnit(); |
1263 LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOv
errideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogi
calHeight() : LayoutUnit(); | 1291 LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOv
errideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogi
calHeight() : LayoutUnit(); |
1264 | 1292 |
1265 LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthF
orChild(*child, ForColumns, sizingData.columnTracks); | 1293 LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthF
orChildIncludingAlignmentOffsets(*child, ForColumns, sizingData); |
1266 LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadth
ForChild(*child, ForRows, sizingData.rowTracks); | 1294 LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadth
ForChildIncludingAlignmentOffsets(*child, ForRows, sizingData); |
1267 | 1295 |
1268 SubtreeLayoutScope layoutScope(*child); | 1296 SubtreeLayoutScope layoutScope(*child); |
1269 if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingB
lockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != ov
errideContainingBlockContentLogicalHeight && child->hasRelativeLogicalHeight())) | 1297 if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingB
lockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != ov
errideContainingBlockContentLogicalHeight && child->hasRelativeLogicalHeight())) |
1270 layoutScope.setNeedsLayout(child, LayoutInvalidationReason::GridChan
ged); | 1298 layoutScope.setNeedsLayout(child, LayoutInvalidationReason::GridChan
ged); |
1271 | 1299 |
1272 child->setOverrideContainingBlockContentLogicalWidth(overrideContainingB
lockContentLogicalWidth); | 1300 child->setOverrideContainingBlockContentLogicalWidth(overrideContainingB
lockContentLogicalWidth); |
1273 child->setOverrideContainingBlockContentLogicalHeight(overrideContaining
BlockContentLogicalHeight); | 1301 child->setOverrideContainingBlockContentLogicalHeight(overrideContaining
BlockContentLogicalHeight); |
1274 | 1302 |
1275 // Stretching logic might force a child layout, so we need to run it bef
ore the layoutIfNeeded | 1303 // Stretching logic might force a child layout, so we need to run it bef
ore the layoutIfNeeded |
1276 // call to avoid unnecessary relayouts. This might imply that child marg
ins, needed to correctly | 1304 // call to avoid unnecessary relayouts. This might imply that child marg
ins, needed to correctly |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 GridCoordinate LayoutGrid::cachedGridCoordinate(const LayoutBox& gridItem) const | 1419 GridCoordinate LayoutGrid::cachedGridCoordinate(const LayoutBox& gridItem) const |
1392 { | 1420 { |
1393 ASSERT(m_gridItemCoordinate.contains(&gridItem)); | 1421 ASSERT(m_gridItemCoordinate.contains(&gridItem)); |
1394 return m_gridItemCoordinate.get(&gridItem); | 1422 return m_gridItemCoordinate.get(&gridItem); |
1395 } | 1423 } |
1396 | 1424 |
1397 LayoutUnit LayoutGrid::gridAreaBreadthForChild(const LayoutBox& child, GridTrack
SizingDirection direction, const Vector<GridTrack>& tracks) const | 1425 LayoutUnit LayoutGrid::gridAreaBreadthForChild(const LayoutBox& child, GridTrack
SizingDirection direction, const Vector<GridTrack>& tracks) const |
1398 { | 1426 { |
1399 const GridCoordinate& coordinate = cachedGridCoordinate(child); | 1427 const GridCoordinate& coordinate = cachedGridCoordinate(child); |
1400 const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coor
dinate.rows; | 1428 const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coor
dinate.rows; |
1401 const Vector<LayoutUnit>& trackPositions = (direction == ForColumns) ? m_col
umnPositions : m_rowPositions; | |
1402 if (span.resolvedFinalPosition.toInt() < trackPositions.size()) { | |
1403 LayoutUnit startOftrack = trackPositions[span.resolvedInitialPosition.to
Int()]; | |
1404 LayoutUnit endOfTrack = trackPositions[span.resolvedFinalPosition.toInt(
)]; | |
1405 return endOfTrack - startOftrack + tracks[span.resolvedFinalPosition.toI
nt()].baseSize(); | |
1406 } | |
1407 LayoutUnit gridAreaBreadth = 0; | 1429 LayoutUnit gridAreaBreadth = 0; |
1408 for (GridSpan::iterator trackPosition = span.begin(); trackPosition != span.
end(); ++trackPosition) | 1430 for (GridSpan::iterator trackPosition = span.begin(); trackPosition != span.
end(); ++trackPosition) |
1409 gridAreaBreadth += tracks[trackPosition.toInt()].baseSize(); | 1431 gridAreaBreadth += tracks[trackPosition.toInt()].baseSize(); |
1410 | |
1411 return gridAreaBreadth; | 1432 return gridAreaBreadth; |
1412 } | 1433 } |
1413 | 1434 |
1414 void LayoutGrid::populateGridPositions(const GridSizingData& sizingData) | 1435 LayoutUnit LayoutGrid::gridAreaBreadthForChildIncludingAlignmentOffsets(const La
youtBox& child, GridTrackSizingDirection direction, const GridSizingData& sizing
Data) const |
1415 { | 1436 { |
1416 unsigned numberOfColumnTracks = sizingData.columnTracks.size(); | 1437 // We need the cached value when available because Content Distribution alig
nment properties |
1417 unsigned numberOfRowTracks = sizingData.rowTracks.size(); | 1438 // may have some influence in the final grid area breadth. |
| 1439 const Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.col
umnTracks : sizingData.rowTracks; |
| 1440 const GridCoordinate& coordinate = cachedGridCoordinate(child); |
| 1441 const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coor
dinate.rows; |
| 1442 const Vector<LayoutUnit>& linePositions = (direction == ForColumns) ? m_colu
mnPositions : m_rowPositions; |
| 1443 LayoutUnit initialTrackPosition = linePositions[span.resolvedInitialPosition
.toInt()]; |
| 1444 LayoutUnit finalTrackPosition = linePositions[span.resolvedFinalPosition.toI
nt()]; |
| 1445 // Track Positions vector stores the 'start' grid line of each track, so w h
ave to add last track's baseSize. |
| 1446 return finalTrackPosition - initialTrackPosition + tracks[span.resolvedFinal
Position.toInt()].baseSize(); |
| 1447 } |
1418 | 1448 |
1419 m_columnPositions.resize(numberOfColumnTracks + 1); | 1449 void LayoutGrid::populateGridPositions(GridSizingData& sizingData, LayoutUnit av
ailableSpaceForColumns, LayoutUnit availableSpaceForRows) |
1420 m_columnPositions[0] = borderAndPaddingStart() + sizingData.columnsPositionO
ffset; | 1450 { |
1421 for (unsigned i = 0; i < numberOfColumnTracks; ++i) | 1451 // Since we add alignment offsets, grid lines are not always adjacent. Hence
we will have to |
1422 m_columnPositions[i + 1] = m_columnPositions[i] + sizingData.columnsDist
ributionOffset + sizingData.columnTracks[i].baseSize(); | 1452 // assume from now on that we just store positions of the initial grid lines
of each track, |
| 1453 // except the last one, which is the only one considered as a final grid lin
e of a track. |
| 1454 // FIXME: This will affect the computed style value of grid tracks size, sin
ce we are |
| 1455 // using these positions to compute them. |
1423 | 1456 |
1424 m_rowPositions.resize(numberOfRowTracks + 1); | 1457 unsigned numberOfTracks = sizingData.columnTracks.size(); |
1425 m_rowPositions[0] = borderAndPaddingBefore() + sizingData.rowsPositionOffset
; | 1458 unsigned numberOfLines = numberOfTracks + 1; |
1426 for (unsigned i = 0; i < numberOfRowTracks; ++i) | 1459 unsigned lastLine = numberOfLines - 1; |
1427 m_rowPositions[i + 1] = m_rowPositions[i] + sizingData.rowsDistributionO
ffset + sizingData.rowTracks[i].baseSize(); | 1460 unsigned nextToLastLine = numberOfLines - 2; |
| 1461 ContentAlignmentData offset = computeContentPositionAndDistributionOffset(Fo
rColumns, availableSpaceForColumns, numberOfTracks); |
| 1462 m_columnPositions.resize(numberOfLines); |
| 1463 m_columnPositions[0] = borderAndPaddingStart() + offset.positionOffset; |
| 1464 for (unsigned i = 0; i < lastLine; ++i) |
| 1465 m_columnPositions[i + 1] = m_columnPositions[i] + offset.distributionOff
set + sizingData.columnTracks[i].baseSize(); |
| 1466 m_columnPositions[lastLine] = m_columnPositions[nextToLastLine] + sizingData
.columnTracks[nextToLastLine].baseSize(); |
| 1467 |
| 1468 numberOfTracks = sizingData.rowTracks.size(); |
| 1469 numberOfLines = numberOfTracks + 1; |
| 1470 lastLine = numberOfLines - 1; |
| 1471 nextToLastLine = numberOfLines - 2; |
| 1472 offset = computeContentPositionAndDistributionOffset(ForRows, availableSpace
ForRows, numberOfTracks); |
| 1473 m_rowPositions.resize(numberOfLines); |
| 1474 m_rowPositions[0] = borderAndPaddingBefore() + offset.positionOffset; |
| 1475 for (unsigned i = 0; i < lastLine; ++i) |
| 1476 m_rowPositions[i + 1] = m_rowPositions[i] + offset.distributionOffset +
sizingData.rowTracks[i].baseSize(); |
| 1477 m_rowPositions[lastLine] = m_rowPositions[nextToLastLine] + sizingData.rowTr
acks[nextToLastLine].baseSize(); |
1428 } | 1478 } |
1429 | 1479 |
1430 static LayoutUnit computeOverflowAlignmentOffset(OverflowAlignment overflow, Lay
outUnit trackBreadth, LayoutUnit childBreadth) | 1480 static LayoutUnit computeOverflowAlignmentOffset(OverflowAlignment overflow, Lay
outUnit trackBreadth, LayoutUnit childBreadth) |
1431 { | 1481 { |
1432 LayoutUnit offset = trackBreadth - childBreadth; | 1482 LayoutUnit offset = trackBreadth - childBreadth; |
1433 switch (overflow) { | 1483 switch (overflow) { |
1434 case OverflowAlignmentSafe: | 1484 case OverflowAlignmentSafe: |
1435 // If overflow is 'safe', we have to make sure we don't overflow the 'st
art' | 1485 // If overflow is 'safe', we have to make sure we don't overflow the 'st
art' |
1436 // edge (potentially cause some data loss as the overflow is unreachable
). | 1486 // edge (potentially cause some data loss as the overflow is unreachable
). |
1437 return std::max<LayoutUnit>(0, offset); | 1487 return std::max<LayoutUnit>(0, offset); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1633 // crbug.com/234191 | 1683 // crbug.com/234191 |
1634 return GridAxisStart; | 1684 return GridAxisStart; |
1635 case ItemPositionAuto: | 1685 case ItemPositionAuto: |
1636 break; | 1686 break; |
1637 } | 1687 } |
1638 | 1688 |
1639 ASSERT_NOT_REACHED(); | 1689 ASSERT_NOT_REACHED(); |
1640 return GridAxisStart; | 1690 return GridAxisStart; |
1641 } | 1691 } |
1642 | 1692 |
1643 LayoutUnit LayoutGrid::rowPositionForChild(const LayoutBox& child) const | 1693 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const |
1644 { | 1694 { |
1645 const GridCoordinate& coordinate = cachedGridCoordinate(child); | 1695 const GridCoordinate& coordinate = cachedGridCoordinate(child); |
1646 LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPositi
on.toInt()]; | 1696 LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPositi
on.toInt()]; |
1647 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 1697 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
1648 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 1698 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
1649 switch (axisPosition) { | 1699 switch (axisPosition) { |
1650 case GridAxisStart: | 1700 case GridAxisStart: |
1651 return startPosition; | 1701 return startPosition; |
1652 case GridAxisEnd: | 1702 case GridAxisEnd: |
1653 case GridAxisCenter: { | 1703 case GridAxisCenter: { |
1654 LayoutUnit endOfRow = m_rowPositions[coordinate.rows.resolvedFinalPositi
on.next().toInt()]; | 1704 LayoutUnit endOfRow = m_rowPositions[coordinate.rows.resolvedFinalPositi
on.next().toInt()]; |
1655 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil
d.styleRef().alignSelfOverflowAlignment(), endOfRow - startOfRow, child.logicalH
eight() + child.marginLogicalHeight()); | 1705 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(chil
d.styleRef().alignSelfOverflowAlignment(), endOfRow - startOfRow, child.logicalH
eight() + child.marginLogicalHeight()); |
1656 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos
ition : offsetFromStartPosition / 2); | 1706 return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPos
ition : offsetFromStartPosition / 2); |
1657 } | 1707 } |
1658 } | 1708 } |
1659 | 1709 |
1660 ASSERT_NOT_REACHED(); | 1710 ASSERT_NOT_REACHED(); |
1661 return 0; | 1711 return 0; |
1662 } | 1712 } |
1663 | 1713 |
1664 LayoutUnit LayoutGrid::columnPositionForChild(const LayoutBox& child) const | 1714 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child) const |
1665 { | 1715 { |
1666 const GridCoordinate& coordinate = cachedGridCoordinate(child); | 1716 const GridCoordinate& coordinate = cachedGridCoordinate(child); |
1667 LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInit
ialPosition.toInt()]; | 1717 LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInit
ialPosition.toInt()]; |
1668 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 1718 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
1669 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 1719 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
1670 switch (axisPosition) { | 1720 switch (axisPosition) { |
1671 case GridAxisStart: | 1721 case GridAxisStart: |
1672 return startPosition; | 1722 return startPosition; |
1673 case GridAxisEnd: | 1723 case GridAxisEnd: |
1674 case GridAxisCenter: { | 1724 case GridAxisCenter: { |
(...skipping 30 matching lines...) Expand all Loading... |
1705 { | 1755 { |
1706 return isLeftToRight ? LayoutUnit() : availableSpace; | 1756 return isLeftToRight ? LayoutUnit() : availableSpace; |
1707 } | 1757 } |
1708 | 1758 |
1709 static inline LayoutUnit offsetToEndEdge(bool isLeftToRight, LayoutUnit availabl
eSpace) | 1759 static inline LayoutUnit offsetToEndEdge(bool isLeftToRight, LayoutUnit availabl
eSpace) |
1710 { | 1760 { |
1711 return !isLeftToRight ? LayoutUnit() : availableSpace; | 1761 return !isLeftToRight ? LayoutUnit() : availableSpace; |
1712 } | 1762 } |
1713 | 1763 |
1714 | 1764 |
1715 static bool contentDistributionOffset(LayoutUnit availableFreeSpace, ContentPosi
tion& fallbackPosition, ContentDistributionType distribution, unsigned numberOfG
ridTracks, LayoutUnit& positionOffset, LayoutUnit& distributionOffset) | 1765 static ContentAlignmentData contentDistributionOffset(LayoutUnit availableFreeSp
ace, ContentPosition& fallbackPosition, ContentDistributionType distribution, un
signed numberOfGridTracks) |
1716 { | 1766 { |
1717 if (distribution != ContentDistributionDefault && fallbackPosition == Conten
tPositionAuto) | 1767 if (distribution != ContentDistributionDefault && fallbackPosition == Conten
tPositionAuto) |
1718 fallbackPosition = resolveContentDistributionFallback(distribution); | 1768 fallbackPosition = resolveContentDistributionFallback(distribution); |
1719 | 1769 |
1720 if (availableFreeSpace <= 0) | 1770 if (availableFreeSpace <= 0) |
1721 return false; | 1771 return {}; |
1722 | 1772 |
| 1773 LayoutUnit distributionOffset; |
1723 switch (distribution) { | 1774 switch (distribution) { |
1724 case ContentDistributionSpaceBetween: | 1775 case ContentDistributionSpaceBetween: |
1725 if (numberOfGridTracks < 2) | 1776 if (numberOfGridTracks < 2) |
1726 return false; | 1777 return {}; |
1727 distributionOffset = availableFreeSpace / (numberOfGridTracks - 1); | 1778 return {0, availableFreeSpace / (numberOfGridTracks - 1)}; |
1728 positionOffset = 0; | |
1729 return true; | |
1730 case ContentDistributionSpaceAround: | 1779 case ContentDistributionSpaceAround: |
1731 if (numberOfGridTracks < 1) | 1780 if (numberOfGridTracks < 1) |
1732 return false; | 1781 return {}; |
1733 distributionOffset = availableFreeSpace / numberOfGridTracks; | 1782 distributionOffset = availableFreeSpace / numberOfGridTracks; |
1734 positionOffset = distributionOffset / 2; | 1783 return {distributionOffset / 2, distributionOffset}; |
1735 return true; | |
1736 case ContentDistributionSpaceEvenly: | 1784 case ContentDistributionSpaceEvenly: |
1737 distributionOffset = availableFreeSpace / (numberOfGridTracks + 1); | 1785 distributionOffset = availableFreeSpace / (numberOfGridTracks + 1); |
1738 positionOffset = distributionOffset; | 1786 return {distributionOffset, distributionOffset}; |
1739 return true; | |
1740 case ContentDistributionStretch: | 1787 case ContentDistributionStretch: |
1741 distributionOffset = 0; | 1788 return {0, 0}; |
1742 positionOffset = 0; | |
1743 return true; | |
1744 case ContentDistributionDefault: | 1789 case ContentDistributionDefault: |
1745 distributionOffset = 0; | 1790 return {}; |
1746 positionOffset = 0; | |
1747 return false; | |
1748 } | 1791 } |
1749 | 1792 |
1750 ASSERT_NOT_REACHED(); | 1793 ASSERT_NOT_REACHED(); |
1751 return false; | 1794 return {}; |
1752 } | 1795 } |
1753 | 1796 |
1754 void LayoutGrid::computeContentPositionAndDistributionColumnOffset(LayoutUnit av
ailableFreeSpace, GridSizingData& sizingData) const | 1797 ContentAlignmentData LayoutGrid::computeContentPositionAndDistributionOffset(Gri
dTrackSizingDirection direction, LayoutUnit availableFreeSpace, unsigned numberO
fGridTracks) const |
1755 { | 1798 { |
1756 ContentPosition position = styleRef().justifyContentPosition(); | 1799 bool isRowAxis = direction == ForColumns; |
1757 ContentDistributionType distribution = styleRef().justifyContentDistribution
(); | 1800 ContentPosition position = isRowAxis ? styleRef().justifyContentPosition() :
styleRef().alignContentPosition(); |
| 1801 ContentDistributionType distribution = isRowAxis ? styleRef().justifyContent
Distribution() : styleRef().alignContentDistribution(); |
1758 // If <content-distribution> value can't be applied, 'position' will become
the associated | 1802 // If <content-distribution> value can't be applied, 'position' will become
the associated |
1759 // <content-position> fallback value. | 1803 // <content-position> fallback value. |
1760 if (contentDistributionOffset(availableFreeSpace, position, distribution, si
zingData.columnTracks.size(), sizingData.columnsPositionOffset, sizingData.colum
nsDistributionOffset)) | 1804 ContentAlignmentData contentAlignment = contentDistributionOffset(availableF
reeSpace, position, distribution, numberOfGridTracks); |
1761 return; | 1805 if (contentAlignment.isValid()) |
| 1806 return contentAlignment; |
1762 | 1807 |
1763 OverflowAlignment overflow = styleRef().justifyContentOverflowAlignment(); | 1808 OverflowAlignment overflow = isRowAxis ? styleRef().justifyContentOverflowAl
ignment() : styleRef().alignContentOverflowAlignment(); |
1764 if (overflow == OverflowAlignmentSafe && availableFreeSpace <= 0) | 1809 if (availableFreeSpace <= 0 && overflow == OverflowAlignmentSafe) |
1765 return; | 1810 return {0, 0}; |
1766 | 1811 |
1767 switch (position) { | 1812 switch (position) { |
1768 case ContentPositionLeft: | 1813 case ContentPositionLeft: |
1769 sizingData.columnsPositionOffset = 0; | 1814 // The align-content's axis is always orthogonal to the inline-axis. |
1770 return; | 1815 return {0, 0}; |
1771 case ContentPositionRight: | 1816 case ContentPositionRight: |
1772 sizingData.columnsPositionOffset = availableFreeSpace; | 1817 if (isRowAxis) |
1773 return; | 1818 return {availableFreeSpace, 0}; |
| 1819 // The align-content's axis is always orthogonal to the inline-axis. |
| 1820 return {0, 0}; |
1774 case ContentPositionCenter: | 1821 case ContentPositionCenter: |
1775 sizingData.columnsPositionOffset = availableFreeSpace / 2; | 1822 return {availableFreeSpace / 2, 0}; |
1776 return; | 1823 case ContentPositionFlexEnd: // Only used in flex layout, for other layout,
it's equivalent to 'End'. |
1777 case ContentPositionFlexEnd: | |
1778 // Only used in flex layout, for other layout, it's equivalent to 'end'. | |
1779 case ContentPositionEnd: | 1824 case ContentPositionEnd: |
1780 sizingData.columnsPositionOffset = offsetToEndEdge(style()->isLeftToRigh
tDirection(), availableFreeSpace); | 1825 if (isRowAxis) |
1781 return; | 1826 return {offsetToEndEdge(styleRef().isLeftToRightDirection(), availab
leFreeSpace), 0}; |
1782 case ContentPositionFlexStart: | 1827 return {availableFreeSpace, 0}; |
1783 // Only used in flex layout, for other layout, it's equivalent to 'start
'. | 1828 case ContentPositionFlexStart: // Only used in flex layout, for other layout
, it's equivalent to 'Start'. |
1784 case ContentPositionStart: | 1829 case ContentPositionStart: |
1785 sizingData.columnsPositionOffset = offsetToStartEdge(style()->isLeftToRi
ghtDirection(), availableFreeSpace); | 1830 if (isRowAxis) |
1786 return; | 1831 return {offsetToStartEdge(styleRef().isLeftToRightDirection(), avail
ableFreeSpace), 0}; |
| 1832 return {0, 0}; |
1787 case ContentPositionBaseline: | 1833 case ContentPositionBaseline: |
1788 case ContentPositionLastBaseline: | 1834 case ContentPositionLastBaseline: |
1789 // FIXME: These two require implementing Baseline Alignment. For now, we
always 'start' align the child. | 1835 // FIXME: These two require implementing Baseline Alignment. For now, we
always 'start' align the child. |
1790 // crbug.com/234191 | 1836 // crbug.com/234191 |
1791 sizingData.columnsPositionOffset = offsetToStartEdge(style()->isLeftToRi
ghtDirection(), availableFreeSpace); | 1837 if (isRowAxis) |
1792 return; | 1838 return {offsetToStartEdge(styleRef().isLeftToRightDirection(), avail
ableFreeSpace), 0}; |
| 1839 return {0, 0}; |
1793 case ContentPositionAuto: | 1840 case ContentPositionAuto: |
1794 break; | 1841 break; |
1795 } | 1842 } |
1796 | 1843 |
1797 ASSERT_NOT_REACHED(); | 1844 ASSERT_NOT_REACHED(); |
1798 } | 1845 return {0, 0}; |
1799 | |
1800 void LayoutGrid::computeContentPositionAndDistributionRowOffset(LayoutUnit avail
ableFreeSpace, GridSizingData& sizingData) const | |
1801 { | |
1802 ContentPosition position = styleRef().alignContentPosition(); | |
1803 ContentDistributionType distribution = styleRef().alignContentDistribution()
; | |
1804 // If <content-distribution> value can't be applied, 'position' will become
the associated | |
1805 // <content-position> fallback value. | |
1806 if (contentDistributionOffset(availableFreeSpace, position, distribution, si
zingData.rowTracks.size(), sizingData.rowsPositionOffset, sizingData.rowsDistrib
utionOffset)) | |
1807 return; | |
1808 | |
1809 OverflowAlignment overflow = styleRef().alignContentOverflowAlignment(); | |
1810 if (overflow == OverflowAlignmentSafe && availableFreeSpace <= 0) | |
1811 return; | |
1812 | |
1813 switch (position) { | |
1814 case ContentPositionLeft: | |
1815 // The align-content's axis is always orthogonal to the inline-axis. | |
1816 sizingData.rowsPositionOffset = 0; | |
1817 return; | |
1818 case ContentPositionRight: | |
1819 // The align-content's axis is always orthogonal to the inline-axis. | |
1820 sizingData.rowsPositionOffset = 0; | |
1821 return; | |
1822 case ContentPositionCenter: | |
1823 sizingData.rowsPositionOffset = availableFreeSpace / 2; | |
1824 return; | |
1825 case ContentPositionFlexEnd: | |
1826 // Only used in flex layout, for other layout, it's equivalent to 'End'. | |
1827 case ContentPositionEnd: | |
1828 sizingData.rowsPositionOffset = availableFreeSpace; | |
1829 return; | |
1830 case ContentPositionFlexStart: | |
1831 // Only used in flex layout, for other layout, it's equivalent to 'Start
'. | |
1832 case ContentPositionStart: | |
1833 sizingData.rowsPositionOffset = 0; | |
1834 return; | |
1835 case ContentPositionBaseline: | |
1836 case ContentPositionLastBaseline: | |
1837 // FIXME: These two require implementing Baseline Alignment. For now, we
always 'start' align the child. | |
1838 // crbug.com/234191 | |
1839 sizingData.rowsPositionOffset = 0; | |
1840 return; | |
1841 case ContentPositionAuto: | |
1842 break; | |
1843 } | |
1844 | |
1845 ASSERT_NOT_REACHED(); | |
1846 } | 1846 } |
1847 | 1847 |
1848 LayoutPoint LayoutGrid::findChildLogicalPosition(const LayoutBox& child, GridSiz
ingData& sizingData) const | 1848 LayoutPoint LayoutGrid::findChildLogicalPosition(const LayoutBox& child, GridSiz
ingData& sizingData) const |
1849 { | 1849 { |
1850 LayoutUnit columnPosition = columnPositionForChild(child); | 1850 LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child); |
1851 // We stored m_columnPositions's data ignoring the direction, hence we might
need now | 1851 // We stored m_columnPosition s's data ignoring the direction, hence we migh
t need now |
1852 // to translate positions from RTL to LTR, as it's more convenient for paint
ing. | 1852 // to translate positions from RTL to LTR, as it's more convenient for paint
ing. |
1853 if (!style()->isLeftToRightDirection()) | 1853 if (!style()->isLeftToRightDirection()) { |
1854 columnPosition = (m_columnPositions[m_columnPositions.size() - 1] + bord
erAndPaddingLogicalLeft() + sizingData.columnsPositionOffset) - columnPosition -
sizingData.columnsDistributionOffset - child.logicalWidth(); | 1854 LayoutUnit alignmentOffset = m_columnPositions[0] - borderAndPaddingSta
rt(); |
| 1855 LayoutUnit rightGridEdgePosition = m_columnPositions[m_columnPositions.s
ize() - 1] + alignmentOffset + borderAndPaddingLogicalLeft(); |
| 1856 rowAxisOffset = rightGridEdgePosition - (rowAxisOffset + child.logicalWi
dth()); |
| 1857 } |
1855 | 1858 |
1856 return LayoutPoint(columnPosition, rowPositionForChild(child)); | 1859 return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child)); |
1857 } | 1860 } |
1858 | 1861 |
1859 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) | 1862 void LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) |
1860 { | 1863 { |
1861 GridPainter(*this).paintChildren(paintInfo, paintOffset); | 1864 GridPainter(*this).paintChildren(paintInfo, paintOffset); |
1862 } | 1865 } |
1863 | 1866 |
1864 } // namespace blink | 1867 } // namespace blink |
OLD | NEW |