Skip to content

Commit

Permalink
Bug 1950844 - Support spelling-error and grammar-error values of text…
Browse files Browse the repository at this point in the history
…-decoration-line. r=tlouw

Differential Revision: https://phabricator.services.mozilla.com/D239913
  • Loading branch information
jfkthame committed Feb 28, 2025
1 parent dce7bcc commit 2b4b16f
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 49 deletions.
51 changes: 40 additions & 11 deletions layout/generic/nsTextFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -5568,6 +5594,7 @@ struct nsTextFrame::PaintDecorationLineParams
DecorationType decorationType = DecorationType::Normal;
DrawPathCallbacks* callbacks = nullptr;
bool paintingShadows = false;
bool allowInkSkipping = true;
};

void nsTextFrame::PaintDecorationLine(
Expand All @@ -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) {
Expand Down Expand Up @@ -7172,6 +7200,7 @@ void nsTextFrame::DrawTextRunAndDecorations(
app, dec.mFrame, wm.IsCentralBaseline(), swapUnderline);

params.style = dec.mStyle;
params.allowInkSkipping = dec.mAllowInkSkipping;
PaintDecorationLine(params);
};

Expand Down
21 changes: 13 additions & 8 deletions layout/generic/nsTextFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,38 +860,42 @@ 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;

// 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;

Expand All @@ -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 {
Expand Down
20 changes: 8 additions & 12 deletions layout/painting/nsCSSRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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 =
Expand Down
2 changes: 2 additions & 0 deletions layout/painting/nsCSSRendering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down
8 changes: 6 additions & 2 deletions servo/components/style/values/specified/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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;
}
}

Expand Down

This file was deleted.

This file was deleted.

0 comments on commit 2b4b16f

Please sign in to comment.