Bug 809478. Handle 90-degree rotations when snapping transformed gradients. r=jrmuizel

--HG--
extra : rebase_source : 61e2873b334f89a0a8b6ae0a7df0dfa37e668d0b
This commit is contained in:
Robert O'Callahan 2012-11-23 14:09:12 +13:00
parent 4e9ee5bd7e
commit b36f5b4ead
4 changed files with 53 additions and 6 deletions

View File

@ -2072,6 +2072,35 @@ FindTileStart(nscoord aDirtyCoord, nscoord aTilePos, nscoord aTileDim)
return NSToCoordRound(multiples*aTileDim + aTilePos);
}
/**
* Return the transform matrix that maps aFrom to the rectangle defined by
* aToTopLeft/aToTopRight/aToBottomRight. The destination rectangle must be
* nonempty and must be axis-aligned.
*/
static gfxMatrix
TransformRectToRect(const gfxRect& aFrom, const gfxPoint& aToTopLeft,
const gfxPoint& aToTopRight, const gfxPoint& aToBottomRight)
{
gfxMatrix m;
if (aToTopRight.y == aToTopLeft.y && aToTopRight.x == aToBottomRight.x) {
// Not a rotation, so xy and yx are zero
m.xy = m.yx = 0.0;
m.xx = (aToBottomRight.x - aToTopLeft.x)/aFrom.width;
m.yy = (aToBottomRight.y - aToTopLeft.y)/aFrom.height;
m.x0 = aToTopLeft.x - m.xx*aFrom.x;
m.y0 = aToTopLeft.y - m.yy*aFrom.y;
} else {
NS_ASSERTION(aToTopRight.y == aToBottomRight.y && aToTopRight.x == aToTopLeft.x,
"Destination rectangle not axis-aligned");
m.xx = m.yy = 0.0;
m.xy = (aToBottomRight.x - aToTopLeft.x)/aFrom.height;
m.yx = (aToBottomRight.y - aToTopLeft.y)/aFrom.width;
m.x0 = aToTopLeft.x - m.xy*aFrom.y;
m.y0 = aToTopLeft.y - m.yx*aFrom.x;
}
return m;
}
void
nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
@ -2392,10 +2421,14 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
// Try snapping the fill rect. Snap its top-left and bottom-right
// independently to preserve the orientation.
gfxPoint snappedFillRectTopLeft = fillRect.TopLeft();
gfxPoint snappedFillRectTopRight = fillRect.TopRight();
gfxPoint snappedFillRectBottomRight = fillRect.BottomRight();
// Snap three points instead of just two to ensure we choose the
// correct orientation if there's a reflection.
if (isCTMPreservingAxisAlignedRectangles &&
ctx->UserToDevicePixelSnapped(snappedFillRectTopLeft, true) &&
ctx->UserToDevicePixelSnapped(snappedFillRectBottomRight, true)) {
ctx->UserToDevicePixelSnapped(snappedFillRectBottomRight, true) &&
ctx->UserToDevicePixelSnapped(snappedFillRectTopRight, true)) {
if (snappedFillRectTopLeft.x == snappedFillRectBottomRight.x ||
snappedFillRectTopLeft.y == snappedFillRectBottomRight.y) {
// Nothing to draw; avoid scaling by zero and other weirdness that
@ -2405,11 +2438,10 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
// Set the context's transform to the transform that maps fillRect to
// snappedFillRect. The part of the gradient that was going to
// exactly fill fillRect will fill snappedFillRect instead.
ctx->IdentityMatrix();
ctx->Translate(snappedFillRectTopLeft);
ctx->Scale((snappedFillRectBottomRight.x - snappedFillRectTopLeft.x)/fillRect.width,
(snappedFillRectBottomRight.y - snappedFillRectTopLeft.y)/fillRect.height);
ctx->Translate(-fillRect.TopLeft());
gfxMatrix transform = TransformRectToRect(fillRect,
snappedFillRectTopLeft, snappedFillRectTopRight,
snappedFillRectBottomRight);
ctx->SetMatrix(transform);
}
ctx->Rectangle(fillRect);
ctx->Translate(tileRect.TopLeft());

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="width:100px; height:100px; background:linear-gradient(to left, red, green);"></div>
<div style="width:100px; height:100px; background:linear-gradient(to right, red, green);"></div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="width:100px; height:100px; transform:rotate(90deg); background:linear-gradient(red, green);"></div>
<div style="width:100px; height:100px; transform:rotate(270deg); background:linear-gradient(red, green);"></div>
</body>
</html>

View File

@ -30,6 +30,7 @@ fails-if(d2d) == linear-repeat-1d.html linear-repeat-1-ref.html # bug 582236
== linear-repeat-1e.html linear-repeat-1-ref.html
fails-if(d2d) == linear-repeat-1f.html linear-repeat-1-ref.html # bug 582236
fails-if(d2d) == linear-repeat-1g.html linear-repeat-1-ref.html # bug 582236
== linear-rotated-1.html linear-rotated-1-ref.html
== linear-size-1a.html linear-size-1-ref.html
== linear-stops-1a.html linear-stops-1-ref.html
== linear-stops-1b.html linear-stops-1-ref.html