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
This commit is contained in:
Mats Palmgren 2019-10-12 17:15:43 +00:00
Родитель cb5a3a5401
Коммит 8be7bfbd5b
2 изменённых файлов: 140 добавлений и 198 удалений

Просмотреть файл

@ -1547,7 +1547,7 @@ already_AddRefed<nsROCSSPrimitiveValue> nsComputedDOMStyle::GetGridTrackSize(
already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows( already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
const StyleGridTemplateComponent& aTrackList, const StyleGridTemplateComponent& aTrackList,
const ComputedGridTrackInfo* aTrackInfo) { const ComputedGridTrackInfo& aTrackInfo) {
if (aTrackList.IsSubgrid()) { if (aTrackList.IsSubgrid()) {
// XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311) // XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311)
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false); RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
@ -1575,235 +1575,177 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
} }
return valueList.forget(); return valueList.forget();
} }
uint32_t numSizes = aTrackInfo.mSizes.Length();
if (!numSizes && !aTrackList.HasRepeatAuto()) {
RefPtr<nsROCSSPrimitiveValue> 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(<positive-integer>, 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<nsDOMCSSValueList> valueList = GetROCSSValueList(false); RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
if (aTrackInfo) { const nsTArray<nscoord>& trackSizes = aTrackInfo.mSizes;
uint32_t numSizes = aTrackInfo->mSizes.Length(); const uint32_t numExplicitTracks = aTrackInfo.mNumExplicitTracks;
if (!numSizes && !aTrackList.HasRepeatAuto()) { const uint32_t numLeadingImplicitTracks =
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; aTrackInfo.mNumLeadingImplicitTracks;
val->SetIdent(eCSSKeyword_none); MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks);
return val.forget();
// Add any leading implicit tracks.
for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
RefPtr<nsROCSSPrimitiveValue> 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, auto* autoRepeatValue = aTrackList.GetRepeatAutoValue();
// so we'll return those sizes here. The grid spec says we MAY use auto beforeAutoRepeat =
// repeat(<positive-integer>, Npx) here for consecutive tracks with the same autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[0].AsSpan()
// size, but that doesn't seem worth doing since even for repeat(auto-*) : Span<StyleCustomIdent>();
// the resolved size might differ for the repeated tracks. auto afterAutoRepeat =
const nsTArray<nscoord>& trackSizes = aTrackInfo->mSizes; autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan()
const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks; : Span<StyleCustomIdent>();
const uint32_t numLeadingImplicitTracks = uint32_t repeatIndex = 0;
aTrackInfo->mNumLeadingImplicitTracks; uint32_t numRepeatTracks = aTrackInfo.mRemovedRepeatTracks.Length();
MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks); 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. // Removed 'auto-fit' tracks are reported as 0px.
for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) { RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; val->SetAppUnits(0);
val->SetAppUnits(trackSizes[i]); valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(val.forget()); atLeastOneTrackReported = true;
}
// Then add any explicit tracks and removed auto-fit tracks. if (aPlacement == LinesFollow) {
if (numExplicitTracks || aTrackList.HasRepeatAuto()) { // Follow it with the lines between repeats.
uint32_t endOfRepeat = 0; // first index after any repeat() tracks AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
int32_t offsetToLastRepeat = 0; }
if (aTrackList.HasRepeatAuto()) { repeatIndex++;
// 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<StyleCustomIdent>();
auto afterAutoRepeat =
autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan()
: Span<StyleCustomIdent>();
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<nsROCSSPrimitiveValue> 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);
} }
repeatIndex++; repeatIndex++;
} };
repeatIndex++;
};
for (uint32_t i = 0;; i++) { for (uint32_t i = 0;; i++) {
if (aTrackList.HasRepeatAuto()) { if (aTrackList.HasRepeatAuto()) {
if (i == aTrackInfo->mRepeatFirstTrack) { if (i == aTrackInfo.mRepeatFirstTrack) {
const nsTArray<StyleCustomIdent>& 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<StyleCustomIdent>& 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<StyleCustomIdent>& lineNames =
aTrackInfo->mResolvedLineNames[j];
AppendGridLineNames(valueList, lineNames);
}
} else {
const nsTArray<StyleCustomIdent>& lineNames = const nsTArray<StyleCustomIdent>& 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<StyleCustomIdent>& 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<StyleCustomIdent>& lineNames =
aTrackInfo.mResolvedLineNames[j];
AppendGridLineNames(valueList, lineNames); AppendGridLineNames(valueList, lineNames);
} }
if (i == numExplicitTracks) { } else {
break; const nsTArray<StyleCustomIdent>& lineNames =
} aTrackInfo.mResolvedLineNames[i];
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; AppendGridLineNames(valueList, lineNames);
val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
valueList->AppendCSSValue(val.forget());
} }
} if (i == numExplicitTracks) {
// Add any trailing implicit tracks.
for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks;
i < numSizes; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(trackSizes[i]);
valueList->AppendCSSValue(val.forget());
}
} else {
if (aTrackList.IsNone()) {
RefPtr<nsROCSSPrimitiveValue> 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) {
break; break;
} }
auto& value = values[i]; RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
if (value.IsTrackRepeat()) { val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
auto& repeat = value.AsTrackRepeat(); valueList->AppendCSSValue(val.forget());
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<nsROCSSPrimitiveValue> 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<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
value->SetString(string);
valueList->AppendCSSValue(value.forget());
} else {
valueList->AppendCSSValue(GetGridTrackSize(value.AsTrackSize()));
}
} }
} }
// Add any trailing implicit tracks.
for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks; i < numSizes;
++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(trackSizes[i]);
valueList->AppendCSSValue(val.forget());
}
return valueList.forget(); return valueList.forget();
} }
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateColumns() { already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateColumns() {
const ComputedGridTrackInfo* info = nullptr;
nsGridContainerFrame* gridFrame = nsGridContainerFrame* gridFrame =
nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame); nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame);
if (!gridFrame) {
if (gridFrame) { // The element doesn't have a box - return the computed value.
info = gridFrame->GetComputedTemplateColumns(); // https://drafts.csswg.org/css-grid/#resolved-track-list
nsAutoString string;
Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_columns,
&string);
RefPtr<nsROCSSPrimitiveValue> 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, return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns,
info); *info);
} }
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateRows() { already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateRows() {
const ComputedGridTrackInfo* info = nullptr;
nsGridContainerFrame* gridFrame = nsGridContainerFrame* gridFrame =
nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame); nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame);
if (!gridFrame) {
if (gridFrame) { // The element doesn't have a box - return the computed value.
info = gridFrame->GetComputedTemplateRows(); // https://drafts.csswg.org/css-grid/#resolved-track-list
nsAutoString string;
Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_rows,
&string);
RefPtr<nsROCSSPrimitiveValue> 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<CSSValue> nsComputedDOMStyle::DoGetPaddingTop() { already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetPaddingTop() {

Просмотреть файл

@ -197,7 +197,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
const mozilla::StyleTrackBreadth&); const mozilla::StyleTrackBreadth&);
already_AddRefed<CSSValue> GetGridTemplateColumnsRows( already_AddRefed<CSSValue> GetGridTemplateColumnsRows(
const mozilla::StyleGridTemplateComponent& aTrackList, const mozilla::StyleGridTemplateComponent& aTrackList,
const mozilla::ComputedGridTrackInfo* aTrackInfo); const mozilla::ComputedGridTrackInfo& aTrackInfo);
bool GetLineHeightCoord(nscoord& aCoord); bool GetLineHeightCoord(nscoord& aCoord);