Backout 55d5f3cd5c85, d89ae7f40549 & 270391fca858 (bug 663776) for assertions

This commit is contained in:
Ed Morley 2012-12-07 12:37:36 +00:00
parent af7472b3b6
commit 2f3183fde3
9 changed files with 77 additions and 141 deletions

View File

@ -44,7 +44,7 @@ void ImageLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurfa
// transform, then we'd snap again when compositing the ThebesLayer).
mEffectiveTransform =
SnapTransform(local, sourceRect, nullptr) *
SnapTransformTranslation(aTransformToSurface, nullptr);
SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
}

View File

@ -545,70 +545,39 @@ Layer::GetEffectiveVisibleRegion()
return GetVisibleRegion();
}
gfx3DMatrix
Layer::SnapTransformTranslation(const gfx3DMatrix& aTransform,
gfxMatrix* aResidualTransform)
{
gfxMatrix matrix2D;
gfx3DMatrix result;
if (mManager->IsSnappingEffectiveTransforms() &&
aTransform.Is2D(&matrix2D) &&
!matrix2D.HasNonTranslation() &&
matrix2D.HasNonIntegerTranslation()) {
gfxPoint snappedTranslation(matrix2D.GetTranslation());
snappedTranslation.Round();
gfxMatrix snappedMatrix = gfxMatrix().Translate(snappedTranslation);
result = gfx3DMatrix::From2D(snappedMatrix);
if (aResidualTransform) {
// set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
// (I.e., appying snappedMatrix after aResidualTransform gives the
// ideal transform.)
*aResidualTransform =
gfxMatrix().Translate(matrix2D.GetTranslation() - snappedTranslation);
}
} else {
result = aTransform;
if (aResidualTransform) {
*aResidualTransform = gfxMatrix();
}
}
return result;
}
static bool
ComputeMatrixForSnappedRect(const gfxMatrix& aMatrix,
const gfxRect& aSnapRect,
gfxMatrix* aResult)
{
if (!aMatrix.PreservesAxisAlignedRectangles())
return false;
gfxPoint transformedTopLeft = aMatrix.Transform(aSnapRect.TopLeft());
transformedTopLeft.Round();
gfxPoint transformedTopRight = aMatrix.Transform(aSnapRect.TopRight());
transformedTopRight.Round();
gfxPoint transformedBottomRight = aMatrix.Transform(aSnapRect.BottomRight());
transformedBottomRight.Round();
*aResult = gfxUtils::TransformRectToRect(aSnapRect, transformedTopLeft,
transformedTopRight, transformedBottomRight);
return true;
}
gfx3DMatrix
Layer::SnapTransform(const gfx3DMatrix& aTransform,
const gfxRect& aSnapRect,
gfxMatrix* aResidualTransform)
{
if (aResidualTransform) {
*aResidualTransform = gfxMatrix();
}
gfxMatrix matrix2D;
gfx3DMatrix result;
gfxPoint snappedTopLeft;
gfxPoint snappedTopRight;
gfxPoint snappedBottomRight;
gfxMatrix snappedMatrix;
if (mManager->IsSnappingEffectiveTransforms() &&
aTransform.Is2D(&matrix2D) &&
ComputeMatrixForSnappedRect(matrix2D, aSnapRect, &snappedMatrix)) {
matrix2D.HasNonIntegerTranslation() &&
!matrix2D.IsSingular() &&
!matrix2D.HasNonAxisAlignedTransform()) {
gfxMatrix snappedMatrix;
gfxPoint topLeft = matrix2D.Transform(aSnapRect.TopLeft());
topLeft.Round();
// first compute scale factors that scale aSnapRect to the snapped rect
if (aSnapRect.IsEmpty()) {
snappedMatrix.xx = matrix2D.xx;
snappedMatrix.yy = matrix2D.yy;
} else {
gfxPoint bottomRight = matrix2D.Transform(aSnapRect.BottomRight());
bottomRight.Round();
snappedMatrix.xx = (bottomRight.x - topLeft.x)/aSnapRect.Width();
snappedMatrix.yy = (bottomRight.y - topLeft.y)/aSnapRect.Height();
}
// compute translation factors that will move aSnapRect to the snapped rect
// given those scale factors
snappedMatrix.x0 = topLeft.x - aSnapRect.X()*snappedMatrix.xx;
snappedMatrix.y0 = topLeft.y - aSnapRect.Y()*snappedMatrix.yy;
result = gfx3DMatrix::From2D(snappedMatrix);
if (aResidualTransform && !snappedMatrix.IsSingular()) {
// set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
@ -620,9 +589,6 @@ Layer::SnapTransform(const gfx3DMatrix& aTransform,
}
} else {
result = aTransform;
if (aResidualTransform) {
*aResidualTransform = gfxMatrix();
}
}
return result;
}
@ -807,7 +773,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformT
gfxMatrix residual;
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
idealTransform.ProjectTo2D();
mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
bool useIntermediateSurface;
if (GetMaskLayer()) {

View File

@ -1066,42 +1066,15 @@ protected:
const float GetLocalOpacity();
/**
* We can snap layer transforms for two reasons:
* 1) To avoid unnecessary resampling when a transform is a translation
* by a non-integer number of pixels.
* Snapping the translation to an integer number of pixels avoids
* blurring the layer and can be faster to composite.
* 2) When a layer is used to render a rectangular object, we need to
* emulate the rendering of rectangular inactive content and snap the
* edges of the rectangle to pixel boundaries. This is both to ensure
* layer rendering is consistent with inactive content rendering, and to
* avoid seams.
* This function implements type 1 snapping. If aTransform is a 2D
* translation, and this layer's layer manager has enabled snapping
* (which is the default), return aTransform with the translation snapped
* to nearest pixels. Otherwise just return aTransform. Call this when the
* layer does not correspond to a single rectangular content object.
* This function does not try to snap if aTransform has a scale, because in
* that case resampling is inevitable and there's no point in trying to
* avoid it. In fact snapping can cause problems because pixel edges in the
* layer's content can be rendered unpredictably (jiggling) as the scale
* interacts with the snapping of the translation, especially with animated
* transforms.
* @param aResidualTransform a transform to apply before the result transform
* in order to get the results to completely match aTransform.
*/
gfx3DMatrix SnapTransformTranslation(const gfx3DMatrix& aTransform,
gfxMatrix* aResidualTransform);
/**
* See comment for SnapTransformTranslation.
* This function implements type 2 snapping. If aTransform is a translation
* and/or scale, transform aSnapRect by aTransform, snap to pixel boundaries,
* and return the transform that maps aSnapRect to that rect. Otherwise
* just return aTransform.
* Computes a tweaked version of aTransform that snaps a point or a rectangle
* to pixel boundaries. Snapping is only performed if this layer's
* layer manager has enabled snapping (which is the default).
* @param aSnapRect a rectangle whose edges should be snapped to pixel
* boundaries in the destination surface.
* @param aResidualTransform a transform to apply before the result transform
* in order to get the results to completely match aTransform.
* boundaries in the destination surface. If the rectangle is empty,
* then the snapping process should preserve the scale factors of the
* transform matrix
* @param aResidualTransform a transform to apply before mEffectiveTransform
* in order to get the results to completely match aTransform
*/
gfx3DMatrix SnapTransform(const gfx3DMatrix& aTransform,
const gfxRect& aSnapRect,
@ -1182,12 +1155,14 @@ public:
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
// The default implementation just snaps 0,0 to pixels.
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
gfxMatrix residual;
mEffectiveTransform = SnapTransformTranslation(idealTransform,
mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0),
mAllowResidualTranslation ? &residual : nullptr);
// The residual can only be a translation because SnapTransformTranslation
// only changes the transform if it's a translation
// The residual can only be a translation because ThebesLayer snapping
// only aligns a single point with the pixel grid; scale factors are always
// preserved exactly
NS_ASSERTION(!residual.HasNonTranslation(),
"Residual transform can only be a translation");
if (!residual.GetTranslation().WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
@ -1414,8 +1389,9 @@ public:
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
// Snap 0,0 to pixel boundaries, no extra internal transform.
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
mEffectiveTransform = SnapTransformTranslation(idealTransform, nullptr);
mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nullptr);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
}
@ -1526,7 +1502,7 @@ public:
mEffectiveTransform =
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
nullptr)*
SnapTransformTranslation(aTransformToSurface, nullptr);
SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
}

View File

@ -79,7 +79,7 @@ public:
mEffectiveTransform =
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
nullptr)*
SnapTransformTranslation(aTransformToSurface, nullptr);
SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
}
/**

View File

@ -147,9 +147,9 @@ ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
}
aContainer->mEffectiveTransform =
aContainer->SnapTransformTranslation(idealTransform, &residual);
aContainer->SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
// We always pass the ideal matrix down to our children, so there is no
// need to apply any compensation using the residual from SnapTransformTranslation.
// need to apply any compensation using the residual from SnapTransform.
aContainer->ComputeEffectiveTransformsForChildren(idealTransform);
aContainer->ComputeEffectiveTransformForMaskLayer(aTransformToSurface);

View File

@ -619,29 +619,6 @@ gfxUtils::PathFromRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion
PathFromRegionInternal(aContext, aRegion, true);
}
gfxMatrix
gfxUtils::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;
}
bool
gfxUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)

View File

@ -86,16 +86,6 @@ public:
*/
static int ImageFormatToDepth(gfxASurface::gfxImageFormat aFormat);
/**
* Return the transform matrix that maps aFrom to the rectangle defined by
* aToTopLeft/aToTopRight/aToBottomRight. aFrom must be
* nonempty and the destination rectangle must be axis-aligned.
*/
static gfxMatrix TransformRectToRect(const gfxRect& aFrom,
const gfxPoint& aToTopLeft,
const gfxPoint& aToTopRight,
const gfxPoint& aToBottomRight);
/**
* If aIn can be represented exactly using an nsIntRect (i.e.
* integer-aligned edges and coordinates in the int32_t range) then we

View File

@ -2783,11 +2783,10 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
// or it was previously unscaled.
bool clamp = true;
gfxMatrix oldFrameTransform2d;
if (aLayer->GetBaseTransform().Is2D(&oldFrameTransform2d)) {
if (aLayer->GetTransform().Is2D(&oldFrameTransform2d)) {
gfxSize oldScale = oldFrameTransform2d.ScaleFactors(true);
if (oldScale == scale || oldScale == gfxSize(1.0, 1.0)) {
if (oldScale == scale || oldScale == gfxSize(1.0, 1.0))
clamp = false;
}
}
if (clamp) {
scale.width = gfxUtils::ClampToScaleFactor(scale.width);

View File

@ -52,7 +52,6 @@
#include "mozilla/Types.h"
#include <ctime>
#include <cstdlib> // for std::abs(int/long)
#include "gfxUtils.h"
#include <cmath> // for std::abs(float/double)
using namespace mozilla;
@ -2075,6 +2074,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,
@ -2412,7 +2440,7 @@ 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.
gfxMatrix transform = gfxUtils::TransformRectToRect(fillRect,
gfxMatrix transform = TransformRectToRect(fillRect,
snappedFillRectTopLeft, snappedFillRectTopRight,
snappedFillRectBottomRight);
ctx->SetMatrix(transform);