mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1012797 - Speed up rendering of linear gradients when only painting the uniform color beyond the gradient edge. r=roc
This commit is contained in:
parent
1bf339ea5d
commit
917c3cf573
@ -2156,6 +2156,68 @@ FindTileStart(nscoord aDirtyCoord, nscoord aTilePos, nscoord aTileDim)
|
||||
return NSToCoordRound(multiples*aTileDim + aTilePos);
|
||||
}
|
||||
|
||||
static gfxFloat
|
||||
LinearGradientStopPositionForPoint(const gfxPoint& aGradientStart,
|
||||
const gfxPoint& aGradientEnd,
|
||||
const gfxPoint& aPoint)
|
||||
{
|
||||
gfxPoint d = aGradientEnd - aGradientStart;
|
||||
gfxPoint p = aPoint - aGradientStart;
|
||||
/**
|
||||
* Compute a parameter t such that a line perpendicular to the
|
||||
* d vector, passing through aGradientStart + d*t, also
|
||||
* passes through aPoint.
|
||||
*
|
||||
* t is given by
|
||||
* (p.x - d.x*t)*d.x + (p.y - d.y*t)*d.y = 0
|
||||
*
|
||||
* Solving for t we get
|
||||
* numerator = d.x*p.x + d.y*p.y
|
||||
* denominator = d.x^2 + d.y^2
|
||||
* t = numerator/denominator
|
||||
*
|
||||
* In nsCSSRendering::PaintGradient we know the length of d
|
||||
* is not zero.
|
||||
*/
|
||||
double numerator = d.x * p.x + d.y * p.y;
|
||||
double denominator = d.x * d.x + d.y * d.y;
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
static bool
|
||||
RectIsBeyondLinearGradientEdge(const gfxRect& aRect,
|
||||
const gfxMatrix& aPatternMatrix,
|
||||
const nsTArray<ColorStop>& aStops,
|
||||
const gfxPoint& aGradientStart,
|
||||
const gfxPoint& aGradientEnd,
|
||||
gfxRGBA* aOutEdgeColor)
|
||||
{
|
||||
gfxFloat topLeft = LinearGradientStopPositionForPoint(
|
||||
aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopLeft()));
|
||||
gfxFloat topRight = LinearGradientStopPositionForPoint(
|
||||
aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopRight()));
|
||||
gfxFloat bottomLeft = LinearGradientStopPositionForPoint(
|
||||
aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomLeft()));
|
||||
gfxFloat bottomRight = LinearGradientStopPositionForPoint(
|
||||
aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomRight()));
|
||||
|
||||
const ColorStop& firstStop = aStops[0];
|
||||
if (topLeft < firstStop.mPosition && topRight < firstStop.mPosition &&
|
||||
bottomLeft < firstStop.mPosition && bottomRight < firstStop.mPosition) {
|
||||
*aOutEdgeColor = firstStop.mColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
const ColorStop& lastStop = aStops.LastElement();
|
||||
if (topLeft >= lastStop.mPosition && topRight >= lastStop.mPosition &&
|
||||
bottomLeft >= lastStop.mPosition && bottomRight >= lastStop.mPosition) {
|
||||
*aOutEdgeColor = lastStop.mColor;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
@ -2362,11 +2424,13 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
||||
nsRefPtr<gfxPattern> gradientPattern;
|
||||
bool forceRepeatToCoverTiles = false;
|
||||
gfxMatrix matrix;
|
||||
gfxPoint gradientStart;
|
||||
gfxPoint gradientEnd;
|
||||
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
|
||||
// Compute the actual gradient line ends we need to pass to cairo after
|
||||
// stops have been normalized.
|
||||
gfxPoint gradientStart = lineStart + (lineEnd - lineStart)*stopOrigin;
|
||||
gfxPoint gradientEnd = lineStart + (lineEnd - lineStart)*stopEnd;
|
||||
gradientStart = lineStart + (lineEnd - lineStart)*stopOrigin;
|
||||
gradientEnd = lineStart + (lineEnd - lineStart)*stopEnd;
|
||||
gfxPoint gradientStopStart = lineStart + (lineEnd - lineStart)*firstStop;
|
||||
gfxPoint gradientStopEnd = lineStart + (lineEnd - lineStart)*lastStop;
|
||||
|
||||
@ -2488,6 +2552,9 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
||||
|
||||
gfxRect areaToFill =
|
||||
nsLayoutUtils::RectToGfxRect(aFillArea, appUnitsPerDevPixel);
|
||||
gfxRect dirtyAreaToFill = nsLayoutUtils::RectToGfxRect(dirty, appUnitsPerDevPixel);
|
||||
dirtyAreaToFill.RoundOut();
|
||||
|
||||
gfxMatrix ctm = ctx->CurrentMatrix();
|
||||
bool isCTMPreservingAxisAlignedRectangles = ctm.PreservesAxisAlignedRectangles();
|
||||
|
||||
@ -2535,8 +2602,18 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
|
||||
}
|
||||
ctx->NewPath();
|
||||
ctx->Rectangle(fillRect);
|
||||
ctx->Translate(tileRect.TopLeft());
|
||||
ctx->SetPattern(gradientPattern);
|
||||
|
||||
gfxRect dirtyFillRect = fillRect.Intersect(dirtyAreaToFill);
|
||||
gfxRect fillRectRelativeToTile = dirtyFillRect - tileRect.TopLeft();
|
||||
gfxRGBA edgeColor;
|
||||
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR && !isRepeat &&
|
||||
RectIsBeyondLinearGradientEdge(fillRectRelativeToTile, matrix, stops,
|
||||
gradientStart, gradientEnd, &edgeColor)) {
|
||||
ctx->SetColor(edgeColor);
|
||||
} else {
|
||||
ctx->Translate(tileRect.TopLeft());
|
||||
ctx->SetPattern(gradientPattern);
|
||||
}
|
||||
ctx->Fill();
|
||||
ctx->SetMatrix(ctm);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user