Bug 1258636 part 1 - Use structs to pass params for decoration-related functions in nsCSSRendering. r=jfkthame

MozReview-Commit-ID: 5EJJVmM1pyK

--HG--
extra : rebase_source : 290efcbe41f85fef3a577ff26b4553f195a7fde9
This commit is contained in:
Xidorn Quan 2016-03-22 16:51:15 +08:00
Родитель 2bae02511f
Коммит c1a6d087c3
4 изменённых файлов: 219 добавлений и 291 удалений

Просмотреть файл

@ -4225,40 +4225,27 @@ nsCSSRendering::ExpandPaintingRectForDecorationLine(
}
void
nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
DrawTarget& aDrawTarget,
const Rect& aDirtyRect,
const nscolor aColor,
const Point& aPt,
const Float aICoordInFrame,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit)
nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame, DrawTarget& aDrawTarget,
const PaintDecorationLineParams& aParams)
{
NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
"aStyle is none");
Rect rect = ToRect(
GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
aDecoration, aStyle, aVertical,
aDescentLimit));
if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) {
Rect rect = ToRect(GetTextDecorationRectInternal(aParams.pt, aParams));
if (rect.IsEmpty() || !rect.Intersects(aParams.dirtyRect)) {
return;
}
if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
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!");
return;
}
Float lineThickness = std::max(NS_round(aLineSize.height), 1.0);
Float lineThickness = std::max(NS_round(aParams.lineSize.height), 1.0);
ColorPattern color(ToDeviceColor(aColor));
ColorPattern color(ToDeviceColor(aParams.color));
StrokeOptions strokeOptions(lineThickness);
DrawOptions drawOptions;
@ -4266,7 +4253,7 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
AutoPopClips autoPopClips(&aDrawTarget);
switch (aStyle) {
switch (aParams.style) {
case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
break;
@ -4278,10 +4265,10 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
strokeOptions.mDashPattern = dash;
strokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
strokeOptions.mLineCap = CapStyle::BUTT;
rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
aICoordInFrame,
rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style,
rect, aParams.icoordInFrame,
dashWidth * 2,
aVertical);
aParams.vertical);
// We should continue to draw the last dash even if it is not in the rect.
rect.width += dashWidth;
break;
@ -4299,10 +4286,10 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
}
strokeOptions.mDashPattern = dash;
strokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
aICoordInFrame,
rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style,
rect, aParams.icoordInFrame,
dashWidth * 2,
aVertical);
aParams.vertical);
// We should continue to draw the last dot even if it is not in the rect.
rect.width += dashWidth;
break;
@ -4324,18 +4311,18 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
}
// The block-direction position should be set to the middle of the line.
if (aVertical) {
if (aParams.vertical) {
rect.x += lineThickness / 2;
} else {
rect.y += lineThickness / 2;
}
switch (aStyle) {
switch (aParams.style) {
case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
case NS_STYLE_TEXT_DECORATION_STYLE_DASHED: {
Point p1 = rect.TopLeft();
Point p2 = aVertical ? rect.BottomLeft() : rect.TopRight();
Point p2 = aParams.vertical ? rect.BottomLeft() : rect.TopRight();
aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
return;
}
@ -4355,16 +4342,16 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
* +-------------------------------------------+
*/
Point p1 = rect.TopLeft();
Point p2 = aVertical ? rect.BottomLeft() : rect.TopRight();
Point p2 = aParams.vertical ? rect.BottomLeft() : rect.TopRight();
aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
if (aVertical) {
if (aParams.vertical) {
rect.width -= lineThickness;
} else {
rect.height -= lineThickness;
}
p1 = aVertical ? rect.TopRight() : rect.BottomLeft();
p1 = aParams.vertical ? rect.TopRight() : rect.BottomLeft();
p2 = rect.BottomRight();
aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
return;
@ -4402,9 +4389,9 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
* directions in the above description.
*/
Float& rectICoord = aVertical ? rect.y : rect.x;
Float& rectISize = aVertical ? rect.height : rect.width;
const Float rectBSize = aVertical ? rect.width : rect.height;
Float& rectICoord = aParams.vertical ? rect.y : rect.x;
Float& rectISize = aParams.vertical ? rect.height : rect.width;
const Float rectBSize = aParams.vertical ? rect.width : rect.height;
const Float adv = rectBSize - lineThickness;
const Float flatLengthAtVertex =
@ -4412,13 +4399,14 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
// Align the start of wavy lines to the nearest ancestor block.
const Float cycleLength = 2 * (adv + flatLengthAtVertex);
rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
aICoordInFrame, cycleLength,
aVertical);
rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style, rect,
aParams.icoordInFrame,
cycleLength, aParams.vertical);
// figure out if we can trim whole cycles from the left and right edges
// of the line, to try and avoid creating an unnecessarily long and
// complex path
const Float dirtyRectICoord = aVertical ? aDirtyRect.y : aDirtyRect.x;
const Float dirtyRectICoord = aParams.vertical ? aParams.dirtyRect.y
: aParams.dirtyRect.x;
int32_t skipCycles = floor((dirtyRectICoord - rectICoord) / cycleLength);
if (skipCycles > 0) {
rectICoord += skipCycles * cycleLength;
@ -4427,15 +4415,15 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
rectICoord += lineThickness / 2.0;
Point pt(rect.TopLeft());
Float& ptICoord = aVertical ? pt.y : pt.x;
Float& ptBCoord = aVertical ? pt.x : pt.y;
if (aVertical) {
Float& ptICoord = aParams.vertical ? pt.y : pt.x;
Float& ptBCoord = aParams.vertical ? pt.x : pt.y;
if (aParams.vertical) {
ptBCoord += adv + lineThickness / 2.0;
}
Float iCoordLimit = ptICoord + rectISize + lineThickness;
const Float dirtyRectIMost = aVertical ?
aDirtyRect.YMost() : aDirtyRect.XMost();
const Float dirtyRectIMost = aParams.vertical ?
aParams.dirtyRect.YMost() : aParams.dirtyRect.XMost();
skipCycles = floor((iCoordLimit - dirtyRectIMost) / cycleLength);
if (skipCycles > 0) {
iCoordLimit -= skipCycles * cycleLength;
@ -4453,7 +4441,7 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
// In vertical mode, to go "down" relative to the text we need to
// decrease the block coordinate, whereas in horizontal we increase
// it. So the sense of this flag is effectively inverted.
bool goDown = aVertical ? false : true;
bool goDown = aParams.vertical ? false : true;
uint32_t iter = 0;
while (ptICoord < iCoordLimit) {
if (++iter > 1000) {
@ -4485,45 +4473,34 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
}
Rect
nsCSSRendering::DecorationLineToPath(const Rect& aDirtyRect,
const Point& aPt,
const Size& aLineSize,
const Float aAscent,
const Float aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const Float aDescentLimit)
nsCSSRendering::DecorationLineToPath(const PaintDecorationLineParams& aParams)
{
NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
"aStyle is none");
Rect path; // To benefit from RVO, we return this from all return points
Rect rect = ToRect(
GetTextDecorationRectInternal(aPt, aLineSize,
aAscent, aOffset,
aDecoration, aStyle, aVertical,
aDescentLimit));
if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) {
Rect rect = ToRect(GetTextDecorationRectInternal(aParams.pt, aParams));
if (rect.IsEmpty() || !rect.Intersects(aParams.dirtyRect)) {
return path;
}
if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
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!");
return path;
}
if (aStyle != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
if (aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
// For the moment, we support only solid text decorations.
return path;
}
Float lineThickness = std::max(NS_round(aLineSize.height), 1.0);
Float lineThickness = std::max(NS_round(aParams.lineSize.height), 1.0);
// The block-direction position should be set to the middle of the line.
if (aVertical) {
if (aParams.vertical) {
rect.x += lineThickness / 2;
path = Rect(rect.TopLeft() - Point(lineThickness / 2, 0.0),
Size(lineThickness, rect.Height()));
@ -4538,21 +4515,13 @@ nsCSSRendering::DecorationLineToPath(const Rect& aDirtyRect,
nsRect
nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit)
const DecorationRectParams& aParams)
{
NS_ASSERTION(aPresContext, "aPresContext is null");
NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
"aStyle is none");
gfxRect rect =
GetTextDecorationRectInternal(Point(0, 0), aLineSize, aAscent, aOffset,
aDecoration, aStyle, aVertical,
aDescentLimit);
gfxRect rect = GetTextDecorationRectInternal(Point(0, 0), aParams);
// The rect values are already rounded to nearest device pixels.
nsRect r;
r.x = aPresContext->GfxUnitsToAppUnits(rect.X());
@ -4564,45 +4533,39 @@ nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
gfxRect
nsCSSRendering::GetTextDecorationRectInternal(const Point& aPt,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit)
const DecorationRectParams& aParams)
{
NS_ASSERTION(aStyle <= NS_STYLE_TEXT_DECORATION_STYLE_WAVY,
NS_ASSERTION(aParams.style <= NS_STYLE_TEXT_DECORATION_STYLE_WAVY,
"Invalid aStyle value");
if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE)
if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE)
return gfxRect(0, 0, 0, 0);
bool canLiftUnderline = aDescentLimit >= 0.0;
bool canLiftUnderline = aParams.descentLimit >= 0.0;
gfxFloat iCoord = aVertical ? aPt.y : aPt.x;
gfxFloat bCoord = aVertical ? aPt.x : aPt.y;
gfxFloat iCoord = aParams.vertical ? aPt.y : aPt.x;
gfxFloat bCoord = aParams.vertical ? aPt.x : aPt.y;
// 'left' and 'right' are relative to the line, so for vertical writing modes
// they will actually become top and bottom of the rendered line.
// Similarly, aLineSize.width and .height are actually length and thickness
// of the line, which runs horizontally or vertically according to aVertical.
const gfxFloat left = floor(iCoord + 0.5),
right = floor(iCoord + aLineSize.width + 0.5);
right = floor(iCoord + aParams.lineSize.width + 0.5);
// We compute |r| as if for a horizontal text run, and then swap vertical
// and horizontal coordinates at the end if vertical was requested.
gfxRect r(left, 0, right - left, 0);
gfxFloat lineThickness = NS_round(aLineSize.height);
gfxFloat lineThickness = NS_round(aParams.lineSize.height);
lineThickness = std::max(lineThickness, 1.0);
gfxFloat ascent = NS_round(aAscent);
gfxFloat descentLimit = floor(aDescentLimit);
gfxFloat ascent = NS_round(aParams.ascent);
gfxFloat descentLimit = floor(aParams.descentLimit);
gfxFloat suggestedMaxRectHeight = std::max(std::min(ascent, descentLimit), 1.0);
r.height = lineThickness;
if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE) {
if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE) {
/**
* We will draw double line as:
*
@ -4628,7 +4591,7 @@ nsCSSRendering::GetTextDecorationRectInternal(const Point& aPt,
r.height = std::max(suggestedMaxRectHeight, lineThickness * 2.0 + 1.0);
}
}
} else if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
} else if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
/**
* We will draw wavy line as:
*
@ -4654,11 +4617,11 @@ nsCSSRendering::GetTextDecorationRectInternal(const Point& aPt,
}
}
gfxFloat baseline = floor(bCoord + aAscent + 0.5);
gfxFloat baseline = floor(bCoord + aParams.ascent + 0.5);
gfxFloat offset = 0.0;
switch (aDecoration) {
switch (aParams.decoration) {
case NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE:
offset = aOffset;
offset = aParams.offset;
if (canLiftUnderline) {
if (descentLimit < -offset + r.Height()) {
// If we can ignore the offset and the decoration line is overflowing,
@ -4672,19 +4635,19 @@ nsCSSRendering::GetTextDecorationRectInternal(const Point& aPt,
}
break;
case NS_STYLE_TEXT_DECORATION_LINE_OVERLINE:
offset = aOffset - lineThickness + r.Height();
offset = aParams.offset - lineThickness + r.Height();
break;
case NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH: {
gfxFloat extra = floor(r.Height() / 2.0 + 0.5);
extra = std::max(extra, lineThickness);
offset = aOffset - lineThickness + extra;
offset = aParams.offset - lineThickness + extra;
break;
}
default:
NS_ERROR("Invalid decoration value!");
}
if (aVertical) {
if (aParams.vertical) {
r.y = baseline + floor(offset + 0.5);
Swap(r.x, r.y);
Swap(r.width, r.height);

Просмотреть файл

@ -668,64 +668,61 @@ struct nsCSSRendering {
uint8_t aEndBevelSide = 0,
nscoord aEndBevelOffset = 0);
// NOTE: pt, dirtyRect, lineSize, ascent, offset in the following
// structs are non-rounded device pixels, not app units.
struct DecorationRectParams
{
// The width [length] and the height [thickness] of the decoration
// line. This is a "logical" size in textRun orientation, so that
// for a vertical textrun, width will actually be a physical height;
// and conversely, height will be a physical width.
Size lineSize;
// The ascent of the text.
Float ascent = 0.0f;
// The offset of the decoration line from the baseline of the text
// (if the value is positive, the line is lifted up).
Float offset = 0.0f;
// If descentLimit is zero or larger and the underline overflows
// from the descent space, the underline should be lifted up as far
// as possible. Note that this does not mean the underline never
// overflows from this limitation, because if the underline is
// positioned to the baseline or upper, it causes unreadability.
// Note that if this is zero or larger, the underline rect may be
// shrunken if it's possible. Therefore, this value is used for
// 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;
// The style of the decoration line such as
// NS_STYLE_TEXT_DECORATION_STYLE_*.
uint8_t style = NS_STYLE_TEXT_DECORATION_STYLE_NONE;
bool vertical = false;
};
struct PaintDecorationLineParams : DecorationRectParams
{
// No need to paint outside this rect.
Rect dirtyRect;
// The top/left edge of the text.
Point pt;
// The color of the decoration line.
nscolor color = NS_RGBA(0, 0, 0, 0);
// The distance between the left edge of the given frame and the
// position of the text as positioned without offset of the shadow.
Float icoordInFrame = 0.0f;
};
/**
* Function for painting the decoration lines for the text.
* NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
* not app units.
* NOTE: aLineSize is a "logical" size in textRun orientation, so that for
* a vertical textrun, aLineSize.width (which is the decoration line
* length) will actually be a physical height; and conversely,
* aLineSize.height [thickness] will be a physical width. The alternate
* names in [brackets] in the comments here apply to the vertical case.
*
* input:
* @param aFrame the frame which needs the decoration line
* @param aGfxContext
* @param aDirtyRect no need to paint outside this rect
* @param aColor the color of the decoration line
* @param aPt the top/left edge of the text
* @param aICoordInFrame the distance between aPt.x [y] and left [top]
* edge of aFrame. If the decoration line is for
* shadow, set the distance between the left edge
* of the aFrame and the position of the text as
* positioned without offset of the shadow.
* @param aLineSize the width [length] and the height [thickness]
* of the decoration line
* @param aAscent the ascent of the text
* @param aOffset the offset of the decoration line from
* the baseline of the text (if the value is
* positive, the line is lifted up [right])
* @param aDecoration 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.
* @param aStyle the style of the decoration line such as
* NS_STYLE_TEXT_DECORATION_STYLE_*.
* @param aDescentLimit If aDescentLimit is zero or larger and the
* underline overflows from the descent space,
* the underline should be lifted up as far as
* possible. Note that this does not mean the
* underline never overflows from this
* limitation. Because if the underline is
* positioned to the baseline or upper, it causes
* unreadability. Note that if this is zero
* or larger, the underline rect may be shrunken
* if it's possible. Therefore, this value is
* used for strikeout line and overline too.
*/
static void PaintDecorationLine(nsIFrame* aFrame,
DrawTarget& aDrawTarget,
const Rect& aDirtyRect,
const nscolor aColor,
const Point& aPt,
const Float aICoordInFrame,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit = -1.0);
static void PaintDecorationLine(nsIFrame* aFrame, DrawTarget& aDrawTarget,
const PaintDecorationLineParams& aParams);
/**
* Returns a Rect corresponding to the outline of the decoration line for the
@ -733,15 +730,7 @@ struct nsCSSRendering {
* PaintDecorationLine. Currently this only works for solid
* decorations; for other decoration styles the returned Rect will be empty.
*/
static Rect DecorationLineToPath(const Rect& aDirtyRect,
const Point& aPt,
const Size& aLineSize,
const Float aAscent,
const Float aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const Float aDescentLimit = -1.0);
static Rect DecorationLineToPath(const PaintDecorationLineParams& aParams);
/**
* Function for getting the decoration line rect for the text.
@ -749,41 +738,12 @@ struct nsCSSRendering {
* not app units.
* input:
* @param aPresContext
* @param aLineSize the width and the height of the decoration
* line
* @param aAscent the ascent of the text
* @param aOffset the offset of the decoration line from
* the baseline of the text (if the value is
* positive, the line is lifted up)
* @param aDecoration 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.
* @param aStyle the style of the decoration line such as
* NS_STYLE_TEXT_DECORATION_STYLE_*.
* @param aDescentLimit If aDescentLimit is zero or larger and the
* underline overflows from the descent space,
* the underline should be lifted up as far as
* possible. Note that this does not mean the
* underline never overflows from this
* limitation. Because if the underline is
* positioned to the baseline or upper, it causes
* unreadability. Note that if this is zero
* or larger, the underline rect may be shrunken
* if it's possible. Therefore, this value is
* used for strikeout line and overline too.
* output:
* @return the decoration line rect for the input,
* the each values are app units.
*/
static nsRect GetTextDecorationRect(nsPresContext* aPresContext,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit = -1.0);
const DecorationRectParams& aParams);
static CompositionOp GetGFXBlendMode(uint8_t mBlendMode) {
switch (mBlendMode) {
@ -818,14 +778,8 @@ struct nsCSSRendering {
}
protected:
static gfxRect GetTextDecorationRectInternal(const Point& aPt,
const Size& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const uint8_t aDecoration,
const uint8_t aStyle,
bool aVertical,
const gfxFloat aDescentLimit);
static gfxRect GetTextDecorationRectInternal(
const Point& aPt, const DecorationRectParams& aParams);
/**
* Returns inflated rect for painting a decoration line.

Просмотреть файл

@ -5235,23 +5235,25 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
nscoord maxAscent = inverted ? fontMetrics->MaxDescent()
: fontMetrics->MaxAscent();
nsCSSRendering::DecorationRectParams params;
gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel();
Float gfxWidth =
(verticalRun ? aVisualOverflowRect->height
: aVisualOverflowRect->width) /
appUnitsPerDevUnit;
gfxFloat gfxAscent = gfxFloat(mAscent) / appUnitsPerDevUnit;
gfxFloat gfxMaxAscent = maxAscent / appUnitsPerDevUnit;
Float gfxUnderlineSize = underlineSize / appUnitsPerDevUnit;
gfxFloat gfxUnderlineOffset = underlineOffset / appUnitsPerDevUnit;
params.lineSize = Size(gfxWidth, underlineSize / appUnitsPerDevUnit);
params.ascent = gfxFloat(mAscent) / appUnitsPerDevUnit;
params.style = decorationStyle;
params.vertical = verticalRun;
params.offset = underlineOffset / appUnitsPerDevUnit;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
nsRect underlineRect =
nsCSSRendering::GetTextDecorationRect(aPresContext,
Size(gfxWidth, gfxUnderlineSize), gfxAscent, gfxUnderlineOffset,
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle, verticalRun);
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
params.offset = maxAscent / appUnitsPerDevUnit;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
nsRect overlineRect =
nsCSSRendering::GetTextDecorationRect(aPresContext,
Size(gfxWidth, gfxUnderlineSize), gfxAscent, gfxMaxAscent,
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle, verticalRun);
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
aVisualOverflowRect->UnionRect(*aVisualOverflowRect, underlineRect);
aVisualOverflowRect->UnionRect(*aVisualOverflowRect, overlineRect);
@ -5279,17 +5281,23 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
ascent = -ascent;
}
nsCSSRendering::DecorationRectParams params;
params.lineSize = Size(gfxWidth, 0);
params.ascent = ascent;
params.vertical = verticalRun;
nscoord topOrLeft(nscoord_MAX), bottomOrRight(nscoord_MIN);
// 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;
for (uint32_t i = 0; i < textDecs.mUnderlines.Length(); ++i) {
const LineDecoration& dec = textDecs.mUnderlines[i];
uint8_t decorationStyle = dec.mStyle;
params.style = dec.mStyle;
// If the style is solid, let's include decoration line rect of solid
// style since changing the style from none to solid/dotted/dashed
// doesn't cause reflow.
if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
}
float inflation =
@ -5298,12 +5306,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
useVerticalMetrics);
params.lineSize.height = metrics.underlineSize;
params.offset = metrics.underlineOffset;
const nsRect decorationRect =
nsCSSRendering::GetTextDecorationRect(aPresContext,
Size(gfxWidth, metrics.underlineSize),
ascent, metrics.underlineOffset,
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle,
verticalRun) +
nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
nsPoint(0, -dec.mBaselineOffset);
if (verticalRun) {
@ -5314,14 +5320,15 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight);
}
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
for (uint32_t i = 0; i < textDecs.mOverlines.Length(); ++i) {
const LineDecoration& dec = textDecs.mOverlines[i];
uint8_t decorationStyle = dec.mStyle;
params.style = dec.mStyle;
// If the style is solid, let's include decoration line rect of solid
// style since changing the style from none to solid/dotted/dashed
// doesn't cause reflow.
if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
}
float inflation =
@ -5330,12 +5337,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
useVerticalMetrics);
params.lineSize.height = metrics.underlineSize;
params.offset = metrics.maxAscent;
const nsRect decorationRect =
nsCSSRendering::GetTextDecorationRect(aPresContext,
Size(gfxWidth, metrics.underlineSize),
ascent, metrics.maxAscent,
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle,
verticalRun) +
nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
nsPoint(0, -dec.mBaselineOffset);
if (verticalRun) {
@ -5346,14 +5351,15 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight);
}
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
for (uint32_t i = 0; i < textDecs.mStrikes.Length(); ++i) {
const LineDecoration& dec = textDecs.mStrikes[i];
uint8_t decorationStyle = dec.mStyle;
params.style = dec.mStyle;
// If the style is solid, let's include decoration line rect of solid
// style since changing the style from none to solid/dotted/dashed
// doesn't cause reflow.
if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
}
float inflation =
@ -5362,12 +5368,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
useVerticalMetrics);
params.lineSize.height = metrics.strikeoutSize;
params.offset = metrics.strikeoutOffset;
const nsRect decorationRect =
nsCSSRendering::GetTextDecorationRect(aPresContext,
Size(gfxWidth, metrics.strikeoutSize),
ascent, metrics.strikeoutOffset,
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorationStyle,
verticalRun) +
nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
nsPoint(0, -dec.mBaselineOffset);
if (verticalRun) {
@ -5479,21 +5483,27 @@ nsTextFrame::PaintDecorationLine(gfxContext* const aCtx,
bool aVertical,
gfxFloat aDescentLimit /* = -1.0 */)
{
nscolor lineColor = aOverrideColor ? *aOverrideColor : aColor;
nsCSSRendering::PaintDecorationLineParams params;
params.dirtyRect = aDirtyRect.ToUnknownRect();
params.pt = aPt;
params.color = aOverrideColor ? *aOverrideColor : aColor;
params.icoordInFrame = Float(aICoordInFrame);
params.lineSize = aLineSize;
params.ascent = aAscent;
params.offset = aOffset;
params.decoration = aDecoration;
params.style = aStyle;
params.vertical = aVertical;
params.descentLimit = aDescentLimit;
if (aCallbacks) {
Rect path = nsCSSRendering::DecorationLineToPath(
aDirtyRect.ToUnknownRect(), aPt, aLineSize, aAscent,
aOffset, aDecoration, aStyle, aVertical, aDescentLimit);
Rect path = nsCSSRendering::DecorationLineToPath(params);
if (aDecorationType == eNormalDecoration) {
aCallbacks->PaintDecorationLine(path, lineColor);
aCallbacks->PaintDecorationLine(path, params.color);
} else {
aCallbacks->PaintSelectionDecorationLine(path, lineColor);
aCallbacks->PaintSelectionDecorationLine(path, params.color);
}
} else {
nsCSSRendering::PaintDecorationLine(
this, *aCtx->GetDrawTarget(), aDirtyRect.ToUnknownRect(), lineColor,
aPt, Float(aICoordInFrame), aLineSize, aAscent, aOffset, aDecoration, aStyle,
aVertical, aDescentLimit);
nsCSSRendering::PaintDecorationLine(this, *aCtx->GetDrawTarget(), params);
}
}
@ -6951,23 +6961,26 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
const gfxFont::Metrics& metrics =
firstFont->GetMetrics(useVerticalMetrics ? gfxFont::eVertical
: gfxFont::eHorizontal);
gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
gfxFloat descentLimit =
nsCSSRendering::DecorationRectParams params;
params.ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
params.offset = fontGroup->GetUnderlineOffset();
params.descentLimit =
ComputeDescentLimitForSelectionUnderline(aPresContext, metrics);
params.vertical = verticalRun;
SelectionDetails *details = GetSelectionDetails();
for (SelectionDetails *sd = details; sd; sd = sd->mNext) {
if (sd->mStart == sd->mEnd || !(sd->mType & SelectionTypesWithDecorations))
continue;
uint8_t style;
float relativeSize;
int32_t index =
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(sd->mType);
if (sd->mType == nsISelectionController::SELECTION_SPELLCHECK) {
if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index, nullptr,
&relativeSize, &style)) {
&relativeSize,
&params.style)) {
continue;
}
} else {
@ -6978,24 +6991,23 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
rangeStyle.mLineStyle == TextRangeStyle::LINESTYLE_NONE) {
continue;
}
style = rangeStyle.mLineStyle;
params.style = rangeStyle.mLineStyle;
relativeSize = rangeStyle.mIsBoldLine ? 2.0f : 1.0f;
} else if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index,
nullptr, &relativeSize,
&style)) {
&params.style)) {
continue;
}
}
nsRect decorationArea;
Size size(aPresContext->AppUnitsToGfxUnits(aRect.width),
ComputeSelectionUnderlineHeight(aPresContext,
metrics, sd->mType));
params.lineSize = Size(aPresContext->AppUnitsToGfxUnits(aRect.width),
ComputeSelectionUnderlineHeight(aPresContext,
metrics, sd->mType));
relativeSize = std::max(relativeSize, 1.0f);
size.height *= relativeSize;
params.lineSize.height *= relativeSize;
decorationArea =
nsCSSRendering::GetTextDecorationRect(aPresContext, size,
ascent, underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
style, verticalRun, descentLimit);
nsCSSRendering::GetTextDecorationRect(aPresContext, params);
aRect.UnionRect(aRect, decorationArea);
}
DestroySelectionDetails(details);

Просмотреть файл

@ -479,12 +479,15 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent);
}
Point pt(presContext->AppUnitsToGfxUnits(aTextRect.x),
presContext->AppUnitsToGfxUnits(aTextRect.y));
Float width = presContext->AppUnitsToGfxUnits(aTextRect.width);
gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
Float xInFrame = Float(PresContext()->AppUnitsToGfxUnits(mTextDrawRect.x));
gfxRect dirtyRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
nsCSSRendering::PaintDecorationLineParams params;
params.dirtyRect = ToRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
params.pt = Point(presContext->AppUnitsToGfxUnits(aTextRect.x),
presContext->AppUnitsToGfxUnits(aTextRect.y));
params.icoordInFrame =
Float(PresContext()->AppUnitsToGfxUnits(mTextDrawRect.x));
params.lineSize = Size(presContext->AppUnitsToGfxUnits(aTextRect.width), 0);
params.ascent = presContext->AppUnitsToGfxUnits(ascent);
params.vertical = vertical;
// XXX todo: vertical-mode support for decorations not tested yet,
// probably won't be positioned correctly
@ -497,25 +500,22 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
if (decorations & (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE |
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE)) {
fontMet->GetUnderline(offset, size);
gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
Float sizePixel = presContext->AppUnitsToGfxUnits(size);
params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
nsCSSRendering::PaintDecorationLine(this, *drawTarget,
ToRect(dirtyRect), underColor,
pt, xInFrame, Size(width, sizePixel),
ascentPixel, offsetPixel,
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle,
vertical);
params.color = underColor;
params.offset = presContext->AppUnitsToGfxUnits(offset);
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
params.style = underStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
nsCSSRendering::PaintDecorationLine(this, *drawTarget,
ToRect(dirtyRect), overColor,
pt, xInFrame, Size(width, sizePixel),
ascentPixel, ascentPixel,
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle,
vertical);
params.color = overColor;
params.offset = params.ascent;
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
params.style = overStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}
}
@ -592,13 +592,12 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
fontMet->GetStrikeout(offset, size);
gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
nsCSSRendering::PaintDecorationLine(this, *drawTarget, ToRect(dirtyRect),
strikeColor,
pt, xInFrame, Size(width, sizePixel), ascentPixel,
offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
strikeStyle, vertical);
params.color = strikeColor;
params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
params.offset = presContext->AppUnitsToGfxUnits(offset);
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
params.style = strikeStyle;
nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
}
}