diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index c3c9e9d02e69..d18a1b7ceef3 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4954,11 +4954,21 @@ static nscoord LazyGetLineBaselineOffset(nsIFrame* aChildFrame, } static bool IsUnderlineRight(nsIFrame* aFrame) { + // Check for 'left' or 'right' explicitly specified in the property; + // if neither is there, we use auto positioning based on lang. + const auto position = aFrame->StyleText()->mTextUnderlinePosition; + if (position.IsLeft()) { + return false; + } + if (position.IsRight()) { + return true; + } + // If neither 'left' nor 'right' was specified, check the language. nsAtom* langAtom = aFrame->StyleFont()->mLanguage; if (!langAtom) { return false; } - nsAtomString langStr(langAtom); + nsDependentAtomString langStr(langAtom); return (StringBeginsWith(langStr, NS_LITERAL_STRING("ja")) || StringBeginsWith(langStr, NS_LITERAL_STRING("ko"))) && (langStr.Length() == 2 || langStr[2] == '-'); @@ -5083,17 +5093,20 @@ void nsTextFrame::GetTextDecorations( if (textDecorations & kUnderline) { aDecorations.mUnderlines.AppendElement(nsTextFrame::LineDecoration( - f, baselineOffset, styleText->mTextUnderlineOffset, + f, baselineOffset, styleText->mTextUnderlinePosition, + styleText->mTextUnderlineOffset, styleTextReset->mTextDecorationThickness, color, style)); } if (textDecorations & kOverline) { aDecorations.mOverlines.AppendElement(nsTextFrame::LineDecoration( - f, baselineOffset, styleText->mTextUnderlineOffset, + f, baselineOffset, styleText->mTextUnderlinePosition, + styleText->mTextUnderlineOffset, styleTextReset->mTextDecorationThickness, color, style)); } if (textDecorations & StyleTextDecorationLine_LINE_THROUGH) { aDecorations.mStrikes.AppendElement(nsTextFrame::LineDecoration( - f, baselineOffset, styleText->mTextUnderlineOffset, + f, baselineOffset, styleText->mTextUnderlinePosition, + styleText->mTextUnderlineOffset, styleTextReset->mTextDecorationThickness, color, style)); } } @@ -5356,8 +5369,15 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, nscoord underlineOffset, underlineSize; fontMetrics->GetUnderline(underlineOffset, underlineSize); + // If text-underline-position:under is in effect, override the default + // underline position from the font. + const auto* styleText = aBlock->StyleText(); + if (styleText->mTextUnderlinePosition.IsUnder()) { + underlineOffset = -fontMetrics->EmDescent(); + } + const StyleTextDecorationLength& textUnderlineOffset = - aBlock->Style()->StyleText()->mTextUnderlineOffset; + styleText->mTextUnderlineOffset; const StyleTextDecorationLength& textDecorationThickness = aBlock->Style()->StyleTextReset()->mTextDecorationThickness; @@ -5467,6 +5487,9 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, bool swapUnderline = verticalDec && IsUnderlineRight(this); if (swapUnderline ? lineType == StyleTextDecorationLine_OVERLINE : lineType == StyleTextDecorationLine_UNDERLINE) { + if (dec.mTextUnderlinePosition.IsUnder()) { + params.offset = -metrics.emDescent; + } SetOffsetIfLength(dec.mTextUnderlineOffset, params, metrics, appUnitsPerDevUnit, parentWM.IsSideways(), swapUnderline); @@ -5684,10 +5707,14 @@ void nsTextFrame::DrawSelectionDecorations( if (swapUnderline ? aDecoration == StyleTextDecorationLine_OVERLINE : aDecoration == StyleTextDecorationLine_UNDERLINE) { WritingMode wm = GetWritingMode(); - params.offset = aFontMetrics.underlineOffset; - SetOffsetIfLength(StyleText()->mTextUnderlineOffset, params, - aFontMetrics, appUnitsPerDevPixel, wm.IsSideways(), - swapUnderline); + const auto* styleText = StyleText(); + if (styleText->mTextUnderlinePosition.IsUnder()) { + params.offset = -aFontMetrics.emDescent; + } else { + params.offset = aFontMetrics.underlineOffset; + } + SetOffsetIfLength(styleText->mTextUnderlineOffset, params, aFontMetrics, + appUnitsPerDevPixel, wm.IsSideways(), swapUnderline); } else { params.offset = aFontMetrics.maxAscent; } @@ -6295,8 +6322,6 @@ void nsTextFrame::PaintTextSelectionDecorations( firstFont->GetMetrics(useVerticalMetrics ? nsFontMetrics::eVertical : nsFontMetrics::eHorizontal)); if (!useVerticalMetrics) { - // The potential adjustment from using gfxFontGroup::GetUnderlineOffset - // is only valid for horizontal font metrics. decorationMetrics.underlineOffset = aParams.provider->GetFontGroup()->GetUnderlineOffset(); } @@ -6968,9 +6993,15 @@ void nsTextFrame::DrawTextRunAndDecorations( params.color = dec.mColor; params.defaultLineThickness = params.lineSize.height; - params.offset = metrics.*lineOffset; params.baselineOffset = dec.mBaselineOffset / app; + if (lineType == StyleTextDecorationLine_UNDERLINE && + dec.mTextUnderlinePosition.IsUnder()) { + params.offset = -metrics.emDescent; + } else { + params.offset = metrics.*lineOffset; + } + bool swapUnderline = verticalDec && IsUnderlineRight(this); if (swapUnderline ? lineType == StyleTextDecorationLine_OVERLINE : lineType == StyleTextDecorationLine_UNDERLINE) { @@ -7268,7 +7299,12 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, nsCSSRendering::DecorationRectParams params; params.ascent = aPresContext->AppUnitsToGfxUnits(mAscent); - params.offset = fontGroup->GetUnderlineOffset(); + + if (StyleText()->mTextUnderlinePosition.IsUnder()) { + params.offset = -metrics.emDescent; + } else { + params.offset = fontGroup->GetUnderlineOffset(); + } TextDecorations textDecs; GetTextDecorations(aPresContext, eResolvedColors, textDecs); diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index d6288d95e549..ea2d38029b8c 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -869,16 +869,22 @@ class nsTextFrame : public nsFrame { nscolor mColor; uint8_t mStyle; + // The text-underline-position property; affects the underline offset only + // if mTextUnderlineOffset is auto. + const mozilla::StyleTextUnderlinePosition mTextUnderlinePosition; + LineDecoration(nsIFrame* const aFrame, const nscoord aOff, - const mozilla::StyleTextDecorationLength& aUnderline, + mozilla::StyleTextUnderlinePosition aUnderlinePosition, + const mozilla::StyleTextDecorationLength& aUnderlineOffset, const mozilla::StyleTextDecorationLength& aDecThickness, const nscolor aColor, const uint8_t aStyle) : mFrame(aFrame), mBaselineOffset(aOff), - mTextUnderlineOffset(aUnderline), + mTextUnderlineOffset(aUnderlineOffset), mTextDecorationThickness(aDecThickness), mColor(aColor), - mStyle(aStyle) {} + mStyle(aStyle), + mTextUnderlinePosition(aUnderlinePosition) {} LineDecoration(const LineDecoration& aOther) : mFrame(aOther.mFrame), @@ -886,12 +892,14 @@ class nsTextFrame : public nsFrame { mTextUnderlineOffset(aOther.mTextUnderlineOffset), mTextDecorationThickness(aOther.mTextDecorationThickness), mColor(aOther.mColor), - mStyle(aOther.mStyle) {} + mStyle(aOther.mStyle), + mTextUnderlinePosition(aOther.mTextUnderlinePosition) {} bool operator==(const LineDecoration& aOther) const { return mFrame == aOther.mFrame && mStyle == aOther.mStyle && mColor == aOther.mColor && mBaselineOffset == aOther.mBaselineOffset && + mTextUnderlinePosition == aOther.mTextUnderlinePosition && mTextUnderlineOffset == aOther.mTextUnderlineOffset && mTextDecorationThickness == aOther.mTextDecorationThickness; } diff --git a/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical-ja.html.ini b/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical-ja.html.ini index 2c69ffca92c5..884b66ec120c 100644 --- a/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical-ja.html.ini +++ b/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical-ja.html.ini @@ -1,2 +1,4 @@ [text-decoration-underline-position-vertical-ja.html] + prefs: [layout.css.text-underline-position.enabled:true] expected: FAIL + bug: https://github.com/web-platform-tests/wpt/issues/20604 diff --git a/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical.html.ini b/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical.html.ini index cfdff6ecde1a..491e52f43274 100644 --- a/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical.html.ini +++ b/testing/web-platform/meta/css/css-text-decor/text-decoration-underline-position-vertical.html.ini @@ -1,2 +1,2 @@ [text-decoration-underline-position-vertical.html] - expected: FAIL + prefs: [layout.css.text-underline-position.enabled:true]