mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
Bug 1440014: Part 1: Implemented rendering for text-decoration-width CSS property r=jfkthame
reftests will be added later Differential Revision: https://phabricator.services.mozilla.com/D34238 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6686b244bd
commit
b695380455
@ -5118,15 +5118,18 @@ void nsTextFrame::GetTextDecorations(
|
||||
|
||||
if (textDecorations & kUnderline) {
|
||||
aDecorations.mUnderlines.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset, color, style));
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationWidth, color, style));
|
||||
}
|
||||
if (textDecorations & kOverline) {
|
||||
aDecorations.mOverlines.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset, color, style));
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationWidth, color, style));
|
||||
}
|
||||
if (textDecorations & StyleTextDecorationLine_LINE_THROUGH) {
|
||||
aDecorations.mStrikes.AppendElement(nsTextFrame::LineDecoration(
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset, color, style));
|
||||
f, baselineOffset, styleText->mTextUnderlineOffset,
|
||||
styleTextReset->mTextDecorationWidth, color, style));
|
||||
}
|
||||
}
|
||||
|
||||
@ -5274,11 +5277,10 @@ nsRect nsTextFrame::UpdateTextEmphasis(WritingMode aWM,
|
||||
return overflowRect.GetPhysicalRect(aWM, frameSize.GetPhysicalSize(aWM));
|
||||
}
|
||||
|
||||
static void SetParamIfLength(const LengthOrAuto& aTextOffset,
|
||||
Float* aParamOffset,
|
||||
static void SetParamIfLength(const LengthOrAuto& aLengthOrAuto, Float* aParam,
|
||||
const gfxFloat aAppUnitsPerDevPixel) {
|
||||
if (aTextOffset.IsLength()) {
|
||||
*aParamOffset = aTextOffset.AsLength().ToAppUnits() / aAppUnitsPerDevPixel;
|
||||
if (aLengthOrAuto.IsLength()) {
|
||||
*aParam = aLengthOrAuto.AsLength().ToAppUnits() / aAppUnitsPerDevPixel;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5305,6 +5307,7 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
|
||||
decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
|
||||
}
|
||||
nsCSSRendering::DecorationRectParams params;
|
||||
nsFontMetrics* fontMetrics = aProvider.GetFontMetrics();
|
||||
nscoord underlineOffset, underlineSize;
|
||||
fontMetrics->GetUnderline(underlineOffset, underlineSize);
|
||||
@ -5312,14 +5315,21 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
const LengthOrAuto& textUnderlineOffset =
|
||||
aBlock->Style()->StyleText()->mTextUnderlineOffset;
|
||||
|
||||
const LengthOrAuto& textDecorationWidth =
|
||||
aBlock->Style()->StyleTextReset()->mTextDecorationWidth;
|
||||
|
||||
if (textUnderlineOffset.IsLength()) {
|
||||
underlineOffset = textUnderlineOffset.AsLength().ToAppUnits();
|
||||
}
|
||||
|
||||
params.defaultLineThickness = underlineSize;
|
||||
if (textDecorationWidth.IsLength()) {
|
||||
underlineSize = textDecorationWidth.AsLength().ToAppUnits();
|
||||
}
|
||||
|
||||
nscoord maxAscent =
|
||||
inverted ? fontMetrics->MaxDescent() : fontMetrics->MaxAscent();
|
||||
|
||||
nsCSSRendering::DecorationRectParams params;
|
||||
Float gfxWidth = (verticalRun ? aVisualOverflowRect->height
|
||||
: aVisualOverflowRect->width) /
|
||||
appUnitsPerDevUnit;
|
||||
@ -5406,9 +5416,13 @@ void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
|
||||
if (lineType == StyleTextDecorationLine_UNDERLINE) {
|
||||
SetParamIfLength(dec.mTextUnderlineOffset, ¶ms.offset,
|
||||
aPresContext->AppUnitsPerDevPixel());
|
||||
appUnitsPerDevUnit);
|
||||
}
|
||||
|
||||
params.defaultLineThickness = params.lineSize.height;
|
||||
SetParamIfLength(dec.mTextDecorationWidth, ¶ms.lineSize.height,
|
||||
appUnitsPerDevUnit);
|
||||
|
||||
const nsRect decorationRect =
|
||||
nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
|
||||
(verticalDec ? nsPoint(frameBStart - dec.mBaselineOffset, 0)
|
||||
@ -5589,7 +5603,7 @@ void nsTextFrame::DrawSelectionDecorations(
|
||||
if (aDecoration == StyleTextDecorationLine_UNDERLINE) {
|
||||
params.offset = aFontMetrics.underlineOffset;
|
||||
SetParamIfLength(StyleText()->mTextUnderlineOffset, ¶ms.offset,
|
||||
PresContext()->AppUnitsPerDevPixel());
|
||||
aTextPaintStyle.PresContext()->AppUnitsPerDevPixel());
|
||||
} else {
|
||||
params.offset = aFontMetrics.maxAscent;
|
||||
}
|
||||
@ -5603,6 +5617,9 @@ void nsTextFrame::DrawSelectionDecorations(
|
||||
aTextPaintStyle.PresContext(), aFontMetrics);
|
||||
|
||||
float relativeSize;
|
||||
const LengthOrAuto& decWidth = StyleTextReset()->mTextDecorationWidth;
|
||||
const gfxFloat appUnitsPerDevPixel =
|
||||
aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
switch (aSelectionType) {
|
||||
case SelectionType::eIMERawClause:
|
||||
@ -5615,8 +5632,11 @@ void nsTextFrame::DrawSelectionDecorations(
|
||||
bool weDefineSelectionUnderline =
|
||||
aTextPaintStyle.GetSelectionUnderlineForPaint(
|
||||
index, ¶ms.color, &relativeSize, ¶ms.style);
|
||||
params.lineSize.height = ComputeSelectionUnderlineHeight(
|
||||
params.defaultLineThickness = ComputeSelectionUnderlineHeight(
|
||||
aTextPaintStyle.PresContext(), aFontMetrics, aSelectionType);
|
||||
params.lineSize.height = params.defaultLineThickness;
|
||||
SetParamIfLength(decWidth, ¶ms.lineSize.height, appUnitsPerDevPixel);
|
||||
|
||||
bool isIMEType = aSelectionType != SelectionType::eSpellCheck;
|
||||
|
||||
if (isIMEType) {
|
||||
@ -5688,6 +5708,8 @@ void nsTextFrame::DrawSelectionDecorations(
|
||||
aTextPaintStyle.GetURLSecondaryColor(¶ms.color);
|
||||
params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
|
||||
params.lineSize.height = metrics.strikeoutSize;
|
||||
params.defaultLineThickness = params.lineSize.height;
|
||||
SetParamIfLength(decWidth, ¶ms.lineSize.height, appUnitsPerDevPixel);
|
||||
params.offset = metrics.strikeoutOffset + 0.5;
|
||||
params.decoration = StyleTextDecorationLine_LINE_THROUGH;
|
||||
break;
|
||||
@ -5697,6 +5719,7 @@ void nsTextFrame::DrawSelectionDecorations(
|
||||
return;
|
||||
}
|
||||
params.lineSize.height *= relativeSize;
|
||||
params.defaultLineThickness *= relativeSize;
|
||||
params.icoordInFrame =
|
||||
(aVertical ? params.pt.y - aPt.y : params.pt.x - aPt.x) + aICoordInFrame;
|
||||
PaintDecorationLine(params);
|
||||
@ -6881,7 +6904,9 @@ void nsTextFrame::DrawTextRunAndDecorations(
|
||||
SetParamIfLength(dec.mTextUnderlineOffset, ¶ms.offset,
|
||||
PresContext()->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
params.defaultLineThickness = params.lineSize.height;
|
||||
SetParamIfLength(dec.mTextDecorationWidth, ¶ms.lineSize.height,
|
||||
PresContext()->AppUnitsPerDevPixel());
|
||||
params.style = dec.mStyle;
|
||||
PaintDecorationLine(params);
|
||||
};
|
||||
@ -7225,11 +7250,16 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
||||
}
|
||||
nsRect decorationArea;
|
||||
|
||||
params.lineSize = Size(aPresContext->AppUnitsToGfxUnits(aRect.width),
|
||||
ComputeSelectionUnderlineHeight(
|
||||
aPresContext, metrics, sd->mSelectionType));
|
||||
const LengthOrAuto& decWidth = StyleTextReset()->mTextDecorationWidth;
|
||||
params.lineSize.width = aPresContext->AppUnitsToGfxUnits(aRect.width);
|
||||
params.defaultLineThickness = ComputeSelectionUnderlineHeight(
|
||||
aPresContext, metrics, sd->mSelectionType);
|
||||
SetParamIfLength(decWidth, ¶ms.lineSize.height,
|
||||
aPresContext->AppUnitsPerDevPixel());
|
||||
|
||||
relativeSize = std::max(relativeSize, 1.0f);
|
||||
params.lineSize.height *= relativeSize;
|
||||
params.defaultLineThickness *= relativeSize;
|
||||
decorationArea =
|
||||
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
|
||||
aRect.UnionRect(aRect, decorationArea);
|
||||
|
@ -699,15 +699,20 @@ class nsTextFrame : public nsFrame {
|
||||
// This represents the offset from the initial position of the underline
|
||||
const mozilla::LengthOrAuto mTextUnderlineOffset;
|
||||
|
||||
// for CSS property text-decoration-width, the width refers to the thickness
|
||||
// of the decoration line
|
||||
const mozilla::LengthOrAuto mTextDecorationWidth;
|
||||
nscolor mColor;
|
||||
uint8_t mStyle;
|
||||
|
||||
LineDecoration(nsIFrame* const aFrame, const nscoord aOff,
|
||||
const mozilla::LengthOrAuto& aUnderline,
|
||||
const nscolor aColor, const uint8_t aStyle)
|
||||
const mozilla::LengthOrAuto& aDecWidth, const nscolor aColor,
|
||||
const uint8_t aStyle)
|
||||
: mFrame(aFrame),
|
||||
mBaselineOffset(aOff),
|
||||
mTextUnderlineOffset(aUnderline),
|
||||
mTextDecorationWidth(aDecWidth),
|
||||
mColor(aColor),
|
||||
mStyle(aStyle) {}
|
||||
|
||||
@ -715,6 +720,7 @@ class nsTextFrame : public nsFrame {
|
||||
: mFrame(aOther.mFrame),
|
||||
mBaselineOffset(aOther.mBaselineOffset),
|
||||
mTextUnderlineOffset(aOther.mTextUnderlineOffset),
|
||||
mTextDecorationWidth(aOther.mTextDecorationWidth),
|
||||
mColor(aOther.mColor),
|
||||
mStyle(aOther.mStyle) {}
|
||||
|
||||
@ -722,7 +728,8 @@ class nsTextFrame : public nsFrame {
|
||||
return mFrame == aOther.mFrame && mStyle == aOther.mStyle &&
|
||||
mColor == aOther.mColor &&
|
||||
mBaselineOffset == aOther.mBaselineOffset &&
|
||||
mTextUnderlineOffset == aOther.mTextUnderlineOffset;
|
||||
mTextUnderlineOffset == aOther.mTextUnderlineOffset &&
|
||||
mTextDecorationWidth == aOther.mTextDecorationWidth;
|
||||
}
|
||||
|
||||
bool operator!=(const LineDecoration& aOther) const {
|
||||
|
@ -4062,6 +4062,8 @@ gfxRect nsCSSRendering::GetTextDecorationRectInternal(
|
||||
|
||||
gfxFloat lineThickness = NS_round(aParams.lineSize.height);
|
||||
lineThickness = std::max(lineThickness, 1.0);
|
||||
gfxFloat defaultLineThickness = NS_round(aParams.defaultLineThickness);
|
||||
defaultLineThickness = std::max(defaultLineThickness, 1.0);
|
||||
|
||||
gfxFloat ascent = NS_round(aParams.ascent);
|
||||
gfxFloat descentLimit = floor(aParams.descentLimit);
|
||||
@ -4154,18 +4156,22 @@ gfxRect nsCSSRendering::GetTextDecorationRectInternal(
|
||||
}
|
||||
}
|
||||
} 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();
|
||||
// For overline, we adjust the offset by defaultlineThickness (the default
|
||||
// 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 - defaultLineThickness + 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;
|
||||
// computes offset for when user specifies a decoration width since
|
||||
// aParams.offset is derived from the font metric's line height
|
||||
gfxFloat decorationWidthOffset =
|
||||
(lineThickness - defaultLineThickness) / 2.0;
|
||||
offset = aParams.offset - lineThickness + extra + decorationWidthOffset;
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid text decoration value");
|
||||
}
|
||||
|
@ -559,6 +559,12 @@ struct nsCSSRendering {
|
||||
// for a vertical textrun, width will actually be a physical height;
|
||||
// and conversely, height will be a physical width.
|
||||
Size lineSize;
|
||||
// The default height [thickness] of the line given by the font metrics.
|
||||
// This is used for obtaining the correct offset for the decoration line
|
||||
// when CSS specifies a unique thickness for a text-decoration,
|
||||
// since the offset given by the font is derived from the font metric's
|
||||
// assumed line height
|
||||
Float defaultLineThickness = 0.0f;
|
||||
// The ascent of the text.
|
||||
Float ascent = 0.0f;
|
||||
// The offset of the decoration line from the baseline of the text
|
||||
|
Loading…
Reference in New Issue
Block a user