mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 952977: Convert SnapTransforms to gfx::Matrix r=nical
This commit is contained in:
parent
b8f0bd8317
commit
7e28db3ce2
@ -206,6 +206,10 @@ public:
|
||||
FuzzyEqual(_32, floorf(_32 + 0.5f));
|
||||
}
|
||||
|
||||
Point GetTranslation() const {
|
||||
return Point(_31, _32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if matrix is multiple of 90 degrees rotation with flipping,
|
||||
* scaling and translation.
|
||||
@ -259,6 +263,21 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Is2D(Matrix* aMatrix) const {
|
||||
if (!Is2D()) {
|
||||
return false;
|
||||
}
|
||||
if (aMatrix) {
|
||||
aMatrix->_11 = _11;
|
||||
aMatrix->_12 = _12;
|
||||
aMatrix->_21 = _21;
|
||||
aMatrix->_22 = _22;
|
||||
aMatrix->_31 = _41;
|
||||
aMatrix->_32 = _42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Matrix As2D() const
|
||||
{
|
||||
MOZ_ASSERT(Is2D(), "Matrix is not a 2D affine transform");
|
||||
@ -266,6 +285,17 @@ public:
|
||||
return Matrix(_11, _12, _21, _22, _41, _42);
|
||||
}
|
||||
|
||||
static Matrix4x4 From2D(const Matrix &aMatrix) {
|
||||
Matrix4x4 matrix;
|
||||
matrix._11 = aMatrix._11;
|
||||
matrix._12 = aMatrix._12;
|
||||
matrix._21 = aMatrix._21;
|
||||
matrix._22 = aMatrix._22;
|
||||
matrix._41 = aMatrix._31;
|
||||
matrix._42 = aMatrix._32;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
bool Is2DIntegerTranslation() const
|
||||
{
|
||||
return Is2D() && As2D().IsIntegerTranslation();
|
||||
|
@ -29,7 +29,8 @@ void ImageLayer::SetContainer(ImageContainer* aContainer)
|
||||
|
||||
void ImageLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
gfx3DMatrix local = GetLocalTransform();
|
||||
gfx::Matrix4x4 local;
|
||||
gfx::ToMatrix4x4(GetLocalTransform(), local);
|
||||
|
||||
// Snap image edges to pixel boundaries
|
||||
gfxRect sourceRect(0, 0, 0, 0);
|
||||
@ -47,10 +48,11 @@ void ImageLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurfa
|
||||
// This makes our snapping equivalent to what would happen if our content
|
||||
// was drawn into a ThebesLayer (gfxContext would snap using the local
|
||||
// transform, then we'd snap again when compositing the ThebesLayer).
|
||||
gfx3DMatrix snappedTransform =
|
||||
gfx::Matrix4x4 transformToSurface;
|
||||
gfx::ToMatrix4x4(aTransformToSurface, transformToSurface);
|
||||
mEffectiveTransform =
|
||||
SnapTransform(local, sourceRect, nullptr) *
|
||||
SnapTransformTranslation(aTransformToSurface, nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
SnapTransformTranslation(transformToSurface, nullptr);
|
||||
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
|
||||
}
|
||||
|
||||
|
@ -467,30 +467,31 @@ Layer::GetEffectiveVisibleRegion()
|
||||
return GetVisibleRegion();
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
Layer::SnapTransformTranslation(const gfx3DMatrix& aTransform,
|
||||
gfxMatrix* aResidualTransform)
|
||||
Matrix4x4
|
||||
Layer::SnapTransformTranslation(const Matrix4x4& aTransform,
|
||||
Matrix* aResidualTransform)
|
||||
{
|
||||
if (aResidualTransform) {
|
||||
*aResidualTransform = gfxMatrix();
|
||||
*aResidualTransform = Matrix();
|
||||
}
|
||||
|
||||
gfxMatrix matrix2D;
|
||||
gfx3DMatrix result;
|
||||
Matrix matrix2D;
|
||||
Matrix4x4 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);
|
||||
IntPoint snappedTranslation = RoundedToInt(matrix2D.GetTranslation());
|
||||
Matrix snappedMatrix = Matrix().Translate(snappedTranslation.x,
|
||||
snappedTranslation.y);
|
||||
result = Matrix4x4::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);
|
||||
Matrix().Translate(matrix2D._31 - snappedTranslation.x,
|
||||
matrix2D._32 - snappedTranslation.y);
|
||||
}
|
||||
} else {
|
||||
result = aTransform;
|
||||
@ -498,37 +499,34 @@ Layer::SnapTransformTranslation(const gfx3DMatrix& aTransform,
|
||||
return result;
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
Layer::SnapTransform(const gfx3DMatrix& aTransform,
|
||||
Matrix4x4
|
||||
Layer::SnapTransform(const Matrix4x4& aTransform,
|
||||
const gfxRect& aSnapRect,
|
||||
gfxMatrix* aResidualTransform)
|
||||
Matrix* aResidualTransform)
|
||||
{
|
||||
if (aResidualTransform) {
|
||||
*aResidualTransform = gfxMatrix();
|
||||
*aResidualTransform = Matrix();
|
||||
}
|
||||
|
||||
gfxMatrix matrix2D;
|
||||
gfx3DMatrix result;
|
||||
Matrix matrix2D;
|
||||
Matrix4x4 result;
|
||||
if (mManager->IsSnappingEffectiveTransforms() &&
|
||||
aTransform.Is2D(&matrix2D) &&
|
||||
gfx::Size(1.0, 1.0) <= ToSize(aSnapRect.Size()) &&
|
||||
matrix2D.PreservesAxisAlignedRectangles()) {
|
||||
gfxPoint transformedTopLeft = matrix2D.Transform(aSnapRect.TopLeft());
|
||||
transformedTopLeft.Round();
|
||||
gfxPoint transformedTopRight = matrix2D.Transform(aSnapRect.TopRight());
|
||||
transformedTopRight.Round();
|
||||
gfxPoint transformedBottomRight = matrix2D.Transform(aSnapRect.BottomRight());
|
||||
transformedBottomRight.Round();
|
||||
IntPoint transformedTopLeft = RoundedToInt(matrix2D * ToPoint(aSnapRect.TopLeft()));
|
||||
IntPoint transformedTopRight = RoundedToInt(matrix2D * ToPoint(aSnapRect.TopRight()));
|
||||
IntPoint transformedBottomRight = RoundedToInt(matrix2D * ToPoint(aSnapRect.BottomRight()));
|
||||
|
||||
gfxMatrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
|
||||
Matrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
|
||||
transformedTopLeft, transformedTopRight, transformedBottomRight);
|
||||
|
||||
result = gfx3DMatrix::From2D(snappedMatrix);
|
||||
result = Matrix4x4::From2D(snappedMatrix);
|
||||
if (aResidualTransform && !snappedMatrix.IsSingular()) {
|
||||
// set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
|
||||
// (i.e., appying snappedMatrix after aResidualTransform gives the
|
||||
// ideal transform.
|
||||
gfxMatrix snappedMatrixInverse = snappedMatrix;
|
||||
Matrix snappedMatrixInverse = snappedMatrix;
|
||||
snappedMatrixInverse.Invert();
|
||||
*aResidualTransform = matrix2D * snappedMatrixInverse;
|
||||
}
|
||||
@ -889,11 +887,12 @@ ContainerLayer::SortChildrenBy3DZOrder(nsTArray<Layer*>& aArray)
|
||||
void
|
||||
ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
gfxMatrix residual;
|
||||
Matrix residual;
|
||||
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
|
||||
idealTransform.ProjectTo2D();
|
||||
gfx3DMatrix snappedTransform = SnapTransformTranslation(idealTransform, &residual);
|
||||
ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
Matrix4x4 ideal;
|
||||
ToMatrix4x4(idealTransform, ideal);
|
||||
mEffectiveTransform = SnapTransformTranslation(ideal, &residual);
|
||||
|
||||
bool useIntermediateSurface;
|
||||
if (GetMaskLayer()) {
|
||||
@ -936,7 +935,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformT
|
||||
|
||||
mUseIntermediateSurface = useIntermediateSurface;
|
||||
if (useIntermediateSurface) {
|
||||
ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual));
|
||||
ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(ThebesMatrix(residual)));
|
||||
} else {
|
||||
ComputeEffectiveTransformsForChildren(idealTransform);
|
||||
}
|
||||
|
@ -1365,8 +1365,8 @@ protected:
|
||||
* @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);
|
||||
gfx::Matrix4x4 SnapTransformTranslation(const gfx::Matrix4x4& aTransform,
|
||||
gfx::Matrix* aResidualTransform);
|
||||
/**
|
||||
* See comment for SnapTransformTranslation.
|
||||
* This function implements type 2 snapping. If aTransform is a translation
|
||||
@ -1378,9 +1378,9 @@ protected:
|
||||
* @param aResidualTransform a transform to apply before the result transform
|
||||
* in order to get the results to completely match aTransform.
|
||||
*/
|
||||
gfx3DMatrix SnapTransform(const gfx3DMatrix& aTransform,
|
||||
const gfxRect& aSnapRect,
|
||||
gfxMatrix* aResidualTransform);
|
||||
gfx::Matrix4x4 SnapTransform(const gfx::Matrix4x4& aTransform,
|
||||
const gfxRect& aSnapRect,
|
||||
gfx::Matrix* aResidualTransform);
|
||||
|
||||
/**
|
||||
* Returns true if this layer's effective transform is not just
|
||||
@ -1480,17 +1480,17 @@ public:
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
|
||||
gfxMatrix residual;
|
||||
gfx3DMatrix snappedTransform = SnapTransformTranslation(idealTransform,
|
||||
gfx::Matrix4x4 idealTransform;
|
||||
gfx::ToMatrix4x4(GetLocalTransform() * aTransformToSurface, idealTransform);
|
||||
gfx::Matrix residual;
|
||||
mEffectiveTransform = SnapTransformTranslation(idealTransform,
|
||||
mAllowResidualTranslation ? &residual : nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
// The residual can only be a translation because SnapTransformTranslation
|
||||
// only changes the transform if it's a translation
|
||||
NS_ASSERTION(!residual.HasNonTranslation(),
|
||||
NS_ASSERTION(residual.IsTranslation(),
|
||||
"Residual transform can only be a translation");
|
||||
if (!residual.GetTranslation().WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
|
||||
mResidualTranslation = residual.GetTranslation();
|
||||
if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
|
||||
mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation());
|
||||
NS_ASSERTION(-0.5 <= mResidualTranslation.x && mResidualTranslation.x < 0.5 &&
|
||||
-0.5 <= mResidualTranslation.y && mResidualTranslation.y < 0.5,
|
||||
"Residual translation out of range");
|
||||
@ -1753,9 +1753,9 @@ public:
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
|
||||
gfx3DMatrix snappedTransform = SnapTransformTranslation(idealTransform, nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
gfx::Matrix4x4 idealTransform;
|
||||
gfx::ToMatrix4x4(GetLocalTransform() * aTransformToSurface, idealTransform);
|
||||
mEffectiveTransform = SnapTransformTranslation(idealTransform, nullptr);
|
||||
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
|
||||
}
|
||||
|
||||
@ -1898,11 +1898,14 @@ public:
|
||||
// This makes our snapping equivalent to what would happen if our content
|
||||
// was drawn into a ThebesLayer (gfxContext would snap using the local
|
||||
// transform, then we'd snap again when compositing the ThebesLayer).
|
||||
gfx3DMatrix snappedTransform =
|
||||
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
|
||||
gfx::Matrix4x4 localTransform;
|
||||
gfx::Matrix4x4 transformToSurface;
|
||||
gfx::ToMatrix4x4(GetLocalTransform(), localTransform);
|
||||
gfx::ToMatrix4x4(aTransformToSurface, transformToSurface);
|
||||
mEffectiveTransform =
|
||||
SnapTransform(localTransform, gfxRect(0, 0, mBounds.width, mBounds.height),
|
||||
nullptr)*
|
||||
SnapTransformTranslation(aTransformToSurface, nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
SnapTransformTranslation(transformToSurface, nullptr);
|
||||
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
|
||||
}
|
||||
|
||||
|
@ -90,11 +90,13 @@ public:
|
||||
// This makes our snapping equivalent to what would happen if our content
|
||||
// was drawn into a ThebesLayer (gfxContext would snap using the local
|
||||
// transform, then we'd snap again when compositing the ThebesLayer).
|
||||
gfx3DMatrix snappedTransform =
|
||||
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
|
||||
gfx::Matrix4x4 localTransform, transformToSurface;
|
||||
gfx::ToMatrix4x4(aTransformToSurface, transformToSurface);
|
||||
gfx::ToMatrix4x4(GetLocalTransform(), localTransform);
|
||||
mEffectiveTransform =
|
||||
SnapTransform(localTransform, gfxRect(0, 0, mSize.width, mSize.height),
|
||||
nullptr)*
|
||||
SnapTransformTranslation(aTransformToSurface, nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
SnapTransformTranslation(transformToSurface, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
|
||||
// We push groups for container layers if we need to, which always
|
||||
// are aligned in device space, so it doesn't really matter how we snap
|
||||
// containers.
|
||||
gfxMatrix residual;
|
||||
Matrix residual;
|
||||
gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
|
||||
idealTransform.ProjectTo2D();
|
||||
|
||||
@ -51,8 +51,9 @@ BasicContainerLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
|
||||
return;
|
||||
}
|
||||
|
||||
gfx3DMatrix snappedTransform = SnapTransformTranslation(idealTransform, &residual);
|
||||
ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
Matrix4x4 ideal;
|
||||
ToMatrix4x4(idealTransform, ideal);
|
||||
mEffectiveTransform = SnapTransformTranslation(ideal, &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.
|
||||
ComputeEffectiveTransformsForChildren(idealTransform);
|
||||
|
@ -106,7 +106,8 @@ ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect)
|
||||
void
|
||||
ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
gfx3DMatrix local = GetLocalTransform();
|
||||
gfx::Matrix4x4 local;
|
||||
gfx::ToMatrix4x4(GetLocalTransform(), local);
|
||||
|
||||
// Snap image edges to pixel boundaries
|
||||
gfxRect sourceRect(0, 0, 0, 0);
|
||||
@ -129,10 +130,11 @@ ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
|
||||
// This makes our snapping equivalent to what would happen if our content
|
||||
// was drawn into a ThebesLayer (gfxContext would snap using the local
|
||||
// transform, then we'd snap again when compositing the ThebesLayer).
|
||||
gfx3DMatrix snappedTransform =
|
||||
gfx::Matrix4x4 transformToSurface;
|
||||
gfx::ToMatrix4x4(aTransformToSurface, transformToSurface);
|
||||
mEffectiveTransform =
|
||||
SnapTransform(local, sourceRect, nullptr) *
|
||||
SnapTransformTranslation(aTransformToSurface, nullptr);
|
||||
gfx::ToMatrix4x4(snappedTransform, mEffectiveTransform);
|
||||
SnapTransformTranslation(transformToSurface, nullptr);
|
||||
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
|
||||
}
|
||||
|
||||
|
@ -676,6 +676,30 @@ gfxUtils::TransformRectToRect(const gfxRect& aFrom, const gfxPoint& aToTopLeft,
|
||||
return m;
|
||||
}
|
||||
|
||||
Matrix
|
||||
gfxUtils::TransformRectToRect(const gfxRect& aFrom, const IntPoint& aToTopLeft,
|
||||
const IntPoint& aToTopRight, const IntPoint& aToBottomRight)
|
||||
{
|
||||
Matrix m;
|
||||
if (aToTopRight.y == aToTopLeft.y && aToTopRight.x == aToBottomRight.x) {
|
||||
// Not a rotation, so xy and yx are zero
|
||||
m._12 = m._21 = 0.0;
|
||||
m._11 = (aToBottomRight.x - aToTopLeft.x)/aFrom.width;
|
||||
m._22 = (aToBottomRight.y - aToTopLeft.y)/aFrom.height;
|
||||
m._31 = aToTopLeft.x - m._11*aFrom.x;
|
||||
m._32 = aToTopLeft.y - m._22*aFrom.y;
|
||||
} else {
|
||||
NS_ASSERTION(aToTopRight.y == aToBottomRight.y && aToTopRight.x == aToTopLeft.x,
|
||||
"Destination rectangle not axis-aligned");
|
||||
m._11 = m._22 = 0.0;
|
||||
m._21 = (aToBottomRight.x - aToTopLeft.x)/aFrom.height;
|
||||
m._12 = (aToBottomRight.y - aToTopLeft.y)/aFrom.width;
|
||||
m._31 = aToTopLeft.x - m._21*aFrom.y;
|
||||
m._32 = aToTopLeft.y - m._12*aFrom.x;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
|
||||
{
|
||||
|
@ -22,6 +22,8 @@ class PlanarYCbCrData;
|
||||
|
||||
class gfxUtils {
|
||||
public:
|
||||
typedef mozilla::gfx::IntPoint IntPoint;
|
||||
typedef mozilla::gfx::Matrix Matrix;
|
||||
/*
|
||||
* Premultiply or Unpremultiply aSourceSurface, writing the result
|
||||
* to aDestSurface or back into aSourceSurface if aDestSurface is null.
|
||||
@ -109,6 +111,11 @@ public:
|
||||
const gfxPoint& aToTopRight,
|
||||
const gfxPoint& aToBottomRight);
|
||||
|
||||
static Matrix TransformRectToRect(const gfxRect& aFrom,
|
||||
const IntPoint& aToTopLeft,
|
||||
const IntPoint& aToTopRight,
|
||||
const IntPoint& aToBottomRight);
|
||||
|
||||
/**
|
||||
* If aIn can be represented exactly using an nsIntRect (i.e.
|
||||
* integer-aligned edges and coordinates in the int32_t range) then we
|
||||
|
Loading…
x
Reference in New Issue
Block a user