tor-browser

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

commit cfc7d6b047ac056a0893e6a073249b0ce2e802df
parent 1b41a53e287fc6ddd90a35eb7a64ed4df6c5ecd4
Author: Jonathan Kew <jkew@mozilla.com>
Date:   Fri, 31 Oct 2025 22:17:19 +0000

Bug 1997569 - Adjust text-decoration-inset computations for margin/border/padding intervening between the decorating frame and the text. r=layout-jp-market-reviewers,layout-reviewers,AlaskanEmily

If there are frames in between the target frame we're rendering and the container
where the decoration was defined, their margin/border/padding effectively reduces
the area within which the decoration is being drawn.

This fixes the rendering of the remaining examples in the testcase so that the
inset is applied consistently in all of them.

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

Diffstat:
Mlayout/generic/nsTextFrame.cpp | 39++++++++++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp @@ -5827,19 +5827,22 @@ static bool ComputeDecorationInset( std::swap(insetLeft, insetRight); } - // These rects must be based on the same origin. - // If the decorating frame is an inline frame, then these rects are relative - // to the decorating frame. - // Otherwise, these rects are relative to the line container. - nsRect inlineRect, frameRect; + // The rect of the decorating box (if an inline) or of the current line (if + // the decoration is propagated from a block ancestor). We will need to + // compare this with the rect of the current frame, which may be only a + // sub-range of the entire decorated range. + nsRect decRect; + + // The container of the decoration, or the fragment of it on this line. + const nsIFrame* decContainer; // If the decorating frame is an inline frame, we can use it as the // reference frame for measurements. // If the decorating frame is not inline, then we will need to consider // text indentation and calculate geometry using line boxes. if (aDecFrame->IsInlineFrame()) { - frameRect = nsRect{aFrame->GetOffsetTo(aDecFrame), aFrame->GetSize()}; - inlineRect = aDecFrame->GetContentRectRelativeToSelf(); + decRect = aDecFrame->GetContentRectRelativeToSelf(); + decContainer = aDecFrame; } else { nsIFrame* const lineContainer = FindLineContainer(aFrame); nsILineIterator* const iter = lineContainer->GetLineIterator(); @@ -5854,8 +5857,8 @@ static bool ComputeDecorationInset( const nsILineIterator::LineInfo lineInfo = iter->GetLine(lineNum).unwrap(); // Create the rects, relative to the line container. - frameRect = nsRect{aFrame->GetOffsetTo(lineContainer), aFrame->GetSize()}; - inlineRect = lineInfo.mLineBounds; + decRect = lineInfo.mLineBounds; + decContainer = lineContainer; // Account for text-indent, which will push text frames into the line box. const StyleTextIndent& textIndent = aFrame->StyleText()->mTextIndent; @@ -5879,14 +5882,28 @@ static bool ComputeDecorationInset( const nscoord basis = lineContainer->GetLogicalSize(wm).ISize(wm); nsMargin indentMargin; indentMargin.Side(side) = textIndent.length.Resolve(basis); - inlineRect.Deflate(indentMargin); + decRect.Deflate(indentMargin); } } } + // The rect of the current frame, mapped to the same coordinate space as + // decRect so that we can compare their edges. + const nsRect frameRect = + aFrame->GetRectRelativeToSelf() + aFrame->GetOffsetTo(decContainer); + + // The nominal size of the decoration (prior to insets being applied) is + // reduced by any margin, border, and padding present on frames intervening + // between aFrame and decContainer. + for (const nsIFrame* parent = aFrame->GetParent(); parent != decContainer; + parent = parent->GetParent()) { + decRect.Deflate(parent->GetUsedMargin()); + decRect.Deflate(parent->GetUsedBorderAndPadding()); + } + // Find the margin of the of this frame inside its container. nscoord marginLeft, marginRight, frameSize; - const nsMargin difference = inlineRect - frameRect; + const nsMargin difference = decRect - frameRect; if (verticalDec) { marginLeft = difference.top; marginRight = difference.bottom;