Bug 1950844 - Support spelling-error and grammar-error values of text-decoration-line. r=tlouw
Differential Revision: https://phabricator.services.mozilla.com/D239913
This commit is contained in:
@@ -4912,8 +4912,29 @@ void nsTextFrame::GetTextDecorations(
|
||||
}
|
||||
|
||||
const nsStyleTextReset* const styleTextReset = context->StyleTextReset();
|
||||
const StyleTextDecorationLine textDecorations =
|
||||
StyleTextDecorationLine textDecorations =
|
||||
styleTextReset->mTextDecorationLine;
|
||||
bool ignoreSubproperties = false;
|
||||
|
||||
auto lineStyle = styleTextReset->mTextDecorationStyle;
|
||||
if (textDecorations == StyleTextDecorationLine::SPELLING_ERROR ||
|
||||
textDecorations == StyleTextDecorationLine::GRAMMAR_ERROR) {
|
||||
nscolor lineColor;
|
||||
float relativeSize;
|
||||
useOverride = nsTextPaintStyle::GetSelectionUnderline(
|
||||
this, nsTextPaintStyle::SelectionStyleIndex::SpellChecker, &lineColor,
|
||||
&relativeSize, &lineStyle);
|
||||
if (useOverride) {
|
||||
// We don't currently have a SelectionStyleIndex::GrammarChecker; for
|
||||
// now just use SpellChecker and change its color to green.
|
||||
overrideColor =
|
||||
textDecorations == StyleTextDecorationLine::SPELLING_ERROR
|
||||
? lineColor
|
||||
: NS_RGBA(0, 128, 0, 255);
|
||||
textDecorations = StyleTextDecorationLine::UNDERLINE;
|
||||
ignoreSubproperties = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useOverride &&
|
||||
(StyleTextDecorationLine::COLOR_OVERRIDE & textDecorations)) {
|
||||
@@ -4961,7 +4982,6 @@ void nsTextFrame::GetTextDecorations(
|
||||
physicalBlockStartOffset +=
|
||||
vertical ? f->GetNormalPosition().x : f->GetNormalPosition().y;
|
||||
|
||||
const auto style = styleTextReset->mTextDecorationStyle;
|
||||
if (textDecorations) {
|
||||
nscolor color;
|
||||
if (useOverride) {
|
||||
@@ -4992,23 +5012,29 @@ void nsTextFrame::GetTextDecorations(
|
||||
: StyleTextDecorationLine::OVERLINE;
|
||||
|
||||
const nsStyleText* const styleText = context->StyleText();
|
||||
const auto position = ignoreSubproperties
|
||||
? StyleTextUnderlinePosition::AUTO
|
||||
: styleText->mTextUnderlinePosition;
|
||||
const auto offset = ignoreSubproperties ? LengthPercentageOrAuto::Auto()
|
||||
: styleText->mTextUnderlineOffset;
|
||||
const auto thickness = ignoreSubproperties
|
||||
? StyleTextDecorationLength::Auto()
|
||||
: styleTextReset->mTextDecorationThickness;
|
||||
|
||||
if (textDecorations & kUnderline) {
|
||||
aDecorations.mUnderlines.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlinePosition,
|
||||
styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationThickness, color, style));
|
||||
f, baselineOffset, position, offset, thickness, color, lineStyle,
|
||||
!ignoreSubproperties));
|
||||
}
|
||||
if (textDecorations & kOverline) {
|
||||
aDecorations.mOverlines.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlinePosition,
|
||||
styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationThickness, color, style));
|
||||
f, baselineOffset, position, offset, thickness, color, lineStyle,
|
||||
!ignoreSubproperties));
|
||||
}
|
||||
if (textDecorations & StyleTextDecorationLine::LINE_THROUGH) {
|
||||
aDecorations.mStrikes.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlinePosition,
|
||||
styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationThickness, color, style));
|
||||
f, baselineOffset, position, offset, thickness, color, lineStyle,
|
||||
!ignoreSubproperties));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5568,6 +5594,7 @@ struct nsTextFrame::PaintDecorationLineParams
|
||||
DecorationType decorationType = DecorationType::Normal;
|
||||
DrawPathCallbacks* callbacks = nullptr;
|
||||
bool paintingShadows = false;
|
||||
bool allowInkSkipping = true;
|
||||
};
|
||||
|
||||
void nsTextFrame::PaintDecorationLine(
|
||||
@@ -5579,6 +5606,7 @@ void nsTextFrame::PaintDecorationLine(
|
||||
params.color = aParams.overrideColor ? *aParams.overrideColor : aParams.color;
|
||||
params.icoordInFrame = Float(aParams.icoordInFrame);
|
||||
params.baselineOffset = Float(aParams.baselineOffset);
|
||||
params.allowInkSkipping = aParams.allowInkSkipping;
|
||||
if (aParams.callbacks) {
|
||||
Rect path = nsCSSRendering::DecorationLineToPath(params);
|
||||
if (aParams.decorationType == DecorationType::Normal) {
|
||||
@@ -7172,6 +7200,7 @@ void nsTextFrame::DrawTextRunAndDecorations(
|
||||
app, dec.mFrame, wm.IsCentralBaseline(), swapUnderline);
|
||||
|
||||
params.style = dec.mStyle;
|
||||
params.allowInkSkipping = dec.mAllowInkSkipping;
|
||||
PaintDecorationLine(params);
|
||||
};
|
||||
|
||||
|
||||
@@ -860,11 +860,11 @@ class nsTextFrame : public nsIFrame {
|
||||
const PaintShadowParams& aParams);
|
||||
|
||||
struct LineDecoration {
|
||||
nsIFrame* mFrame;
|
||||
nsIFrame* const mFrame;
|
||||
|
||||
// This is represents the offset from our baseline to mFrame's baseline;
|
||||
// positive offsets are *above* the baseline and negative offsets below
|
||||
nscoord mBaselineOffset;
|
||||
const nscoord mBaselineOffset;
|
||||
|
||||
// This represents the offset from the initial position of the underline
|
||||
const mozilla::LengthPercentageOrAuto mTextUnderlineOffset;
|
||||
@@ -872,26 +872,30 @@ class nsTextFrame : public nsIFrame {
|
||||
// for CSS property text-decoration-thickness, the width refers to the
|
||||
// thickness of the decoration line
|
||||
const mozilla::StyleTextDecorationLength mTextDecorationThickness;
|
||||
nscolor mColor;
|
||||
mozilla::StyleTextDecorationStyle mStyle;
|
||||
const nscolor mColor;
|
||||
const mozilla::StyleTextDecorationStyle mStyle;
|
||||
|
||||
// The text-underline-position property; affects the underline offset only
|
||||
// if mTextUnderlineOffset is auto.
|
||||
const mozilla::StyleTextUnderlinePosition mTextUnderlinePosition;
|
||||
|
||||
const bool mAllowInkSkipping;
|
||||
|
||||
LineDecoration(nsIFrame* const aFrame, const nscoord aOff,
|
||||
mozilla::StyleTextUnderlinePosition aUnderlinePosition,
|
||||
const mozilla::StyleTextUnderlinePosition aUnderlinePosition,
|
||||
const mozilla::LengthPercentageOrAuto& aUnderlineOffset,
|
||||
const mozilla::StyleTextDecorationLength& aDecThickness,
|
||||
const nscolor aColor,
|
||||
const mozilla::StyleTextDecorationStyle aStyle)
|
||||
const mozilla::StyleTextDecorationStyle aStyle,
|
||||
const bool aAllowInkSkipping)
|
||||
: mFrame(aFrame),
|
||||
mBaselineOffset(aOff),
|
||||
mTextUnderlineOffset(aUnderlineOffset),
|
||||
mTextDecorationThickness(aDecThickness),
|
||||
mColor(aColor),
|
||||
mStyle(aStyle),
|
||||
mTextUnderlinePosition(aUnderlinePosition) {}
|
||||
mTextUnderlinePosition(aUnderlinePosition),
|
||||
mAllowInkSkipping(aAllowInkSkipping) {}
|
||||
|
||||
LineDecoration(const LineDecoration& aOther) = default;
|
||||
|
||||
@@ -901,7 +905,8 @@ class nsTextFrame : public nsIFrame {
|
||||
mBaselineOffset == aOther.mBaselineOffset &&
|
||||
mTextUnderlinePosition == aOther.mTextUnderlinePosition &&
|
||||
mTextUnderlineOffset == aOther.mTextUnderlineOffset &&
|
||||
mTextDecorationThickness == aOther.mTextDecorationThickness;
|
||||
mTextDecorationThickness == aOther.mTextDecorationThickness &&
|
||||
mAllowInkSkipping == aOther.mAllowInkSkipping;
|
||||
}
|
||||
|
||||
bool operator!=(const LineDecoration& aOther) const {
|
||||
|
||||
@@ -1153,9 +1153,10 @@ static nsIFrame* GetPageSequenceForCanvas(const nsIFrame* aCanvasFrame) {
|
||||
return ps;
|
||||
}
|
||||
|
||||
auto nsCSSRendering::FindEffectiveBackgroundColor(
|
||||
nsIFrame* aFrame, bool aStopAtThemed,
|
||||
bool aPreferBodyToCanvas) -> EffectiveBackgroundColor {
|
||||
auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
|
||||
bool aStopAtThemed,
|
||||
bool aPreferBodyToCanvas)
|
||||
-> EffectiveBackgroundColor {
|
||||
MOZ_ASSERT(aFrame);
|
||||
nsPresContext* pc = aFrame->PresContext();
|
||||
auto BgColorIfNotTransparent = [&](nsIFrame* aFrame) -> Maybe<nscolor> {
|
||||
@@ -4095,21 +4096,16 @@ void nsCSSRendering::PaintDecorationLine(
|
||||
aFrame->StyleText()->mTextDecorationSkipInk;
|
||||
bool skipInkEnabled =
|
||||
skipInk != mozilla::StyleTextDecorationSkipInk::None &&
|
||||
aParams.decoration != StyleTextDecorationLine::LINE_THROUGH;
|
||||
aParams.decoration != StyleTextDecorationLine::LINE_THROUGH &&
|
||||
aParams.allowInkSkipping && aFrame->IsTextFrame();
|
||||
|
||||
if (!skipInkEnabled || aParams.glyphRange.Length() == 0) {
|
||||
PaintDecorationLineInternal(aFrame, aDrawTarget, aParams, rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the frame is a text frame or not
|
||||
nsTextFrame* textFrame = nullptr;
|
||||
if (aFrame->IsTextFrame()) {
|
||||
textFrame = static_cast<nsTextFrame*>(aFrame);
|
||||
} else {
|
||||
PaintDecorationLineInternal(aFrame, aDrawTarget, aParams, rect);
|
||||
return;
|
||||
}
|
||||
// Must be a text frame, otherwise skipInkEnabled (above) would be false.
|
||||
nsTextFrame* textFrame = static_cast<nsTextFrame*>(aFrame);
|
||||
|
||||
// get text run and current text offset (for line wrapping)
|
||||
gfxTextRun* textRun =
|
||||
|
||||
@@ -610,6 +610,8 @@ struct nsCSSRendering {
|
||||
// Baseline offset being applied to this text (block-direction adjustment
|
||||
// applied to glyph positions when computing skip-ink intercepts).
|
||||
Float baselineOffset = 0.0f;
|
||||
// Whether text-decoration-skip-ink behavior is to be supported.
|
||||
bool allowInkSkipping = true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -274,7 +274,7 @@ impl ToCss for TextOverflow {
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[css(bitflags(single = "none", mixed = "underline,overline,line-through,blink"))]
|
||||
#[css(bitflags(single = "none,spelling-error,grammar-error", mixed = "underline,overline,line-through,blink"))]
|
||||
#[repr(C)]
|
||||
/// Specified keyword values for the text-decoration-line property.
|
||||
pub struct TextDecorationLine(u8);
|
||||
@@ -290,6 +290,10 @@ bitflags! {
|
||||
const LINE_THROUGH = 1 << 2;
|
||||
/// blink
|
||||
const BLINK = 1 << 3;
|
||||
/// spelling-error
|
||||
const SPELLING_ERROR = 1 << 4;
|
||||
/// grammar-error
|
||||
const GRAMMAR_ERROR = 1 << 5;
|
||||
/// Only set by presentation attributes
|
||||
///
|
||||
/// Setting this will mean that text-decorations use the color
|
||||
@@ -298,7 +302,7 @@ bitflags! {
|
||||
/// For example, this gives <a href=foo><font color="red">text</font></a>
|
||||
/// a red text decoration
|
||||
#[cfg(feature = "gecko")]
|
||||
const COLOR_OVERRIDE = 0x10;
|
||||
const COLOR_OVERRIDE = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[text-decoration-line-computed.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [TIMEOUT, OK]
|
||||
[Property text-decoration-line value 'spelling-error']
|
||||
expected: FAIL
|
||||
|
||||
[Property text-decoration-line value 'grammar-error']
|
||||
expected: FAIL
|
||||
@@ -1,8 +0,0 @@
|
||||
[text-decoration-line-valid.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[e.style['text-decoration-line'\] = "spelling-error" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-decoration-line'\] = "grammar-error" should set the property value]
|
||||
expected: FAIL
|
||||
Reference in New Issue
Block a user