GridPosition StyleBuilderConverter::convertGridPosition(StyleResolverState&, CSSValue* value) { // We accept the specification's grammar: // 'auto' | [ <integer> || <custom-ident> ] | [ span && [ <integer> || <custom-ident> ] ] | <custom-ident> GridPosition position; if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); // We translate <custom-ident> to <string> during parsing as it // makes handling it more simple. if (primitiveValue->isString()) { position.setNamedGridArea(primitiveValue->getStringValue()); return position; } ASSERT(primitiveValue->getValueID() == CSSValueAuto); return position; } CSSValueList* values = toCSSValueList(value); ASSERT(values->length()); bool isSpanPosition = false; // The specification makes the <integer> optional, in which case it default to '1'. int gridLineNumber = 1; String gridLineName; CSSValueListIterator it = values; CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value()); if (currentValue->getValueID() == CSSValueSpan) { isSpanPosition = true; it.advance(); currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; } if (currentValue && currentValue->isNumber()) { gridLineNumber = currentValue->getIntValue(); it.advance(); currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; } if (currentValue && currentValue->isString()) { gridLineName = currentValue->getStringValue(); it.advance(); } ASSERT(!it.hasMore()); if (isSpanPosition) position.setSpanPosition(gridLineNumber, gridLineName); else position.setExplicitPosition(gridLineNumber, gridLineName); return position; }
static int resolveNamedGridLinePositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side, unsigned autoRepeatTracksCount) { ASSERT(!position.namedGridLine().isNull()); unsigned lastLine = explicitGridSizeForSide(gridContainerStyle, side, autoRepeatTracksCount); NamedLineCollection linesCollection(gridContainerStyle, position.namedGridLine(), directionFromSide(side), lastLine, autoRepeatTracksCount); if (position.isPositive()) return lookAheadForNamedGridLine(0, std::abs(position.integerPosition()), lastLine, linesCollection); return lookBackForNamedGridLine(lastLine, std::abs(position.integerPosition()), lastLine, linesCollection); }
static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, int oppositeLine, const GridPosition& position, GridPositionSide side, unsigned autoRepeatTracksCount) { ASSERT(position.isSpan()); ASSERT(!position.namedGridLine().isNull()); // Negative positions are not allowed per the specification and should have been handled during parsing. ASSERT(position.spanPosition() > 0); unsigned lastLine = explicitGridSizeForSide(gridContainerStyle, side, autoRepeatTracksCount); NamedLineCollection linesCollection(gridContainerStyle, position.namedGridLine(), directionFromSide(side), lastLine, autoRepeatTracksCount); return definiteGridSpanWithNamedLineSpanAgainstOpposite(oppositeLine, position, side, lastLine, linesCollection); }
static GridSpan definiteGridSpanWithNamedLineSpanAgainstOpposite(int oppositeLine, const GridPosition& position, GridPositionSide side, unsigned lastLine, NamedLineCollection& linesCollection) { int start, end; if (side == RowStartSide || side == ColumnStartSide) { start = lookBackForNamedGridLine(oppositeLine - 1, position.spanPosition(), lastLine, linesCollection); end = oppositeLine; } else { start = oppositeLine; end = lookAheadForNamedGridLine(oppositeLine + 1, position.spanPosition(), lastLine, linesCollection); } return GridSpan::untranslatedDefiniteGridSpan(start, end); }
PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side) { if (position.isAuto()) return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition); ASSERT(position.isSpan()); ASSERT(position.spanPosition() > 0); if (!position.namedGridLine().isNull()) { // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position. return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side); } return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, position, side); }
PassOwnPtr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side) { ASSERT(position.isSpan()); ASSERT(!position.namedGridLine().isNull()); // Negative positions are not allowed per the specification and should have been handled during parsing. ASSERT(position.spanPosition() > 0); const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? gridContainerStyle.namedGridColumnLines() : gridContainerStyle.namedGridRowLines(); NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine()); // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case). // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html. if (it == gridLinesNames.end()) return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition); return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, it->value); }
unsigned GridPositionsResolver::spanSizeForAutoPlacedItem(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction) { GridPosition initialPosition, finalPosition; adjustGridPositionsFromStyle(gridContainerStyle, gridItem, direction, initialPosition, finalPosition); // This method will only be used when both positions need to be resolved against the opposite one. ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()); if (initialPosition.isAuto() && finalPosition.isAuto()) return 1; GridPosition position = initialPosition.isSpan() ? initialPosition : finalPosition; ASSERT(position.isSpan()); ASSERT(position.spanPosition()); return position.spanPosition(); }
GridSpan GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side) { if (position.isAuto()) { if ((side == ColumnStartSide || side == RowStartSide) && resolvedOppositePosition.toInt()) return GridSpan::definiteGridSpan(resolvedOppositePosition.prev(), resolvedOppositePosition); return GridSpan::definiteGridSpan(resolvedOppositePosition, resolvedOppositePosition.next()); } ASSERT(position.isSpan()); ASSERT(position.spanPosition() > 0); if (!position.namedGridLine().isNull()) { // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position. return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side); } return GridSpan::definiteGridSpanWithSpanAgainstOpposite(resolvedOppositePosition, position, side); }
size_t RenderGrid::resolveGridPosition(const GridPosition& position) const { // FIXME: Handle other values for grid-{row,column} like ranges or line names. switch (position.type()) { case IntegerPosition: // FIXME: What does a non-positive integer mean for a column/row? if (!position.isPositive()) return 0; return position.integerPosition() - 1; case AutoPosition: // FIXME: We should follow 'grid-auto-flow' for resolution. // Until then, we use the 'grid-auto-flow: none' behavior (which is the default) // and resolve 'auto' as the first row / column. return 0; } ASSERT_NOT_REACHED(); return 0; }
GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) { switch (position.type()) { case ExplicitPosition: { ASSERT(position.integerPosition()); if (!position.namedGridLine().isNull()) return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side); // Handle <integer> explicit position. if (position.isPositive()) return GridResolvedPosition::adjustGridPositionForSide(position.integerPosition() - 1, side); size_t resolvedPosition = abs(position.integerPosition()) - 1; const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side); // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line. if (endOfTrack < resolvedPosition) return 0; return GridResolvedPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side); } case NamedGridAreaPosition: { // First attempt to match the grid area's edge to a named grid area: if there is a named line with the name // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such // line to the grid item's placement. String namedGridLine = position.namedGridLine(); ASSERT(!isNonExistentNamedLineOrArea(namedGridLine, gridContainerStyle, side)); const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerStyle, side); auto implicitLine = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side)); if (implicitLine != gridLineNames.end()) return GridResolvedPosition::adjustGridPositionForSide(implicitLine->value[0], side); // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid // item's placement. auto explicitLine = gridLineNames.find(namedGridLine); if (explicitLine != gridLineNames.end()) return GridResolvedPosition::adjustGridPositionForSide(explicitLine->value[0], side); // If none of the above works specs mandate us to treat it as auto BUT we should have detected it before calling // this function in resolveGridPositionsFromStyle(). We should be covered anyway by the ASSERT at the beginning // of this case block. ASSERT_NOT_REACHED(); return 0; } case AutoPosition: case SpanPosition: // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader"). ASSERT_NOT_REACHED(); return GridResolvedPosition(0); } ASSERT_NOT_REACHED(); return GridResolvedPosition(0); }
static int resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side, unsigned autoRepeatTracksCount) { switch (position.type()) { case ExplicitPosition: { ASSERT(position.integerPosition()); if (!position.namedGridLine().isNull()) return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side, autoRepeatTracksCount); // Handle <integer> explicit position. if (position.isPositive()) return position.integerPosition() - 1; unsigned resolvedPosition = std::abs(position.integerPosition()) - 1; const unsigned endOfTrack = explicitGridSizeForSide(gridContainerStyle, side, autoRepeatTracksCount); return endOfTrack - resolvedPosition; } case NamedGridAreaPosition: { // First attempt to match the grid area's edge to a named grid area: if there is a named line with the name // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such // line to the grid item's placement. String namedGridLine = position.namedGridLine(); ASSERT(!position.namedGridLine().isNull()); unsigned lastLine = explicitGridSizeForSide(gridContainerStyle, side, autoRepeatTracksCount); NamedLineCollection implicitLines(gridContainerStyle, implicitNamedGridLineForSide(namedGridLine, side), directionFromSide(side), lastLine, autoRepeatTracksCount); if (implicitLines.hasNamedLines()) return implicitLines.firstPosition(); // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid // item's placement. NamedLineCollection explicitLines(gridContainerStyle, namedGridLine, directionFromSide(side), lastLine, autoRepeatTracksCount); if (explicitLines.hasNamedLines()) return explicitLines.firstPosition(); ASSERT(!NamedLineCollection::isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side)); // If none of the above works specs mandate to assume that all the lines in the implicit grid have this name. return lastLine + 1; } case AutoPosition: case SpanPosition: // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader"). ASSERT_NOT_REACHED(); return 0; } ASSERT_NOT_REACHED(); return 0; }
std::unique_ptr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side) { if (position.isAuto()) return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition); ASSERT(position.isSpan()); ASSERT(position.spanPosition() > 0); if (!position.namedGridLine().isNull()) { // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position. return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side); } // 'span 1' is contained inside a single grid track regardless of the direction. // That's why the CSS span value is one more than the offset we apply. size_t positionOffset = position.spanPosition() - 1; if (isStartSide(side)) { size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition.toInt() - positionOffset); return std::make_unique<GridSpan>(initialResolvedPosition, resolvedOppositePosition); } return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition.toInt() + positionOffset); }
static GridSpan resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, int oppositeLine, const GridPosition& position, GridPositionSide side, unsigned autoRepeatTracksCount) { if (position.isAuto()) { if (isStartSide(side)) return GridSpan::untranslatedDefiniteGridSpan(oppositeLine - 1, oppositeLine); return GridSpan::untranslatedDefiniteGridSpan(oppositeLine, oppositeLine + 1); } ASSERT(position.isSpan()); ASSERT(position.spanPosition() > 0); if (!position.namedGridLine().isNull()) { // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position. return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, oppositeLine, position, side, autoRepeatTracksCount); } // 'span 1' is contained inside a single grid track regardless of the direction. // That's why the CSS span value is one more than the offset we apply. unsigned positionOffset = position.spanPosition(); if (isStartSide(side)) return GridSpan::untranslatedDefiniteGridSpan(oppositeLine - positionOffset, oppositeLine); return GridSpan::untranslatedDefiniteGridSpan(oppositeLine, oppositeLine + positionOffset); }
GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) { switch (position.type()) { case ExplicitPosition: { ASSERT(position.integerPosition()); if (!position.namedGridLine().isNull()) return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side); // Handle <integer> explicit position. if (position.isPositive()) return adjustGridPositionForSide(position.integerPosition() - 1, side); size_t resolvedPosition = abs(position.integerPosition()) - 1; const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side); // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line. if (endOfTrack < resolvedPosition) return GridResolvedPosition(0); return adjustGridPositionForSide(endOfTrack - resolvedPosition, side); } case NamedGridAreaPosition: { NamedGridAreaMap::const_iterator it = gridContainerStyle.namedGridArea().find(position.namedGridLine()); // Unknown grid area should have been computed to 'auto' by now. ASSERT_WITH_SECURITY_IMPLICATION(it != gridContainerStyle.namedGridArea().end()); const GridCoordinate& gridAreaCoordinate = it->value; switch (side) { case ColumnStartSide: return gridAreaCoordinate.columns.resolvedInitialPosition; case ColumnEndSide: return gridAreaCoordinate.columns.resolvedFinalPosition; case RowStartSide: return gridAreaCoordinate.rows.resolvedInitialPosition; case RowEndSide: return GridResolvedPosition(gridAreaCoordinate.rows.resolvedFinalPosition); } ASSERT_NOT_REACHED(); return GridResolvedPosition(0); } case AutoPosition: case SpanPosition: // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader"). ASSERT_NOT_REACHED(); return GridResolvedPosition(0); } ASSERT_NOT_REACHED(); return GridResolvedPosition(0); }
GridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) { ASSERT(!position.namedGridLine().isNull()); const NamedGridLinesMap& gridLinesNames = isColumnSide(side) ? gridContainerStyle.namedGridColumnLines() : gridContainerStyle.namedGridRowLines(); NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine()); if (it == gridLinesNames.end()) { if (position.isPositive()) return 0; const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side); return GridResolvedPosition::adjustGridPositionForSide(lastLine, side); } size_t namedGridLineIndex; if (position.isPositive()) namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1; else namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0); return GridResolvedPosition::adjustGridPositionForSide(it->value[namedGridLineIndex], side); }
GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, const GridResolvedPosition& resolvedInitialPosition) { GridPosition initialPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnStart() : gridItem.style().gridItemRowStart(); const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide; GridPosition finalPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnEnd() : gridItem.style().gridItemRowEnd(); const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide; adjustGridPositionsFromStyle(gridContainerStyle, initialPosition, finalPosition, initialPositionSide, finalPositionSide); // This method will only be used when both positions need to be resolved against the opposite one. ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()); GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition; if (initialPosition.isSpan()) resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, initialPosition, finalPositionSide)->resolvedFinalPosition; else if (finalPosition.isSpan()) resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, finalPosition, finalPositionSide)->resolvedFinalPosition; return GridSpan(resolvedInitialPosition, resolvedFinalPosition); }
std::unique_ptr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction) { GridPosition initialPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnStart() : gridItem.style().gridItemRowStart(); const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide; GridPosition finalPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnEnd() : gridItem.style().gridItemRowEnd(); const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide; adjustGridPositionsFromStyle(gridContainerStyle, initialPosition, finalPosition, initialPositionSide, finalPositionSide); if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) { if (gridContainerStyle.gridAutoFlow() == AutoFlowNone) return std::make_unique<GridSpan>(0, 0); // We can't get our grid positions without running the auto placement algorithm. return nullptr; } if (initialPosition.shouldBeResolvedAgainstOppositePosition()) { // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case). const GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide); return resolveGridPositionAgainstOppositePosition(gridContainerStyle, finalResolvedPosition, initialPosition, initialPositionSide); } if (finalPosition.shouldBeResolvedAgainstOppositePosition()) { // Infer our position from the initial position ('1 / auto' or '3 / span 2' case). const GridResolvedPosition initialResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide); return resolveGridPositionAgainstOppositePosition(gridContainerStyle, initialResolvedPosition, finalPosition, finalPositionSide); } GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide); GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide); // If 'grid-row-end' specifies a line at or before that specified by 'grid-row-start', it computes to 'span 1'. if (resolvedFinalPosition < resolvedInitialPosition) resolvedFinalPosition = resolvedInitialPosition; return std::make_unique<GridSpan>(resolvedInitialPosition, resolvedFinalPosition); }
std::unique_ptr<GridSpan> GridResolvedPosition::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) { size_t gridLineIndex = std::max<int>(0, firstNamedGridLineBeforePosition(resolvedOppositePosition.toInt(), gridLines) - position.spanPosition() + 1); GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition(gridLines[gridLineIndex]); if (resolvedGridLinePosition > resolvedOppositePosition) resolvedGridLinePosition = resolvedOppositePosition; return std::make_unique<GridSpan>(resolvedGridLinePosition, resolvedOppositePosition); }
PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction) { GridPosition initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnStart() : gridItem.style()->gridRowStart(); const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide; GridPosition finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd() : gridItem.style()->gridRowEnd(); const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide; // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to // overwrite the specified values. if (initialPosition.isSpan() && finalPosition.isSpan()) finalPosition.setAutoPosition(); if (initialPosition.isNamedGridArea() && !gridContainerStyle.namedGridArea().contains(initialPosition.namedGridLine())) initialPosition.setAutoPosition(); if (finalPosition.isNamedGridArea() && !gridContainerStyle.namedGridArea().contains(finalPosition.namedGridLine())) finalPosition.setAutoPosition(); if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) { if (gridContainerStyle.gridAutoFlow() == AutoFlowNone) return adoptPtr(new GridSpan(0, 0)); // We can't get our grid positions without running the auto placement algorithm. return nullptr; } if (initialPosition.shouldBeResolvedAgainstOppositePosition()) { // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case). GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide); return resolveGridPositionAgainstOppositePosition(gridContainerStyle, finalResolvedPosition, initialPosition, initialPositionSide); } if (finalPosition.shouldBeResolvedAgainstOppositePosition()) { // Infer our position from the initial position ('1 / auto' or '3 / span 2' case). GridResolvedPosition initialResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide); return resolveGridPositionAgainstOppositePosition(gridContainerStyle, initialResolvedPosition, finalPosition, finalPositionSide); } GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide); GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide); // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'. if (resolvedFinalPosition < resolvedInitialPosition) resolvedFinalPosition = resolvedInitialPosition; return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition)); }
static void adjustGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, GridPosition& initialPosition, GridPosition& finalPosition) { bool isForColumns = direction == ForColumns; initialPosition = isForColumns ? gridItem.style().gridItemColumnStart() : gridItem.style().gridItemRowStart(); finalPosition = isForColumns ? gridItem.style().gridItemColumnEnd() : gridItem.style().gridItemRowEnd(); // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to // overwrite the specified values. if (initialPosition.isSpan() && finalPosition.isSpan()) finalPosition.setAutoPosition(); if (gridItem.isOutOfFlowPositioned()) { // Early detect the case of non existing named grid lines for positioned items. if (initialPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide(direction))) initialPosition.setAutoPosition(); if (finalPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide(direction))) finalPosition.setAutoPosition(); } // If the grid item has an automatic position and a grid span for a named line in a given dimension, instead treat the grid span as one. if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull()) finalPosition.setSpanPosition(1, String()); if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull()) initialPosition.setSpanPosition(1, String()); }
void GridResolvedPosition::adjustGridPositionsFromStyle(const RenderStyle& gridContainerStyle, GridPosition& initialPosition, GridPosition& finalPosition, GridPositionSide initialPositionSide, GridPositionSide finalPositionSide) { ASSERT(isColumnSide(initialPositionSide) == isColumnSide(finalPositionSide)); // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to // overwrite the specified values. if (initialPosition.isSpan() && finalPosition.isSpan()) finalPosition.setAutoPosition(); // Try to early detect the case of non existing named grid lines. This way we could assume later that // GridResolvedPosition::resolveGrisPositionFromStyle() won't require the autoplacement to run, i.e., it'll always return a // valid resolved position. if (initialPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide)) initialPosition.setAutoPosition(); if (finalPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide)) finalPosition.setAutoPosition(); // If the grid item has an automatic position and a grid span for a named line in a given dimension, instead treat the grid span as one. if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull()) finalPosition.setSpanPosition(1, String()); if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull()) initialPosition.setSpanPosition(1, String()); }
std::unique_ptr<GridSpan> GridResolvedPosition::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) { size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1; const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition); if (firstLineAfterOppositePosition != gridLines.end()) firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin(); size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1); GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition::adjustGridPositionForRowEndColumnEndSide(gridLines[gridLineIndex]); if (resolvedGridLinePosition < resolvedOppositePosition) resolvedGridLinePosition = resolvedOppositePosition; return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedGridLinePosition); }
void GridResolvedPosition::initialAndFinalPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, GridPosition& initialPosition, GridPosition& finalPosition) { initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnStart() : gridItem.style()->gridRowStart(); finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd() : gridItem.style()->gridRowEnd(); GridPositionSide initialPositionSide = calculateInitialPositionSide(direction); GridPositionSide finalPositionSide = calculateFinalPositionSide(direction); // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to // overwrite the specified values. if (initialPosition.isSpan() && finalPosition.isSpan()) finalPosition.setAutoPosition(); // Try to early detect the case of non existing named grid lines. This way we could assume later that // GridResolvedPosition::resolveGrisPositionFromStyle() always return a valid resolved position. if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide)) initialPosition.setAutoPosition(); if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide)) finalPosition.setAutoPosition(); // If the grid item has an automatic position and a grid span for a named line in a given dimension, instead treat the grid span as one. if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull()) finalPosition.setSpanPosition(1, String()); if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull()) initialPosition.setSpanPosition(1, String()); }