Bug 1535165 - Use cbindgen for text-decoration-line. r=dholbert,boris

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-03-18 17:58:16 +00:00
parent 9928a5bda4
commit e66fb8488c
25 changed files with 228 additions and 318 deletions

View File

@ -606,9 +606,9 @@ TextAttrsMgr::TextDecorValue::TextDecorValue(nsIFrame* aFrame) {
const nsStyleTextReset* textReset = aFrame->StyleTextReset();
mStyle = textReset->mTextDecorationStyle;
mColor = textReset->mTextDecorationColor.CalcColor(aFrame);
mLine = textReset->mTextDecorationLine &
(NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
mLine =
textReset->mTextDecorationLine & (StyleTextDecorationLine_UNDERLINE |
StyleTextDecorationLine_LINE_THROUGH);
}
TextAttrsMgr::TextDecorTextAttr::TextDecorTextAttr(nsIFrame* aRootFrame,

View File

@ -358,7 +358,7 @@ class TextAttrsMgr {
public:
TextDecorValue()
: mColor{0},
mLine{NS_STYLE_TEXT_DECORATION_LINE_NONE},
mLine{StyleTextDecorationLine_NONE},
mStyle{NS_STYLE_TEXT_DECORATION_STYLE_NONE} {}
explicit TextDecorValue(nsIFrame* aFrame);
@ -367,10 +367,10 @@ class TextAttrsMgr {
bool IsDefined() const { return IsUnderline() || IsLineThrough(); }
bool IsUnderline() const {
return mLine & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
return bool(mLine & mozilla::StyleTextDecorationLine_UNDERLINE);
}
bool IsLineThrough() const {
return mLine & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
return bool(mLine & mozilla::StyleTextDecorationLine_LINE_THROUGH);
}
bool operator==(const TextDecorValue& aValue) {
@ -381,7 +381,7 @@ class TextAttrsMgr {
private:
nscolor mColor;
uint8_t mLine;
mozilla::StyleTextDecorationLine mLine;
uint8_t mStyle;
};

View File

@ -73,7 +73,7 @@ void HTMLFontElement::MapAttributesIntoRule(
}
if (aDecls.Document()->GetCompatibilityMode() == eCompatibility_NavQuirks) {
// Make <a><font color="red">text</font></a> give the text a red underline
// in quirks mode. The NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL flag only
// in quirks mode. The StyleTextDecorationLine_COLOR_OVERRIDE flag only
// affects quirks mode rendering.
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
nscolor color;

View File

@ -5279,10 +5279,11 @@ void nsTextFrame::GetTextDecorations(
}
const nsStyleTextReset* const styleText = context->StyleTextReset();
const uint8_t textDecorations = styleText->mTextDecorationLine;
const StyleTextDecorationLine textDecorations =
styleText->mTextDecorationLine;
if (!useOverride &&
(NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL & textDecorations)) {
(StyleTextDecorationLine_COLOR_OVERRIDE & textDecorations)) {
// This handles the <a href="blah.html"><font color="green">La
// la la</font></a> case. The link underline should be green.
useOverride = true;
@ -5347,12 +5348,12 @@ void nsTextFrame::GetTextDecorations(
}
bool swapUnderlineAndOverline = vertical && IsUnderlineRight(f);
const uint8_t kUnderline = swapUnderlineAndOverline
? NS_STYLE_TEXT_DECORATION_LINE_OVERLINE
: NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
const uint8_t kOverline = swapUnderlineAndOverline
? NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE
: NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
const auto kUnderline = swapUnderlineAndOverline
? StyleTextDecorationLine_OVERLINE
: StyleTextDecorationLine_UNDERLINE;
const auto kOverline = swapUnderlineAndOverline
? StyleTextDecorationLine_UNDERLINE
: StyleTextDecorationLine_OVERLINE;
if (textDecorations & kUnderline) {
aDecorations.mUnderlines.AppendElement(
@ -5362,7 +5363,7 @@ void nsTextFrame::GetTextDecorations(
aDecorations.mOverlines.AppendElement(
nsTextFrame::LineDecoration(f, baselineOffset, color, style));
}
if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
if (textDecorations & StyleTextDecorationLine_LINE_THROUGH) {
aDecorations.mStrikes.AppendElement(
nsTextFrame::LineDecoration(f, baselineOffset, color, style));
}
@ -5551,11 +5552,11 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
params.sidewaysLeft = mTextRun->IsSidewaysLeft();
params.offset = underlineOffset / appUnitsPerDevUnit;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
params.decoration = StyleTextDecorationLine_UNDERLINE;
nsRect underlineRect =
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
params.offset = maxAscent / appUnitsPerDevUnit;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
params.decoration = StyleTextDecorationLine_OVERLINE;
nsRect overlineRect =
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
@ -5638,17 +5639,17 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
// Below we loop through all text decorations and compute the rectangle
// containing all of them, in this frame's coordinate space
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
params.decoration = StyleTextDecorationLine_UNDERLINE;
for (const LineDecoration& dec : textDecs.mUnderlines) {
accumulateDecorationRect(dec, &Metrics::underlineSize,
&Metrics::underlineOffset);
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
params.decoration = StyleTextDecorationLine_OVERLINE;
for (const LineDecoration& dec : textDecs.mOverlines) {
accumulateDecorationRect(dec, &Metrics::underlineSize,
&Metrics::maxAscent);
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
params.decoration = StyleTextDecorationLine_LINE_THROUGH;
for (const LineDecoration& dec : textDecs.mStrikes) {
accumulateDecorationRect(dec, &Metrics::strikeoutSize,
&Metrics::strikeoutOffset);
@ -5789,14 +5790,14 @@ void nsTextFrame::DrawSelectionDecorations(
const TextRangeStyle& aRangeStyle, const Point& aPt,
gfxFloat aICoordInFrame, gfxFloat aWidth, gfxFloat aAscent,
const gfxFont::Metrics& aFontMetrics, DrawPathCallbacks* aCallbacks,
bool aVertical, uint8_t aDecoration) {
bool aVertical, StyleTextDecorationLine aDecoration) {
PaintDecorationLineParams params;
params.context = aContext;
params.dirtyRect = aDirtyRect;
params.pt = aPt;
params.lineSize.width = aWidth;
params.ascent = aAscent;
params.offset = aDecoration == NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE
params.offset = aDecoration == StyleTextDecorationLine_UNDERLINE
? aFontMetrics.underlineOffset
: aFontMetrics.maxAscent;
params.decoration = aDecoration;
@ -5894,7 +5895,7 @@ void nsTextFrame::DrawSelectionDecorations(
params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
params.lineSize.height = metrics.strikeoutSize;
params.offset = metrics.strikeoutOffset + 0.5;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
params.decoration = StyleTextDecorationLine_LINE_THROUGH;
break;
}
default:
@ -6413,9 +6414,8 @@ void nsTextFrame::PaintTextSelectionDecorations(
gfxFont* firstFont = aParams.provider->GetFontGroup()->GetFirstValidFont();
bool verticalRun = mTextRun->IsVertical();
bool rightUnderline = verticalRun && IsUnderlineRight(this);
const uint8_t kDecoration = rightUnderline
? NS_STYLE_TEXT_DECORATION_LINE_OVERLINE
: NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
const auto kDecoration = rightUnderline ? StyleTextDecorationLine_OVERLINE
: StyleTextDecorationLine_UNDERLINE;
bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline();
gfxFont::Metrics decorationMetrics(firstFont->GetMetrics(
useVerticalMetrics ? gfxFont::eVertical : gfxFont::eHorizontal));
@ -7126,14 +7126,14 @@ void nsTextFrame::DrawTextRunAndDecorations(
}
// Underlines
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
params.decoration = StyleTextDecorationLine_UNDERLINE;
for (const LineDecoration& dec : Reversed(aDecorations.mUnderlines)) {
paintDecorationLine(dec, &Metrics::underlineSize,
&Metrics::underlineOffset);
}
// Overlines
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
params.decoration = StyleTextDecorationLine_OVERLINE;
for (const LineDecoration& dec : Reversed(aDecorations.mOverlines)) {
paintDecorationLine(dec, &Metrics::underlineSize, &Metrics::maxAscent);
}
@ -7166,7 +7166,7 @@ void nsTextFrame::DrawTextRunAndDecorations(
}
// Line-throughs
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
params.decoration = StyleTextDecorationLine_LINE_THROUGH;
for (const LineDecoration& dec : Reversed(aDecorations.mStrikes)) {
paintDecorationLine(dec, &Metrics::strikeoutSize,
&Metrics::strikeoutOffset);

View File

@ -760,7 +760,7 @@ class nsTextFrame : public nsFrame {
const TextRangeStyle& aRangeStyle, const Point& aPt,
gfxFloat aICoordInFrame, gfxFloat aWidth, gfxFloat aAscent,
const gfxFont::Metrics& aFontMetrics, DrawPathCallbacks* aCallbacks,
bool aVertical, uint8_t aDecoration);
bool aVertical, mozilla::StyleTextDecorationLine aDecoration);
struct PaintDecorationLineParams;
void PaintDecorationLine(const PaintDecorationLineParams& aParams);

View File

@ -3682,10 +3682,10 @@ void nsCSSRendering::PaintDecorationLine(
return;
}
if (aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
NS_ERROR("Invalid decoration value!");
if (aParams.decoration != StyleTextDecorationLine_UNDERLINE &&
aParams.decoration != StyleTextDecorationLine_OVERLINE &&
aParams.decoration != StyleTextDecorationLine_LINE_THROUGH) {
MOZ_ASSERT_UNREACHABLE("Invalid text decoration value");
return;
}
@ -3961,10 +3961,10 @@ Rect nsCSSRendering::DecorationLineToPath(
return path;
}
if (aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
NS_ERROR("Invalid decoration value!");
if (aParams.decoration != StyleTextDecorationLine_UNDERLINE &&
aParams.decoration != StyleTextDecorationLine_OVERLINE &&
aParams.decoration != StyleTextDecorationLine_LINE_THROUGH) {
MOZ_ASSERT_UNREACHABLE("Invalid text decoration value");
return path;
}
@ -4109,42 +4109,34 @@ gfxRect nsCSSRendering::GetTextDecorationRectInternal(
// upwards. We'll swap them to be physical coords at the end.
gfxFloat offset = 0.0;
switch (aParams.decoration) {
case NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE:
offset = aParams.offset;
if (canLiftUnderline) {
if (descentLimit < -offset + r.Height()) {
// If we can ignore the offset and the decoration line is overflowing,
// we should align the bottom edge of the decoration line rect if it's
// possible. Otherwise, we should lift up the top edge of the rect as
// far as possible.
gfxFloat offsetBottomAligned = -descentLimit + r.Height();
gfxFloat offsetTopAligned = 0.0;
offset = std::min(offsetBottomAligned, offsetTopAligned);
}
if (aParams.decoration == StyleTextDecorationLine_UNDERLINE) {
offset = aParams.offset;
if (canLiftUnderline) {
if (descentLimit < -offset + r.Height()) {
// If we can ignore the offset and the decoration line is overflowing,
// we should align the bottom edge of the decoration line rect if it's
// possible. Otherwise, we should lift up the top edge of the rect as
// far as possible.
gfxFloat offsetBottomAligned = -descentLimit + r.Height();
gfxFloat offsetTopAligned = 0.0;
offset = std::min(offsetBottomAligned, offsetTopAligned);
}
break;
case NS_STYLE_TEXT_DECORATION_LINE_OVERLINE:
// For overline, we adjust the offset by lineThickness (the thickness of
// a single decoration line) because empirically it looks better to draw
// the overline just inside rather than outside the font's ascent, which
// is what nsTextFrame passes as aParams.offset (as fonts don't provide
// an explicit overline-offset).
offset = aParams.offset - lineThickness + r.Height();
break;
case NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH: {
// To maintain a consistent mid-point for line-through decorations,
// we adjust the offset by half of the decoration rect's height.
gfxFloat extra = floor(r.Height() / 2.0 + 0.5);
extra = std::max(extra, lineThickness);
offset = aParams.offset - lineThickness + extra;
break;
}
default:
NS_ERROR("Invalid decoration value!");
} else if (aParams.decoration == StyleTextDecorationLine_OVERLINE) {
// For overline, we adjust the offset by lineThickness (the thickness of
// a single decoration line) because empirically it looks better to draw
// the overline just inside rather than outside the font's ascent, which
// is what nsTextFrame passes as aParams.offset (as fonts don't provide
// an explicit overline-offset).
offset = aParams.offset - lineThickness + r.Height();
} else if (aParams.decoration == StyleTextDecorationLine_LINE_THROUGH) {
// To maintain a consistent mid-point for line-through decorations,
// we adjust the offset by half of the decoration rect's height.
gfxFloat extra = floor(r.Height() / 2.0 + 0.5);
extra = std::max(extra, lineThickness);
offset = aParams.offset - lineThickness + extra;
} else {
MOZ_ASSERT_UNREACHABLE("Invalid text decoration value");
}
// Convert line-relative coordinate system (x = line-right, y = line-up)

View File

@ -572,10 +572,9 @@ struct nsCSSRendering {
// strikeout line and overline too.
Float descentLimit = -1.0f;
// Which line will be painted. The value can be
// NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
// NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
// NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
uint8_t decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
// UNDERLINE or OVERLINE or LINE_THROUGH.
mozilla::StyleTextDecorationLine decoration =
mozilla::StyleTextDecorationLine_UNDERLINE;
// The style of the decoration line such as
// NS_STYLE_TEXT_DECORATION_STYLE_*.
uint8_t style = NS_STYLE_TEXT_DECORATION_STYLE_NONE;

View File

@ -449,6 +449,7 @@ cbindgen-types = [
{ gecko = "StyleGenericLineHeight", servo = "values::generics::text::LineHeight" },
{ gecko = "StyleContain", servo = "values::computed::Contain" },
{ gecko = "StyleRestyleHint", servo = "invalidation::element::restyle_hints::RestyleHint" },
{ gecko = "StyleTextDecorationLine", servo = "values::computed::TextDecorationLine" },
]
mapped-generic-types = [

View File

@ -114,7 +114,6 @@ LONGHANDS_NOT_SERIALIZED_WITH_SERVO = [
"scroll-snap-points-x",
"scroll-snap-points-y",
"stroke",
"text-decoration-line",
"text-emphasis-position",
"text-emphasis-style",
"text-overflow",

View File

@ -359,14 +359,6 @@ const KTableEntry nsCSSProps::kTextAlignKTable[] = {
{eCSSKeyword_end, NS_STYLE_TEXT_ALIGN_END},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kTextDecorationLineKTable[] = {
{eCSSKeyword_none, NS_STYLE_TEXT_DECORATION_LINE_NONE},
{eCSSKeyword_underline, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE},
{eCSSKeyword_overline, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE},
{eCSSKeyword_line_through, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH},
{eCSSKeyword_blink, NS_STYLE_TEXT_DECORATION_LINE_BLINK},
{eCSSKeyword_UNKNOWN, -1}};
const KTableEntry nsCSSProps::kTextDecorationStyleKTable[] = {
{eCSSKeyword__moz_none, NS_STYLE_TEXT_DECORATION_STYLE_NONE},
{eCSSKeyword_solid, NS_STYLE_TEXT_DECORATION_STYLE_SOLID},

View File

@ -306,7 +306,6 @@ class nsCSSProps {
static const KTableEntry kGridTrackBreadthKTable[];
static const KTableEntry kLineHeightKTable[];
static const KTableEntry kTextAlignKTable[];
static const KTableEntry kTextDecorationLineKTable[];
static const KTableEntry kTextDecorationStyleKTable[];
static const KTableEntry kTextEmphasisStyleShapeKTable[];
static const KTableEntry kTextOverflowKTable[];

View File

@ -1990,13 +1990,22 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTextDecoration() {
textReset->mTextDecorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
StyleComplexColor color = textReset->mTextDecorationColor;
RefPtr<nsROCSSPrimitiveValue> textDecorationLine = new nsROCSSPrimitiveValue;
{
nsAutoString decorationLine;
Servo_GetPropertyValue(mComputedStyle, eCSSProperty_text_decoration_line,
&decorationLine);
textDecorationLine->SetString(decorationLine);
}
if (isInitialStyle && color.IsCurrentColor()) {
return DoGetTextDecorationLine();
return textDecorationLine.forget();
}
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
valueList->AppendCSSValue(DoGetTextDecorationLine());
valueList->AppendCSSValue(textDecorationLine.forget());
if (!isInitialStyle) {
valueList->AppendCSSValue(DoGetTextDecorationStyle());
}
@ -2013,28 +2022,6 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTextDecorationColor() {
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTextDecorationLine() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
int32_t intValue = StyleTextReset()->mTextDecorationLine;
if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
val->SetIdent(eCSSKeyword_none);
} else {
nsAutoString decorationLineString;
// Clear the OVERRIDE_ALL bits -- we don't want these to appear in
// the computed style.
intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
nsStyleUtil::AppendBitmaskCSSValue(
nsCSSProps::kTextDecorationLineKTable, intValue,
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
NS_STYLE_TEXT_DECORATION_LINE_BLINK, decorationLineString);
val->SetString(decorationLineString);
}
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTextDecorationStyle() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;

View File

@ -307,7 +307,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetLineHeight();
already_AddRefed<CSSValue> DoGetTextDecoration();
already_AddRefed<CSSValue> DoGetTextDecorationColor();
already_AddRefed<CSSValue> DoGetTextDecorationLine();
already_AddRefed<CSSValue> DoGetTextDecorationStyle();
already_AddRefed<CSSValue> DoGetTextEmphasisPosition();
already_AddRefed<CSSValue> DoGetTextEmphasisStyle();

View File

@ -562,20 +562,6 @@ enum class StyleGridTrackBreadth : uint8_t {
// Note: make sure that the largest NS_STYLE_TEXT_ALIGN_* value is smaller than
// the smallest NS_STYLE_VERTICAL_ALIGN_* value below!
// See nsStyleText, nsStyleFont
#define NS_STYLE_TEXT_DECORATION_LINE_NONE 0
#define NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE 0x01
#define NS_STYLE_TEXT_DECORATION_LINE_OVERLINE 0x02
#define NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH 0x04
#define NS_STYLE_TEXT_DECORATION_LINE_BLINK 0x08
// OVERRIDE_ALL does not occur in stylesheets; it only comes from HTML
// attribute mapping (and thus appears in computed data)
#define NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL 0x10
#define NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK \
(NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE | \
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE | \
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH)
// See nsStyleText
#define NS_STYLE_TEXT_DECORATION_STYLE_NONE \
0 // not in CSS spec, mapped to -moz-none

View File

@ -3618,7 +3618,7 @@ nsChangeHint nsStyleContent::CalcDifference(
nsStyleTextReset::nsStyleTextReset(const Document& aDocument)
: mTextOverflow(),
mTextDecorationLine(NS_STYLE_TEXT_DECORATION_LINE_NONE),
mTextDecorationLine(StyleTextDecorationLine_NONE),
mTextDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID),
mUnicodeBidi(NS_STYLE_UNICODE_BIDI_NORMAL),
mInitialLetterSink(0),

View File

@ -1425,15 +1425,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset {
// Note the difference between this and
// ComputedStyle::HasTextDecorationLines.
bool HasTextDecorationLines() const {
return mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_NONE &&
mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
return mTextDecorationLine != mozilla::StyleTextDecorationLine_NONE &&
mTextDecorationLine !=
mozilla::StyleTextDecorationLine_COLOR_OVERRIDE;
}
nsChangeHint CalcDifference(const nsStyleTextReset& aNewData) const;
nsStyleTextOverflow mTextOverflow; // enum, string
uint8_t mTextDecorationLine; // NS_STYLE_TEXT_DECORATION_LINE_*
mozilla::StyleTextDecorationLine mTextDecorationLine;
uint8_t mTextDecorationStyle; // NS_STYLE_TEXT_DECORATION_STYLE_*
uint8_t mUnicodeBidi; // NS_STYLE_UNICODE_BIDI_*
nscoord mInitialLetterSink; // 0 means normal

View File

@ -371,9 +371,11 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext,
uint8_t strikeStyle = 0;
// Begin with no decorations
uint8_t decorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
// A mask of all possible decorations.
uint8_t decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
auto decorations = StyleTextDecorationLine_NONE;
// A mask of all possible line decorations.
auto decorMask = StyleTextDecorationLine_UNDERLINE |
StyleTextDecorationLine_OVERLINE |
StyleTextDecorationLine_LINE_THROUGH;
WritingMode wm = GetWritingMode();
bool vertical = wm.IsVertical();
@ -396,29 +398,30 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext,
}
uint8_t style = styleText->mTextDecorationStyle;
if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decorMask &
if (StyleTextDecorationLine_UNDERLINE & decorMask &
styleText->mTextDecorationLine) {
underColor = color;
underStyle = style;
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
decorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
// TODO(emilio): Could add `operator~` or `remove()` to cbindgen.
decorMask.bits &= ~StyleTextDecorationLine_UNDERLINE.bits;
decorations |= StyleTextDecorationLine_UNDERLINE;
}
if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & decorMask &
if (StyleTextDecorationLine_OVERLINE & decorMask &
styleText->mTextDecorationLine) {
overColor = color;
overStyle = style;
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
decorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
decorMask.bits &= ~StyleTextDecorationLine_OVERLINE.bits;
decorations |= StyleTextDecorationLine_OVERLINE;
}
if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & decorMask &
if (StyleTextDecorationLine_LINE_THROUGH & decorMask &
styleText->mTextDecorationLine) {
strikeColor = color;
strikeStyle = style;
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
decorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
decorMask.bits &= ~StyleTextDecorationLine_LINE_THROUGH.bits;
decorations |= StyleTextDecorationLine_LINE_THROUGH;
}
}
} while (0 != decorMask && (f = nsLayoutUtils::GetParentOrPlaceholderFor(f)));
} while (decorMask && (f = nsLayoutUtils::GetParentOrPlaceholderFor(f)));
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
@ -458,23 +461,23 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext,
// (We don't apply this rule to the access-key underline because we only
// find out where that is as a side effect of drawing the text, in the
// general case -- see below.)
if (decorations & (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE |
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE)) {
if (decorations &
(StyleTextDecorationLine_OVERLINE | StyleTextDecorationLine_UNDERLINE)) {
fontMet->GetUnderline(offset, size);
params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
if ((decorations & StyleTextDecorationLine_UNDERLINE) &&
underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
params.color = underColor;
params.offset = presContext->AppUnitsToGfxUnits(offset);
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
params.decoration = StyleTextDecorationLine_UNDERLINE;
params.style = underStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
if ((decorations & StyleTextDecorationLine_OVERLINE) &&
overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
params.color = overColor;
params.offset = params.ascent;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
params.decoration = StyleTextDecorationLine_OVERLINE;
params.style = overStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}
@ -544,13 +547,13 @@ void nsTextBoxFrame::DrawText(gfxContext& aRenderingContext,
// Strikeout is drawn on top of the text, per
// http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
if ((decorations & StyleTextDecorationLine_LINE_THROUGH) &&
strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
fontMet->GetStrikeout(offset, size);
params.color = strikeColor;
params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
params.offset = presContext->AppUnitsToGfxUnits(offset);
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
params.decoration = StyleTextDecorationLine_LINE_THROUGH;
params.style = strikeStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}

View File

@ -3446,26 +3446,27 @@ ImgDrawResult nsTreeBodyFrame::PaintText(
ColorPattern color(ToDeviceColor(textContext->StyleColor()->mColor));
// Draw decorations.
uint8_t decorations = textContext->StyleTextReset()->mTextDecorationLine;
StyleTextDecorationLine decorations =
textContext->StyleTextReset()->mTextDecorationLine;
nscoord offset;
nscoord size;
if (decorations & (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE |
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE)) {
if (decorations &
(StyleTextDecorationLine_OVERLINE | StyleTextDecorationLine_UNDERLINE)) {
fontMet->GetUnderline(offset, size);
if (decorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
if (decorations & StyleTextDecorationLine_OVERLINE) {
nsRect r(textRect.x, textRect.y, textRect.width, size);
Rect devPxRect = NSRectToSnappedRect(r, appUnitsPerDevPixel, *drawTarget);
drawTarget->FillRect(devPxRect, color);
}
if (decorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
if (decorations & StyleTextDecorationLine_UNDERLINE) {
nsRect r(textRect.x, textRect.y + baseline - offset, textRect.width,
size);
Rect devPxRect = NSRectToSnappedRect(r, appUnitsPerDevPixel, *drawTarget);
drawTarget->FillRect(devPxRect, color);
}
}
if (decorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
if (decorations & StyleTextDecorationLine_LINE_THROUGH) {
fontMet->GetStrikeout(offset, size);
nsRect r(textRect.x, textRect.y + baseline - offset, textRect.width, size);
Rect devPxRect = NSRectToSnappedRect(r, appUnitsPerDevPixel, *drawTarget);

View File

@ -105,6 +105,7 @@ include = [
"WordBreak",
"Contain",
"RestyleHint",
"TextDecorationLine",
]
item_types = ["enums", "structs", "typedefs"]

View File

@ -3996,9 +3996,7 @@ fn static_assert() {
</%self:impl_trait>
<%self:impl_trait style_struct_name="Text"
skip_longhands="text-decoration-line text-overflow initial-letter">
${impl_simple_type_with_conversion("text_decoration_line")}
skip_longhands="text-overflow initial-letter">
fn clear_overflow_sides_if_string(&mut self) {
use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
@ -4112,21 +4110,6 @@ fn static_assert() {
InitialLetter::Specified(self.gecko.mInitialLetterSize, Some(self.gecko.mInitialLetterSink))
}
}
#[inline]
pub fn has_underline(&self) -> bool {
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE as u8)) != 0
}
#[inline]
pub fn has_overline(&self) -> bool {
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8)) != 0
}
#[inline]
pub fn has_line_through(&self) -> bool {
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8)) != 0
}
</%self:impl_trait>
// Set SVGPathData to StyleShapeSource.

View File

@ -5,16 +5,7 @@
<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>
<% data.new_style_struct(
"Text",
inherited=False,
gecko_name="TextReset",
additional_methods=[
Method("has_underline", "bool"),
Method("has_overline", "bool"),
Method("has_line_through", "bool"),
]
) %>
<% data.new_style_struct("Text", inherited=False, gecko_name="TextReset") %>
${helpers.predefined_type(
"text-overflow",

View File

@ -2638,24 +2638,6 @@ pub mod style_structs {
use crate::Zero;
!self.outline_width.is_zero()
}
% elif style_struct.name == "Text":
/// Whether the text decoration has an underline.
#[inline]
pub fn has_underline(&self) -> bool {
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::UNDERLINE)
}
/// Whether the text decoration has an overline.
#[inline]
pub fn has_overline(&self) -> bool {
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::OVERLINE)
}
/// Whether the text decoration has a line through.
#[inline]
pub fn has_line_through(&self) -> bool {
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::LINE_THROUGH)
}
% elif style_struct.name == "Box":
/// Sets the display property, but without touching original_display,
/// except when the adjustment comes from root or item display fixups.

View File

@ -19,7 +19,7 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::TextEmphasisPosition;
pub use crate::values::specified::{TextEmphasisPosition, TextDecorationLine};
pub use crate::values::specified::{OverflowWrap, WordBreak};
/// A computed value for the `initial-letter` property.
@ -182,11 +182,11 @@ impl TextDecorationsInEffect {
.clone(),
};
let text_style = style.get_text();
let line = style.get_text().clone_text_decoration_line();
result.underline |= text_style.has_underline();
result.overline |= text_style.has_overline();
result.line_through |= text_style.has_line_through();
result.underline |= line.contains(TextDecorationLine::UNDERLINE);
result.overline |= line.contains(TextDecorationLine::OVERLINE);
result.line_through |= line.contains(TextDecorationLine::LINE_THROUGH);
result
}

View File

@ -22,8 +22,7 @@ use cssparser::{Parser, Token};
use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write};
use style_traits::values::SequenceWriter;
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use unicode_segmentation::UnicodeSegmentation;
/// A specified type for the `initial-letter` property.
@ -255,119 +254,115 @@ impl ToComputedValue for TextOverflow {
}
}
macro_rules! impl_text_decoration_line {
{
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf, ToComputedValue)]
/// Specified keyword values for the text-decoration-line property.
pub struct TextDecorationLine: u8 {
/// No text decoration line is specified
const NONE = 0;
$(
$(#[$($meta)+])*
const $ident = $value;
)+
#[cfg(feature = "gecko")]
/// Only set by presentation attributes
///
/// Setting this will mean that text-decorations use the color
/// specified by `color` in quirks mode.
///
/// For example, this gives <a href=foo><font color="red">text</font></a>
/// a red text decoration
const COLOR_OVERRIDE = 0x10;
bitflags! {
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
#[value_info(other_values = "none,underline,overline,line-through,blink")]
#[repr(C)]
/// Specified keyword values for the text-decoration-line property.
pub struct TextDecorationLine: u8 {
/// No text decoration line is specified.
const NONE = 0;
/// underline
const UNDERLINE = 1 << 0;
/// overline
const OVERLINE = 1 << 1;
/// line-through
const LINE_THROUGH = 1 << 2;
/// blink
const BLINK = 1 << 3;
/// Only set by presentation attributes
///
/// Setting this will mean that text-decorations use the color
/// specified by `color` in quirks mode.
///
/// For example, this gives <a href=foo><font color="red">text</font></a>
/// a red text decoration
#[cfg(feature = "gecko")]
const COLOR_OVERRIDE = 0x10;
}
}
impl Parse for TextDecorationLine {
/// none | [ underline || overline || line-through || blink ]
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut result = TextDecorationLine::empty();
// NOTE(emilio): this loop has this weird structure because we run this
// code to parse the text-decoration shorthand as well, so we need to
// ensure we don't return an error if we don't consume the whole thing
// because we find an invalid identifier or other kind of token.
loop {
let flag: Result<_, ParseError<'i>> = input.try(|input| {
let flag = try_match_ident_ignore_ascii_case! { input,
"none" if result.is_empty() => TextDecorationLine::NONE,
"underline" => TextDecorationLine::UNDERLINE,
"overline" => TextDecorationLine::OVERLINE,
"line-through" => TextDecorationLine::LINE_THROUGH,
"blink" => TextDecorationLine::BLINK,
};
Ok(flag)
});
let flag = match flag {
Ok(flag) => flag,
Err(..) => break,
};
if flag.is_empty() {
return Ok(TextDecorationLine::NONE);
}
if result.contains(flag) {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
result.insert(flag)
}
impl Parse for TextDecorationLine {
/// none | [ underline || overline || line-through || blink ]
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<TextDecorationLine, ParseError<'i>> {
let mut result = TextDecorationLine::NONE;
if input
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
return Ok(result);
}
loop {
let result = input.try(|input| {
let ident = input.expect_ident().map_err(|_| ())?;
match_ignore_ascii_case! { ident,
$(
$css => {
if result.contains(TextDecorationLine::$ident) {
Err(())
} else {
result.insert(TextDecorationLine::$ident);
Ok(())
}
}
)+
_ => Err(()),
}
});
if result.is_err() {
break;
}
}
if !result.is_empty() {
Ok(result)
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
}
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("none");
}
let mut writer = SequenceWriter::new(dest, " ");
$(
if self.contains(TextDecorationLine::$ident) {
writer.raw_item($css)?;
}
)+
Ok(())
}
}
impl SpecifiedValueInfo for TextDecorationLine {
fn collect_completion_keywords(f: KeywordsCollectFn) {
f(&["none", $($css,)+]);
}
if !result.is_empty() {
Ok(result)
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
}
impl_text_decoration_line! {
/// Underline
UNDERLINE / "underline" => 1 << 0,
/// Overline
OVERLINE / "overline" => 1 << 1,
/// Line through
LINE_THROUGH / "line-through" => 1 << 2,
/// Blink
BLINK / "blink" => 1 << 3,
}
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_empty() {
return dest.write_str("none");
}
#[cfg(feature = "gecko")]
impl_bitflags_conversions!(TextDecorationLine);
let mut writer = SequenceWriter::new(dest, " ");
let mut any = false;
macro_rules! maybe_write {
($ident:ident => $str:expr) => {
if self.contains(TextDecorationLine::$ident) {
any = true;
writer.raw_item($str)?;
}
};
}
maybe_write!(UNDERLINE => "underline");
maybe_write!(OVERLINE => "overline");
maybe_write!(LINE_THROUGH => "line-through");
maybe_write!(BLINK => "blink");
debug_assert!(any || *self == TextDecorationLine::COLOR_OVERRIDE);
Ok(())
}
}
impl TextDecorationLine {
#[inline]

View File

@ -4742,8 +4742,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetTextDecorationColorOverride(
use style::properties::PropertyDeclaration;
use style::values::specified::text::TextDecorationLine;
let mut decoration = TextDecorationLine::none();
decoration |= TextDecorationLine::COLOR_OVERRIDE;
let decoration = TextDecorationLine::COLOR_OVERRIDE;
let decl = PropertyDeclaration::TextDecorationLine(decoration);
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
decls.push(decl, Importance::Normal);