New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement last baseline alignment for Flexbox containers. #4067
Implement last baseline alignment for Flexbox containers. #4067
Conversation
EWS run on previous version of this PR (hash 4296caa) |
4296caa
to
4f2c4cd
Compare
EWS run on previous version of this PR (hash 4f2c4cd) |
4f2c4cd
to
ebec868
Compare
EWS run on previous version of this PR (hash ebec868) |
Updated RenderBlockFlow::lastLineBaseline so that the call to modern layout lastLinePhysicalBaseline was guarded by an if instead of an assert. Now we should fall back to legacy line layout the scenarios where modernLineLayout returns a nullptr |
ebec868
to
49f2d52
Compare
EWS run on previous version of this PR (hash 49f2d52)
|
49f2d52
to
63e7fc6
Compare
EWS run on previous version of this PR (hash 63e7fc6) |
63e7fc6
to
2ba17d5
Compare
EWS run on previous version of this PR (hash 2ba17d5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds reasonable, but not an expert in baselines nor css-align in general.
Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.h
Outdated
Show resolved
Hide resolved
LayoutUnit firstLineBaseline = m_grid[0].baseline; | ||
if (firstLineBaseline) | ||
return firstLineBaseline + m_rowPos[0]; | ||
return firstLineBaseline + m_rowPos[0] + tableMarginBefore; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how this is related to the last baseline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not directly related to the last baseline implementation but to a test case for it. There were 2 expectation files we were rendering incorrectly (css-flexbox/flexbox-align-self-baseline-horiz-001a-expected.xhtml and flexbox-align-self-baseline-horiz-001b-expected.xhtml)
These were using the first baseline for table elements and we were not computing the correct first baseline. This caused us to fail the tests even though we were rendering the actual test file correctly. This was the incorrect way to do it and I moved the logic to RenderTable::baselinePosition. Now it is similar to other objects (e.g. RenderBlock::baselinePosition).
2ba17d5
to
8710e23
Compare
EWS run on previous version of this PR (hash 8710e23)
|
bool RenderFlexibleBox::childIsParticipatingInBaselineAlignment(const RenderBox& child) const | ||
{ | ||
auto alignment = alignmentForChild(child); | ||
return (alignment == ItemPosition::Baseline || alignment == ItemPosition::LastBaseline) && !hasAutoMarginsInCrossAxis(child); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method only has a single caller and the logic is short, so adding it seems unnecessary to me.
By removing it you can reuse the alignmentForChild(child)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. It was useful before, but now after the cleanup it is much less useful. Changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's no longer used, remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
|
||
bool containerHasWrapReverse = style().flexWrap() == FlexWrap::Reverse; | ||
auto shouldAdjustItemTowardsCrossAxis = [this, containerHasWrapReverse](const RenderBox& box, ItemPosition alignment) { | ||
return (containerHasWrapReverse && alignment == ItemPosition::Baseline && !hasAutoMarginsInCrossAxis(box)) || (alignment == ItemPosition::LastBaseline && !containerHasWrapReverse); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why check !hasAutoMarginsInCrossAxis(box)
for the 1st baseline but not for the last one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it should be checked in both cases, then the logic could be shared with another conditional:
auto something = [containerHasWrapReverse](ItemPosition alignment) {
return (containerHasWrapReverse && alignment == ItemPosition::Baseline) || (alignment == ItemPosition::LastBaseline && !containerHasWrapReverse);
};
// ...
if (something(position))
minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, flexItem.box) - offset);
// ...
if (!hasAutoMarginsInCrossAxis(flexItem.box) && something(alignmentForChild(flexItem.box)))
adjustAlignmentForChild(flexItem.box, minMarginAfterBaseline);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it should be for both. I made the adjustment, but let me know if you see any other issues with this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove !hasAutoMarginsInCrossAxis(box)
from shouldAdjustItemTowardsCrossAxis
since the caller that needs it is already checking it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed now
c97879e
to
9336c2b
Compare
EWS run on previous version of this PR (hash 9336c2b)
|
9336c2b
to
14fc529
Compare
EWS run on previous version of this PR (hash 14fc529) |
14fc529
to
2cffcf6
Compare
EWS run on previous version of this PR (hash 2cffcf6) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with the changes Loirooriol (and I) suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Informal LGTM with the suggested changes
bool RenderFlexibleBox::childIsParticipatingInBaselineAlignment(const RenderBox& child) const | ||
{ | ||
auto alignment = alignmentForChild(child); | ||
return (alignment == ItemPosition::Baseline || alignment == ItemPosition::LastBaseline) && !hasAutoMarginsInCrossAxis(child); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's no longer used, remove it.
|
||
bool containerHasWrapReverse = style().flexWrap() == FlexWrap::Reverse; | ||
auto shouldAdjustItemTowardsCrossAxis = [this, containerHasWrapReverse](const RenderBox& box, ItemPosition alignment) { | ||
return (containerHasWrapReverse && alignment == ItemPosition::Baseline && !hasAutoMarginsInCrossAxis(box)) || (alignment == ItemPosition::LastBaseline && !containerHasWrapReverse); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove !hasAutoMarginsInCrossAxis(box)
from shouldAdjustItemTowardsCrossAxis
since the caller that needs it is already checking it?
}); | ||
auto baselinePos = firstLineBaseline(); | ||
if (baselinePos) | ||
return (direction == HorizontalLine ? marginTop() : marginRight()) + firstLineBaseline().value(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that you need this fix for some tests, but it's actually fixing the reference, not the flexbox tests, so it seems strange to do it here.
I would prefer to do this change in its own PR, and have a specific test not involving flexbox, like comparing
<div style="display: inline-block; background: lime;">line 1</div>
<div style="display: inline-table; margin-top: 20px; background: aqua;">line 1<br/>line 2</div>
with this reference:
<div style="display: inline-block; margin-top: 20px; background: lime; vertical-align: top">line 1</div>
<div style="display: inline-block; margin-top: 20px; background: aqua;">line 1<br/>line 2</div>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I refactored it out and created its own PR
2cffcf6
to
132311a
Compare
EWS run on previous version of this PR (hash 132311a) |
|
132311a
to
6857a96
Compare
EWS run on previous version of this PR (hash 6857a96)
|
Rebaselined test expectations with the new tests imported from WPT |
6857a96
to
c1e411a
Compare
EWS run on current version of this PR (hash c1e411a)
|
https://bugs.webkit.org/show_bug.cgi?id=244734 rdar://99506835 Reviewed by Brent Fulgham. In order to implement last baseline alignment for flex containers, we need to hold a little bit more information. Currently, RenderFlexibleBox::LineContext holds a maxAscent value, which holds the value of the furthest baseline in the cross axis. This is then used to shift the other flex items to this baseline. A new field called lastBaselineMaxAscent was added to achieve this same functionality for the last baseline elements. This needs to be a separate field in scenarios where you may have certain items being aligned by their baselines and others by their last baselines. This patch also adds the “margin before” to the first baseline of table elements since it was not being added before. This is needed in order to properly align other elements alongside a table with margins. Without this addition, we were rendering the expectation for both css-flexbox/flexbox-align-self-baseline-horiz-001a and css-flexbox/flexbox-align-self-baseline-horiz-001b incorrectly. * LayoutTests/TestExpectations: * Source/WebCore/rendering/RenderFlexibleBox.cpp: (WebCore::RenderFlexibleBox::LineContext::LineContext): (WebCore::RenderFlexibleBox::marginBoxAscentForChild): Since marginBoxAscentForChild is being called during alignment purposes, we can determine what type of alignment is being done here and return the appropriate ascent (first baseline vs last baseline). (WebCore::alignmentOffset): (WebCore::RenderFlexibleBox::layoutAndPlaceChildren): Depending on whether the item is being first baseline aligned or last baseline aligned, we need to either update maxAscent or lastBaselineMaxAscent. Later on when the alignment is being done, we can check the type of alignment one more time and use the correct value. (WebCore::RenderFlexibleBox::alignChildren): Since items need to be pushed to the end of the cross axis when wrap-reverse is specified, we can use the same logic to push the items that are being last baseline aligned. There was also a little bit of cleanup that I was able to do here. Instead of waiting until all of the lines have had their items aligned to make any adjustments (e.g. due to wrap-reverse), we can do it after laying out each line. We can determine whether or not we need to loop over the line again by checking the value of minMarginAfterBaseline. If this value was set then that means that not only is there room to move the items in the flex line, but also that we need to because the flex container has wrap-reverse set or some items are being last baseline aligned. (WebCore::RenderFlexibleBox::childIsParticipatingInBaselineAlignment const): * Source/WebCore/rendering/RenderFlexibleBox.h: * Source/WebCore/rendering/RenderTableSection.cpp: (WebCore::RenderTable::baselinePosition const): This is not directly related to the last baseline implementation but to a test case for it. There were 2 expectation files we were rendering incorrectly (css-flexbox/flexbox-align-self-baseline-horiz-001a-expected.xhtml and flexbox-align-self-baseline-horiz-001b-expected.xhtml). These were using the first baseline for table elements and we were not computing the correct first baseline. This caused us to fail the tests even though we were rendering the actual test file correctly. Canonical link: https://commits.webkit.org/255383@main
c1e411a
to
a7e014a
Compare
Committed 255383@main (a7e014a): https://commits.webkit.org/255383@main Reviewed commits have been landed. Closing PR #4067 and removing active labels. |
a7e014a
c1e411a
🛠 🧪 win🧪 mac-wk1