From 8be7bfbd5b92fcc1d69eb558f72f80561e0a25b0 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Sat, 12 Oct 2019 17:15:43 +0000 Subject: [PATCH] Bug 1234311 part 1 - [css-grid][css-grid-2] Simplify and improve calculation of 'grid-template-rows/columns' resolved value when the element has no box. r=dholbert Differential Revision: https://phabricator.services.mozilla.com/D49026 --HG-- extra : moz-landing-system : lando --- layout/style/nsComputedDOMStyle.cpp | 336 ++++++++++++---------------- layout/style/nsComputedDOMStyle.h | 2 +- 2 files changed, 140 insertions(+), 198 deletions(-) diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 6482bb379d93..c9a87040b203 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -1547,7 +1547,7 @@ already_AddRefed nsComputedDOMStyle::GetGridTrackSize( already_AddRefed nsComputedDOMStyle::GetGridTemplateColumnsRows( const StyleGridTemplateComponent& aTrackList, - const ComputedGridTrackInfo* aTrackInfo) { + const ComputedGridTrackInfo& aTrackInfo) { if (aTrackList.IsSubgrid()) { // XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311) RefPtr valueList = GetROCSSValueList(false); @@ -1575,235 +1575,177 @@ already_AddRefed nsComputedDOMStyle::GetGridTemplateColumnsRows( } return valueList.forget(); } + + uint32_t numSizes = aTrackInfo.mSizes.Length(); + if (!numSizes && !aTrackList.HasRepeatAuto()) { + RefPtr val = new nsROCSSPrimitiveValue; + val->SetIdent(eCSSKeyword_none); + return val.forget(); + } + + // We've done layout on the grid and have resolved the sizes of its tracks, + // so we'll return those sizes here. The grid spec says we MAY use + // repeat(, Npx) here for consecutive tracks with the same + // size, but that doesn't seem worth doing since even for repeat(auto-*) + // the resolved size might differ for the repeated tracks. RefPtr valueList = GetROCSSValueList(false); - if (aTrackInfo) { - uint32_t numSizes = aTrackInfo->mSizes.Length(); - if (!numSizes && !aTrackList.HasRepeatAuto()) { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetIdent(eCSSKeyword_none); - return val.forget(); + const nsTArray& trackSizes = aTrackInfo.mSizes; + const uint32_t numExplicitTracks = aTrackInfo.mNumExplicitTracks; + const uint32_t numLeadingImplicitTracks = + aTrackInfo.mNumLeadingImplicitTracks; + MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks); + + // Add any leading implicit tracks. + for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) { + RefPtr val = new nsROCSSPrimitiveValue; + val->SetAppUnits(trackSizes[i]); + valueList->AppendCSSValue(val.forget()); + } + + // Then add any explicit tracks and removed auto-fit tracks. + if (numExplicitTracks || aTrackList.HasRepeatAuto()) { + uint32_t endOfRepeat = 0; // first index after any repeat() tracks + int32_t offsetToLastRepeat = 0; + if (aTrackList.HasRepeatAuto()) { + // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty + offsetToLastRepeat = + numExplicitTracks + 1 - aTrackInfo.mResolvedLineNames.Length(); + endOfRepeat = aTrackInfo.mRepeatFirstTrack + offsetToLastRepeat + 1; } - // We've done layout on the grid and have resolved the sizes of its tracks, - // so we'll return those sizes here. The grid spec says we MAY use - // repeat(, Npx) here for consecutive tracks with the same - // size, but that doesn't seem worth doing since even for repeat(auto-*) - // the resolved size might differ for the repeated tracks. - const nsTArray& trackSizes = aTrackInfo->mSizes; - const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks; - const uint32_t numLeadingImplicitTracks = - aTrackInfo->mNumLeadingImplicitTracks; - MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks); + auto* autoRepeatValue = aTrackList.GetRepeatAutoValue(); + auto beforeAutoRepeat = + autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[0].AsSpan() + : Span(); + auto afterAutoRepeat = + autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan() + : Span(); + uint32_t repeatIndex = 0; + uint32_t numRepeatTracks = aTrackInfo.mRemovedRepeatTracks.Length(); + enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween }; + auto AppendRemovedAutoFits = + [&aTrackInfo, &valueList, aTrackList, beforeAutoRepeat, afterAutoRepeat, + &repeatIndex, numRepeatTracks](LinePlacement aPlacement) { + // Add in removed auto-fit tracks and lines here, if necessary + bool atLeastOneTrackReported = false; + while (repeatIndex < numRepeatTracks && + aTrackInfo.mRemovedRepeatTracks[repeatIndex]) { + if ((aPlacement == LinesPrecede) || + ((aPlacement == LinesBetween) && atLeastOneTrackReported)) { + // Precede it with the lines between repeats. + AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); + } - // Add any leading implicit tracks. - for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetAppUnits(trackSizes[i]); - valueList->AppendCSSValue(val.forget()); - } + // Removed 'auto-fit' tracks are reported as 0px. + RefPtr val = new nsROCSSPrimitiveValue; + val->SetAppUnits(0); + valueList->AppendCSSValue(val.forget()); + atLeastOneTrackReported = true; - // Then add any explicit tracks and removed auto-fit tracks. - if (numExplicitTracks || aTrackList.HasRepeatAuto()) { - uint32_t endOfRepeat = 0; // first index after any repeat() tracks - int32_t offsetToLastRepeat = 0; - if (aTrackList.HasRepeatAuto()) { - // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty - offsetToLastRepeat = - numExplicitTracks + 1 - aTrackInfo->mResolvedLineNames.Length(); - endOfRepeat = aTrackInfo->mRepeatFirstTrack + offsetToLastRepeat + 1; - } - - auto* autoRepeatValue = aTrackList.GetRepeatAutoValue(); - auto beforeAutoRepeat = - autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[0].AsSpan() - : Span(); - auto afterAutoRepeat = - autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan() - : Span(); - uint32_t repeatIndex = 0; - uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length(); - enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween }; - auto AppendRemovedAutoFits = [aTrackInfo, &valueList, aTrackList, - beforeAutoRepeat, afterAutoRepeat, - &repeatIndex, - numRepeatTracks](LinePlacement aPlacement) { - // Add in removed auto-fit tracks and lines here, if necessary - bool atLeastOneTrackReported = false; - while (repeatIndex < numRepeatTracks && - aTrackInfo->mRemovedRepeatTracks[repeatIndex]) { - if ((aPlacement == LinesPrecede) || - ((aPlacement == LinesBetween) && atLeastOneTrackReported)) { - // Precede it with the lines between repeats. - AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); - } - - // Removed 'auto-fit' tracks are reported as 0px. - RefPtr val = new nsROCSSPrimitiveValue; - val->SetAppUnits(0); - valueList->AppendCSSValue(val.forget()); - atLeastOneTrackReported = true; - - if (aPlacement == LinesFollow) { - // Follow it with the lines between repeats. - AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); + if (aPlacement == LinesFollow) { + // Follow it with the lines between repeats. + AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); + } + repeatIndex++; } repeatIndex++; - } - repeatIndex++; - }; + }; - for (uint32_t i = 0;; i++) { - if (aTrackList.HasRepeatAuto()) { - if (i == aTrackInfo->mRepeatFirstTrack) { - const nsTArray& lineNames = - aTrackInfo->mResolvedLineNames[i]; - if (i == endOfRepeat) { - // All auto-fit tracks are empty, but we report them anyway. - AppendGridLineNames(valueList, lineNames); - - AppendRemovedAutoFits(LinesBetween); - - AppendGridLineNames(valueList, - aTrackInfo->mResolvedLineNames[i + 1]); - } else { - AppendGridLineNames(valueList, lineNames); - AppendRemovedAutoFits(LinesFollow); - } - } else if (i == endOfRepeat) { - // Before appending the last line, finish off any removed auto-fits. - AppendRemovedAutoFits(LinesPrecede); - - const nsTArray& lineNames = - aTrackInfo - ->mResolvedLineNames[aTrackInfo->mRepeatFirstTrack + 1]; - AppendGridLineNames(valueList, lineNames); - } else if (i > aTrackInfo->mRepeatFirstTrack && i < endOfRepeat) { - AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); - AppendRemovedAutoFits(LinesFollow); - } else { - uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i; - const nsTArray& lineNames = - aTrackInfo->mResolvedLineNames[j]; - AppendGridLineNames(valueList, lineNames); - } - } else { + for (uint32_t i = 0;; i++) { + if (aTrackList.HasRepeatAuto()) { + if (i == aTrackInfo.mRepeatFirstTrack) { const nsTArray& lineNames = - aTrackInfo->mResolvedLineNames[i]; + aTrackInfo.mResolvedLineNames[i]; + if (i == endOfRepeat) { + // All auto-fit tracks are empty, but we report them anyway. + AppendGridLineNames(valueList, lineNames); + + AppendRemovedAutoFits(LinesBetween); + + AppendGridLineNames(valueList, + aTrackInfo.mResolvedLineNames[i + 1]); + } else { + AppendGridLineNames(valueList, lineNames); + AppendRemovedAutoFits(LinesFollow); + } + } else if (i == endOfRepeat) { + // Before appending the last line, finish off any removed auto-fits. + AppendRemovedAutoFits(LinesPrecede); + + const nsTArray& lineNames = + aTrackInfo.mResolvedLineNames[aTrackInfo.mRepeatFirstTrack + 1]; + AppendGridLineNames(valueList, lineNames); + } else if (i > aTrackInfo.mRepeatFirstTrack && i < endOfRepeat) { + AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat); + AppendRemovedAutoFits(LinesFollow); + } else { + uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i; + const nsTArray& lineNames = + aTrackInfo.mResolvedLineNames[j]; AppendGridLineNames(valueList, lineNames); } - if (i == numExplicitTracks) { - break; - } - RefPtr val = new nsROCSSPrimitiveValue; - val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]); - valueList->AppendCSSValue(val.forget()); + } else { + const nsTArray& lineNames = + aTrackInfo.mResolvedLineNames[i]; + AppendGridLineNames(valueList, lineNames); } - } - - // Add any trailing implicit tracks. - for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks; - i < numSizes; ++i) { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetAppUnits(trackSizes[i]); - valueList->AppendCSSValue(val.forget()); - } - } else { - if (aTrackList.IsNone()) { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetIdent(eCSSKeyword_none); - return val.forget(); - } - // We don't have a frame. So, we'll just return a serialization of - // the tracks from the style (without resolved sizes). - auto& trackList = *aTrackList.AsTrackList(); - auto nameLists = trackList.line_names.AsSpan(); - auto values = trackList.values.AsSpan(); - uint32_t numSizes = values.Length(); - for (uint32_t i = 0;; i++) { - auto names = nameLists[i].AsSpan(); - if (!names.IsEmpty()) { - AppendGridLineNames(valueList, names); - } - if (i == numSizes) { + if (i == numExplicitTracks) { break; } - auto& value = values[i]; - if (value.IsTrackRepeat()) { - auto& repeat = value.AsTrackRepeat(); - nsAutoString string; - string.AppendLiteral("repeat("); - if (repeat.count.IsNumber()) { - nsStyleUtil::AppendCSSNumber(repeat.count.AsNumber(), string); - } else if (repeat.count.IsAutoFit()) { - string.AppendLiteral("auto-fit"); - } else { - MOZ_ASSERT(repeat.count.IsAutoFill()); - string.AppendLiteral("auto-fill"); - } - string.AppendLiteral(","); - - auto repeat_names = repeat.line_names.AsSpan(); - auto repeat_sizes = repeat.track_sizes.AsSpan(); - MOZ_ASSERT(repeat_names.Length() == repeat_sizes.Length() || - repeat_names.Length() == repeat_sizes.Length() + 1); - for (auto i : IntegerRange(repeat_sizes.Length())) { - auto names = repeat_names[i]; - if (!names.IsEmpty()) { - string.Append(' '); - AppendGridLineNames(string, names.AsSpan(), Brackets::Yes); - } - string.Append(' '); - RefPtr size = - GetGridTrackSize(repeat_sizes[i]); - nsAutoString tmp; - size->GetCssText(tmp); - string.Append(tmp); - } - if (repeat_names.Length() == repeat_sizes.Length() + 1) { - auto lastList = repeat_names[repeat_sizes.Length()].AsSpan(); - if (!lastList.IsEmpty()) { - string.Append(' '); - AppendGridLineNames(string, lastList, Brackets::Yes); - } - } - string.Append(')'); - RefPtr value = new nsROCSSPrimitiveValue; - value->SetString(string); - valueList->AppendCSSValue(value.forget()); - } else { - valueList->AppendCSSValue(GetGridTrackSize(value.AsTrackSize())); - } + RefPtr val = new nsROCSSPrimitiveValue; + val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]); + valueList->AppendCSSValue(val.forget()); } } + // Add any trailing implicit tracks. + for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks; i < numSizes; + ++i) { + RefPtr val = new nsROCSSPrimitiveValue; + val->SetAppUnits(trackSizes[i]); + valueList->AppendCSSValue(val.forget()); + } + return valueList.forget(); } already_AddRefed nsComputedDOMStyle::DoGetGridTemplateColumns() { - const ComputedGridTrackInfo* info = nullptr; - nsGridContainerFrame* gridFrame = nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame); - - if (gridFrame) { - info = gridFrame->GetComputedTemplateColumns(); + if (!gridFrame) { + // The element doesn't have a box - return the computed value. + // https://drafts.csswg.org/css-grid/#resolved-track-list + nsAutoString string; + Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_columns, + &string); + RefPtr value = new nsROCSSPrimitiveValue; + value->SetString(string); + return value.forget(); } + // GetGridFrameWithComputedInfo() above ensures that this returns non-null: + const ComputedGridTrackInfo* info = gridFrame->GetComputedTemplateColumns(); return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, - info); + *info); } already_AddRefed nsComputedDOMStyle::DoGetGridTemplateRows() { - const ComputedGridTrackInfo* info = nullptr; - nsGridContainerFrame* gridFrame = nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame); - - if (gridFrame) { - info = gridFrame->GetComputedTemplateRows(); + if (!gridFrame) { + // The element doesn't have a box - return the computed value. + // https://drafts.csswg.org/css-grid/#resolved-track-list + nsAutoString string; + Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_rows, + &string); + RefPtr value = new nsROCSSPrimitiveValue; + value->SetString(string); + return value.forget(); } - return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info); + // GetGridFrameWithComputedInfo() above ensures that this returns non-null: + const ComputedGridTrackInfo* info = gridFrame->GetComputedTemplateRows(); + return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, *info); } already_AddRefed nsComputedDOMStyle::DoGetPaddingTop() { diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 0aded9246f70..945c1190d6d2 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -197,7 +197,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration, const mozilla::StyleTrackBreadth&); already_AddRefed GetGridTemplateColumnsRows( const mozilla::StyleGridTemplateComponent& aTrackList, - const mozilla::ComputedGridTrackInfo* aTrackInfo); + const mozilla::ComputedGridTrackInfo& aTrackInfo); bool GetLineHeightCoord(nscoord& aCoord);