tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 09f5e8014568124215e737b186a3198462ae297e
parent 11f456595ac43091170bff03ee639757f0428667
Author: David Shin <dshin@mozilla.com>
Date:   Wed, 22 Oct 2025 13:40:05 +0000

Bug 1993650: Fix up align/justify overflow handling. r=layout-reviewers,emilio

Follows the spec [1] closely now.
[1]: https://drafts.csswg.org/css-align-3/#auto-safety-position

Differential Revision: https://phabricator.services.mozilla.com/D268240

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 52+++++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 19 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -657,27 +657,41 @@ static nscoord OffsetToAlignedStaticPos( // alignment values: https://drafts.csswg.org/css-position-3/#abspos-layout // Skip if the raw self alignment for this element is `auto` to preserve // legacy behaviour. - // We've already aligned as if unsafe. Now get the union of inset-reduced - // containing block and the containing block. - const auto unionedStartOffset = - std::min(0, aNonAutoAlignParams->mCurrentStartInset); + // Follows https://drafts.csswg.org/css-align-3/#auto-safety-position const auto cbSize = aAbsPosCBSize.Size(aAbsPosCBAxis, aAbsPosCBWM); - const auto unionedEndOffset = - std::max(cbSize, cbSize - aNonAutoAlignParams->mCurrentEndInset); - const auto kidSizeInAxis = - aKidSizeInAbsPosCBWM.Size(aAbsPosCBAxis, aAbsPosCBWM); - if (unionedEndOffset - unionedStartOffset < kidSizeInAxis) { - // Kid is bigger than the union - start align it. - offset = -aNonAutoAlignParams->mCurrentStartInset + unionedStartOffset; - } else { - const auto start = aNonAutoAlignParams->mCurrentStartInset; - const auto end = start + kidSizeInAxis; - // Nudge into the union - if (start < unionedStartOffset) { - offset = unionedStartOffset - start; - } else if (end > unionedEndOffset) { - offset = unionedEndOffset - end; + // IMCB stands for "Inset-Modified Containing Block." + const auto imcbStart = aNonAutoAlignParams->mCurrentStartInset; + const auto imcbEnd = cbSize - aNonAutoAlignParams->mCurrentEndInset; + const auto kidSize = aKidSizeInAbsPosCBWM.Size(aAbsPosCBAxis, aAbsPosCBWM); + const auto kidStart = aNonAutoAlignParams->mCurrentStartInset + offset; + const auto kidEnd = kidStart + kidSize; + // "[...] the overflow limit rect is the bounding rectangle of the alignment + // subject’s inset-modified containing block and its original containing + // block." + const auto overflowLimitRectStart = std::min(0, imcbStart); + const auto overflowLimitRectEnd = std::max(cbSize, imcbEnd); + + if (kidStart >= imcbStart && kidEnd <= imcbEnd) { + // 1. We fit inside the IMCB, no action needed. + } else if (kidSize <= overflowLimitRectEnd - overflowLimitRectStart) { + // 2. We overflowed IMCB, try to cover IMCB completely, if it's not. + if (kidEnd < imcbEnd) { + offset += imcbEnd - kidEnd; + } else if (kidStart > imcbStart) { + offset -= kidStart - imcbStart; + } else { + // IMCB already covered, ensure that we aren't escaping the limit rect. + if (kidStart < overflowLimitRectStart) { + offset += overflowLimitRectStart - kidStart; + } else if (kidEnd > overflowLimitRectEnd) { + offset -= kidEnd - overflowLimitRectEnd; + } } + } else { + // 3. We'll overflow the limit rect. Start align the subject int overflow + // limit rect. + offset = + -aNonAutoAlignParams->mCurrentStartInset + overflowLimitRectStart; } }