Bug 952977: Switch some uses of gfx3DMatrix in nsLayoutUtils to Matrix4x4 r=nical

This commit is contained in:
David Zbarsky 2014-08-22 09:40:02 -04:00
parent 07112b161c
commit 48fe8afc64
15 changed files with 207 additions and 192 deletions

View File

@ -116,6 +116,8 @@ struct BasePoint4D {
void Normalize() {
*this /= Length();
}
bool HasPositiveWCoord() { return w > 0; }
};
}

View File

@ -5,10 +5,13 @@
#include "Matrix.h"
#include "Tools.h"
#include <algorithm>
#include <math.h>
#include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
using namespace std;
namespace mozilla {
namespace gfx {
@ -24,7 +27,7 @@ Matrix::Rotation(Float aAngle)
newMatrix._12 = s;
newMatrix._21 = -s;
newMatrix._22 = c;
return newMatrix;
}
@ -104,6 +107,73 @@ Matrix4x4::TransformBounds(const Rect& aRect) const
return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
}
Point4D ComputePerspectivePlaneIntercept(const Point4D& aFirst,
const Point4D& aSecond)
{
// FIXME: See bug 1035611
// Since we can't easily deal with points as w=0 (since we divide by w), we
// approximate this by finding a point with w just greater than 0. Unfortunately
// this is a tradeoff between accuracy and floating point precision.
// We want to interpolate aFirst and aSecond to find a point as close to
// the positive side of the w=0 plane as possible.
// Since we know what we want the w component to be, we can rearrange the
// interpolation equation and solve for t.
float w = 0.00001f;
float t = (w - aFirst.w) / (aSecond.w - aFirst.w);
// Use t to find the remainder of the components
return aFirst + (aSecond - aFirst) * t;
}
Rect Matrix4x4::ProjectRectBounds(const Rect& aRect) const
{
Point4D points[4];
points[0] = ProjectPoint(aRect.TopLeft());
points[1] = ProjectPoint(aRect.TopRight());
points[2] = ProjectPoint(aRect.BottomLeft());
points[3] = ProjectPoint(aRect.BottomRight());
Float min_x = std::numeric_limits<Float>::max();
Float min_y = std::numeric_limits<Float>::max();
Float max_x = -std::numeric_limits<Float>::max();
Float max_y = -std::numeric_limits<Float>::max();
bool foundPoint = false;
for (int i=0; i<4; i++) {
// Only use points that exist above the w=0 plane
if (points[i].HasPositiveWCoord()) {
foundPoint = true;
Point point2d = points[i].As2DPoint();
min_x = min<Float>(point2d.x, min_x);
max_x = max<Float>(point2d.x, max_x);
min_y = min<Float>(point2d.y, min_y);
max_y = max<Float>(point2d.y, max_y);
}
int next = (i == 3) ? 0 : i + 1;
if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
// If the line between two points crosses the w=0 plane, then interpolate a point
// as close to the w=0 plane as possible and use that instead.
Point4D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
Point point2d = intercept.As2DPoint();
min_x = min<Float>(point2d.x, min_x);
max_x = max<Float>(point2d.x, max_x);
min_y = min<Float>(point2d.y, min_y);
max_y = max<Float>(point2d.y, max_y);
}
}
if (!foundPoint) {
return Rect(0, 0, 0, 0);
}
return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
}
bool
Matrix4x4::Invert()
{

View File

@ -375,6 +375,19 @@ public:
return *this;
}
Point4D ProjectPoint(const Point& aPoint) const {
// Find a value for z that will transform to 0.
// The transformed value of z is computed as:
// z' = aPoint.x * _13 + aPoint.y * _23 + z * _33 + _43;
// Solving for z when z' = 0 gives us:
float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
// Compute the transformed point
return *this * Point4D(aPoint.x, aPoint.y, z, 1);
}
static Matrix4x4 From2D(const Matrix &aMatrix) {
Matrix4x4 matrix;
matrix._11 = aMatrix._11;
@ -452,6 +465,8 @@ public:
return *this;
}
Rect ProjectRectBounds(const Rect& aRect) const;
Matrix4x4 &PostTranslate(Float aX, Float aY, Float aZ)
{
_11 += _14 * aX;

View File

@ -153,6 +153,10 @@ struct Point4DTyped :
Point4DTyped<UnknownUnits> ToUnknownPoint() const {
return Point4DTyped<UnknownUnits>(this->x, this->y, this->z, this->w);
}
PointTyped<units> As2DPoint() {
return PointTyped<units>(this->x / this->w, this->y / this->w);
}
};
typedef Point4DTyped<UnknownUnits> Point4D;

View File

@ -777,73 +777,6 @@ gfxPointH3D gfx3DMatrix::ProjectPoint(const gfxPoint& aPoint) const
return Transform4D(gfxPointH3D(aPoint.x, aPoint.y, z, 1));
}
gfxPointH3D ComputePerspectivePlaneIntercept(const gfxPointH3D& aFirst,
const gfxPointH3D& aSecond)
{
// FIXME: See bug 1035611
// Since we can't easily deal with points as w=0 (since we divide by w), we
// approximate this by finding a point with w just greater than 0. Unfortunately
// this is a tradeoff between accuracy and floating point precision.
// We want to interpolate aFirst and aSecond to find a point as close to
// the positive side of the w=0 plane as possible.
// Since we know what we want the w component to be, we can rearrange the
// interpolation equation and solve for t.
float w = 0.00001f;
float t = (w - aFirst.w) / (aSecond.w - aFirst.w);
// Use t to find the remainder of the components
return aFirst + (aSecond - aFirst) * t;
}
gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const
{
gfxPointH3D points[4];
points[0] = ProjectPoint(aRect.TopLeft());
points[1] = ProjectPoint(aRect.TopRight());
points[2] = ProjectPoint(aRect.BottomLeft());
points[3] = ProjectPoint(aRect.BottomRight());
gfxFloat min_x = std::numeric_limits<gfxFloat>::max();
gfxFloat min_y = std::numeric_limits<gfxFloat>::max();
gfxFloat max_x = -std::numeric_limits<gfxFloat>::max();
gfxFloat max_y = -std::numeric_limits<gfxFloat>::max();
bool foundPoint = false;
for (int i=0; i<4; i++) {
// Only use points that exist above the w=0 plane
if (points[i].HasPositiveWCoord()) {
foundPoint = true;
gfxPoint point2d = points[i].As2DPoint();
min_x = min(point2d.x, min_x);
max_x = max(point2d.x, max_x);
min_y = min(point2d.y, min_y);
max_y = max(point2d.y, max_y);
}
int next = (i == 3) ? 0 : i + 1;
if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
// If the line between two points crosses the w=0 plane, then interpolate a point
// as close to the w=0 plane as possible and use that instead.
gfxPointH3D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
gfxPoint point2d = intercept.As2DPoint();
min_x = min(point2d.x, min_x);
max_x = max(point2d.x, max_x);
min_y = min(point2d.y, min_y);
max_y = max(point2d.y, max_y);
}
}
if (!foundPoint) {
return gfxRect(0, 0, 0, 0);
}
return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
}
gfxPoint3D gfx3DMatrix::GetNormalVector() const
{
// Define a plane in transformed space as the transformations

View File

@ -264,7 +264,6 @@ public:
* into (x',y',0,w') and returns the latter.
*/
gfxPointH3D ProjectPoint(const gfxPoint& aPoint) const;
gfxRect ProjectRectBounds(const gfxRect& aRect) const;
/**
* Inverts this matrix, if possible. Otherwise, the matrix is left

View File

@ -1737,8 +1737,8 @@ static void
SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion,
const nsIntRect* aLayerContentsVisibleRect = nullptr)
{
gfx3DMatrix transform = To3DMatrix(aLayer->GetTransform());
gfxMatrix transform2D;
Matrix4x4 transform = aLayer->GetTransform();
Matrix transform2D;
if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) {
aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32));
if (aLayerContentsVisibleRect) {
@ -1748,8 +1748,9 @@ SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion,
nsIntRect outerRect = aOuterVisibleRegion->GetBounds();
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
gfxRect outerVisible(outerRect.x, outerRect.y, outerRect.width, outerRect.height);
gfxRect layerVisible = transform.Inverse().ProjectRectBounds(outerVisible);
Rect outerVisible(outerRect.x, outerRect.y, outerRect.width, outerRect.height);
transform.Invert();
gfxRect layerVisible = ThebesRect(transform.ProjectRectBounds(outerVisible));
if (aLayerContentsVisibleRect) {
NS_ASSERTION(aLayerContentsVisibleRect->width >= 0 &&
aLayerContentsVisibleRect->height >= 0,
@ -2208,9 +2209,9 @@ ContainerState::PopThebesLayerData()
if (!data->mHitRegion.GetBounds().IsEmpty()) {
// Our definitely-hit region must go to the maybe-hit-region since
// this function is an approximation.
gfx3DMatrix matrix = nsLayoutUtils::GetTransformToAncestor(
Matrix4x4 matrix = nsLayoutUtils::GetTransformToAncestor(
mContainerReferenceFrame, containingThebesLayerData->mReferenceFrame);
gfxMatrix matrix2D;
Matrix matrix2D;
bool isPrecise = matrix.Is2D(&matrix2D) && !matrix2D.HasNonAxisAlignedTransform();
nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
mContainerReferenceFrame,
@ -3986,15 +3987,14 @@ static gfxSize
PredictScaleForContent(nsIFrame* aFrame, nsIFrame* aAncestorWithScale,
const gfxSize& aScale)
{
gfx3DMatrix transform =
gfx3DMatrix::ScalingMatrix(aScale.width, aScale.height, 1.0);
Matrix4x4 transform = Matrix4x4().Scale(aScale.width, aScale.height, 1.0);
if (aFrame != aAncestorWithScale) {
// aTransform is applied first, then the scale is applied to the result
transform = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestorWithScale)*transform;
}
gfxMatrix transform2d;
Matrix transform2d;
if (transform.CanDraw2D(&transform2d)) {
return transform2d.ScaleFactors(true);
return ThebesMatrix(transform2d).ScaleFactors(true);
}
return gfxSize(1.0, 1.0);
}

View File

@ -5063,19 +5063,20 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
1, 1);
} else {
gfxRect originalRect(NSAppUnitsToFloatPixels(aRect.x, factor),
NSAppUnitsToFloatPixels(aRect.y, factor),
NSAppUnitsToFloatPixels(aRect.width, factor),
NSAppUnitsToFloatPixels(aRect.height, factor));
Rect originalRect(NSAppUnitsToFloatPixels(aRect.x, factor),
NSAppUnitsToFloatPixels(aRect.y, factor),
NSAppUnitsToFloatPixels(aRect.width, factor),
NSAppUnitsToFloatPixels(aRect.height, factor));
gfxRect rect = To3DMatrix(matrix).Inverse().ProjectRectBounds(originalRect);
matrix.Invert();
Rect rect = matrix.ProjectRectBounds(originalRect);
bool snap;
nsRect childBounds = mStoredList.GetBounds(aBuilder, &snap);
gfxRect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
NSAppUnitsToFloatPixels(childBounds.y, factor),
NSAppUnitsToFloatPixels(childBounds.width, factor),
NSAppUnitsToFloatPixels(childBounds.height, factor));
Rect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
NSAppUnitsToFloatPixels(childBounds.y, factor),
NSAppUnitsToFloatPixels(childBounds.width, factor),
NSAppUnitsToFloatPixels(childBounds.height, factor));
rect = rect.Intersect(childGfxBounds);
resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
@ -5304,19 +5305,19 @@ bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
return false;
}
gfxRect result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
Rect result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
gfxRect childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
NSAppUnitsToFloatPixels(aChildBounds.y, factor),
NSAppUnitsToFloatPixels(aChildBounds.width, factor),
NSAppUnitsToFloatPixels(aChildBounds.height, factor));
Rect childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
NSAppUnitsToFloatPixels(aChildBounds.y, factor),
NSAppUnitsToFloatPixels(aChildBounds.width, factor),
NSAppUnitsToFloatPixels(aChildBounds.height, factor));
result = transform.Inverse().ProjectRectBounds(result);
result = ToMatrix4x4(transform.Inverse()).ProjectRectBounds(result);
result = result.Intersect(childGfxBounds);
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(result, factor);
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
return true;
}
@ -5329,23 +5330,23 @@ bool nsDisplayTransform::UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
gfxRect result(NSAppUnitsToFloatPixels(mVisibleRect.x, factor),
NSAppUnitsToFloatPixels(mVisibleRect.y, factor),
NSAppUnitsToFloatPixels(mVisibleRect.width, factor),
NSAppUnitsToFloatPixels(mVisibleRect.height, factor));
Rect result(NSAppUnitsToFloatPixels(mVisibleRect.x, factor),
NSAppUnitsToFloatPixels(mVisibleRect.y, factor),
NSAppUnitsToFloatPixels(mVisibleRect.width, factor),
NSAppUnitsToFloatPixels(mVisibleRect.height, factor));
bool snap;
nsRect childBounds = mStoredList.GetBounds(aBuilder, &snap);
gfxRect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
NSAppUnitsToFloatPixels(childBounds.y, factor),
NSAppUnitsToFloatPixels(childBounds.width, factor),
NSAppUnitsToFloatPixels(childBounds.height, factor));
Rect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
NSAppUnitsToFloatPixels(childBounds.y, factor),
NSAppUnitsToFloatPixels(childBounds.width, factor),
NSAppUnitsToFloatPixels(childBounds.height, factor));
/* We want to untransform the matrix, so invert the transformation first! */
result = matrix.Inverse().ProjectRectBounds(result);
result = ToMatrix4x4(matrix.Inverse()).ProjectRectBounds(result);
result = result.Intersect(childGfxBounds);
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(result, factor);
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
return true;
}

View File

@ -2247,11 +2247,11 @@ nsLayoutUtils::MatrixTransformPoint(const nsPoint &aPoint,
NSFloatPixelsToAppUnits(float(image.y), aFactor));
}
gfx3DMatrix
Matrix4x4
nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor)
{
nsIFrame* parent;
gfx3DMatrix ctm;
Matrix4x4 ctm;
if (aFrame == aAncestor) {
return ctm;
}
@ -2301,12 +2301,12 @@ nsLayoutUtils::TransformPoints(nsIFrame* aFromFrame, nsIFrame* aToFrame,
if (!nearestCommonAncestor) {
return NO_COMMON_ANCESTOR;
}
gfx3DMatrix downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
Matrix4x4 downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
if (downToDest.IsSingular()) {
return NONINVERTIBLE_TRANSFORM;
}
downToDest.Invert();
gfx3DMatrix upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
Matrix4x4 upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
CSSToLayoutDeviceScale devPixelsPerCSSPixelFromFrame(
double(nsPresContext::AppUnitsPerCSSPixel())/
aFromFrame->PresContext()->AppUnitsPerDevPixel());
@ -2317,8 +2317,8 @@ nsLayoutUtils::TransformPoints(nsIFrame* aFromFrame, nsIFrame* aToFrame,
LayoutDevicePoint devPixels = aPoints[i] * devPixelsPerCSSPixelFromFrame;
// What should the behaviour be if some of the points aren't invertible
// and others are? Just assume all points are for now.
gfxPoint toDevPixels = downToDest.ProjectPoint(
upToAncestor.Transform(gfxPoint(devPixels.x, devPixels.y))).As2DPoint();
Point toDevPixels = downToDest.ProjectPoint(
(upToAncestor * Point(devPixels.x, devPixels.y))).As2DPoint();
// Divide here so that when the devPixelsPerCSSPixels are the same, we get the correct
// answer instead of some inaccuracy multiplying a number by its reciprocal.
aPoints[i] = LayoutDevicePoint(toDevPixels.x, toDevPixels.y) /
@ -2335,21 +2335,20 @@ nsLayoutUtils::TransformPoint(nsIFrame* aFromFrame, nsIFrame* aToFrame,
if (!nearestCommonAncestor) {
return NO_COMMON_ANCESTOR;
}
gfx3DMatrix downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
Matrix4x4 downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
if (downToDest.IsSingular()) {
return NONINVERTIBLE_TRANSFORM;
}
downToDest.Invert();
gfx3DMatrix upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
Matrix4x4 upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
float devPixelsPerAppUnitFromFrame =
1.0f / aFromFrame->PresContext()->AppUnitsPerDevPixel();
float devPixelsPerAppUnitToFrame =
1.0f / aToFrame->PresContext()->AppUnitsPerDevPixel();
gfxPointH3D toDevPixels = downToDest.ProjectPoint(
upToAncestor.Transform(
gfxPoint(aPoint.x * devPixelsPerAppUnitFromFrame,
aPoint.y * devPixelsPerAppUnitFromFrame)));
Point4D toDevPixels = downToDest.ProjectPoint(
upToAncestor * Point(aPoint.x * devPixelsPerAppUnitFromFrame,
aPoint.y * devPixelsPerAppUnitFromFrame));
if (!toDevPixels.HasPositiveWCoord()) {
// Not strictly true, but we failed to get a valid point in this
// coordinate space.
@ -2368,23 +2367,23 @@ nsLayoutUtils::TransformRect(nsIFrame* aFromFrame, nsIFrame* aToFrame,
if (!nearestCommonAncestor) {
return NO_COMMON_ANCESTOR;
}
gfx3DMatrix downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
Matrix4x4 downToDest = GetTransformToAncestor(aToFrame, nearestCommonAncestor);
if (downToDest.IsSingular()) {
return NONINVERTIBLE_TRANSFORM;
}
downToDest.Invert();
gfx3DMatrix upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
Matrix4x4 upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
float devPixelsPerAppUnitFromFrame =
1.0f / aFromFrame->PresContext()->AppUnitsPerDevPixel();
float devPixelsPerAppUnitToFrame =
1.0f / aToFrame->PresContext()->AppUnitsPerDevPixel();
gfxRect toDevPixels = downToDest.ProjectRectBounds(
gfx::Rect toDevPixels = downToDest.ProjectRectBounds(
upToAncestor.ProjectRectBounds(
gfxRect(aRect.x * devPixelsPerAppUnitFromFrame,
aRect.y * devPixelsPerAppUnitFromFrame,
aRect.width * devPixelsPerAppUnitFromFrame,
aRect.height * devPixelsPerAppUnitFromFrame)));
gfx::Rect(aRect.x * devPixelsPerAppUnitFromFrame,
aRect.y * devPixelsPerAppUnitFromFrame,
aRect.width * devPixelsPerAppUnitFromFrame,
aRect.height * devPixelsPerAppUnitFromFrame)));
aRect.x = toDevPixels.x / devPixelsPerAppUnitToFrame;
aRect.y = toDevPixels.y / devPixelsPerAppUnitToFrame;
aRect.width = toDevPixels.width / devPixelsPerAppUnitToFrame;
@ -2394,7 +2393,7 @@ nsLayoutUtils::TransformRect(nsIFrame* aFromFrame, nsIFrame* aToFrame,
bool
nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
gfx3DMatrix* aTransform)
Matrix4x4* aTransform)
{
// FIXME/bug 796690: we can sometimes compute a transform in these
// cases, it just increases complexity considerably. Punt for now.
@ -2420,8 +2419,7 @@ nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
nsDisplayTransform* item =
new (&builder) nsDisplayTransform(&builder, aFrame, &list, nsRect());
*aTransform =
To3DMatrix(item->GetTransform());
*aTransform = item->GetTransform();
item->~nsDisplayTransform();
return true;
@ -2429,19 +2427,13 @@ nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
static bool
TransformGfxPointFromAncestor(nsIFrame *aFrame,
const gfxPoint &aPoint,
const Point &aPoint,
nsIFrame *aAncestor,
gfxPoint* aOut)
Point* aOut)
{
gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
nsRect childBounds = aFrame->GetVisualOverflowRectRelativeToSelf();
gfxRect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
NSAppUnitsToFloatPixels(childBounds.y, factor),
NSAppUnitsToFloatPixels(childBounds.width, factor),
NSAppUnitsToFloatPixels(childBounds.height, factor));
gfxPointH3D point = ctm.Inverse().ProjectPoint(aPoint);
Matrix4x4 ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
ctm.Invert();
Point4D point = ctm.ProjectPoint(aPoint);
if (!point.HasPositiveWCoord()) {
return false;
}
@ -2449,15 +2441,15 @@ TransformGfxPointFromAncestor(nsIFrame *aFrame,
return true;
}
static gfxRect
static Rect
TransformGfxRectToAncestor(nsIFrame *aFrame,
const gfxRect &aRect,
const Rect &aRect,
const nsIFrame *aAncestor,
bool* aPreservesAxisAlignedRectangles = nullptr)
{
gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
Matrix4x4 ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
if (aPreservesAxisAlignedRectangles) {
gfxMatrix matrix2d;
Matrix matrix2d;
*aPreservesAxisAlignedRectangles =
ctm.Is2D(&matrix2d) && matrix2d.PreservesAxisAlignedRectangles();
}
@ -2484,8 +2476,8 @@ nsLayoutUtils::TransformAncestorPointToFrame(nsIFrame* aFrame,
SVGTextFrame* text = GetContainingSVGTextFrame(aFrame);
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
gfxPoint result(NSAppUnitsToFloatPixels(aPoint.x, factor),
NSAppUnitsToFloatPixels(aPoint.y, factor));
Point result(NSAppUnitsToFloatPixels(aPoint.x, factor),
NSAppUnitsToFloatPixels(aPoint.y, factor));
if (text) {
if (!TransformGfxPointFromAncestor(text, result, aAncestor, &result)) {
@ -2511,20 +2503,20 @@ nsLayoutUtils::TransformFrameRectToAncestor(nsIFrame* aFrame,
SVGTextFrame* text = GetContainingSVGTextFrame(aFrame);
float srcAppUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
gfxRect result;
Rect result;
if (text) {
result = text->TransformFrameRectFromTextChild(aRect, aFrame);
result = ToRect(text->TransformFrameRectFromTextChild(aRect, aFrame));
result = TransformGfxRectToAncestor(text, result, aAncestor);
// TransformFrameRectFromTextChild could involve any kind of transform, we
// could drill down into it to get an answer out of it but we don't yet.
if (aPreservesAxisAlignedRectangles)
*aPreservesAxisAlignedRectangles = false;
} else {
result = gfxRect(NSAppUnitsToFloatPixels(aRect.x, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.y, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.width, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.height, srcAppUnitsPerDevPixel));
result = Rect(NSAppUnitsToFloatPixels(aRect.x, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.y, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.width, srcAppUnitsPerDevPixel),
NSAppUnitsToFloatPixels(aRect.height, srcAppUnitsPerDevPixel));
result = TransformGfxRectToAncestor(aFrame, result, aAncestor, aPreservesAxisAlignedRectangles);
}

View File

@ -122,6 +122,7 @@ class nsLayoutUtils
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
public:
typedef mozilla::layers::FrameMetrics FrameMetrics;
@ -718,7 +719,7 @@ public:
* Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor
* to go up to the root frame.
*/
static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor);
static Matrix4x4 GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor);
/**
* Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into
@ -760,7 +761,7 @@ public:
* transaction were opened at the time this helper is called.
*/
static bool GetLayerTransformForFrame(nsIFrame* aFrame,
gfx3DMatrix* aTransform);
Matrix4x4* aTransform);
/**
* Given a point in the global coordinate space, returns that point expressed

View File

@ -462,11 +462,11 @@ nsComboboxControlFrame::GetCSSTransformTranslation()
{
nsIFrame* frame = this;
bool is3DTransform = false;
gfxMatrix transform;
Matrix transform;
while (frame) {
nsIFrame* parent;
gfx3DMatrix ctm = frame->GetTransformMatrix(nullptr, &parent);
gfxMatrix matrix;
Matrix4x4 ctm = frame->GetTransformMatrix(nullptr, &parent);
Matrix matrix;
if (ctm.Is2D(&matrix)) {
transform = transform * matrix;
} else {
@ -478,17 +478,14 @@ nsComboboxControlFrame::GetCSSTransformTranslation()
nsPoint translation;
if (!is3DTransform && !transform.HasNonTranslation()) {
nsPresContext* pc = PresContext();
gfxPoint pixelTranslation = transform.GetTranslation();
int32_t apd = pc->AppUnitsPerDevPixel();
translation.x = NSFloatPixelsToAppUnits(float(pixelTranslation.x), apd);
translation.y = NSFloatPixelsToAppUnits(float(pixelTranslation.y), apd);
// To get the translation introduced only by transforms we subtract the
// regular non-transform translation.
nsRootPresContext* rootPC = pc->GetRootPresContext();
if (rootPC) {
int32_t apd = pc->AppUnitsPerDevPixel();
translation.x = NSFloatPixelsToAppUnits(transform._31, apd);
translation.y = NSFloatPixelsToAppUnits(transform._32, apd);
translation -= GetOffsetToCrossDoc(rootPC->PresShell()->GetRootFrame());
} else {
translation.x = translation.y = 0;
}
}
return translation;

View File

@ -96,6 +96,7 @@
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::layout;
@ -4731,7 +4732,7 @@ nsIFrame::IsLeaf() const
return true;
}
gfx3DMatrix
Matrix4x4
nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
nsIFrame** aOutAncestor)
{
@ -4749,12 +4750,12 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
"Cannot transform the viewport frame!");
int32_t scaleFactor = PresContext()->AppUnitsPerDevPixel();
gfx3DMatrix result =
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0), scaleFactor, nullptr, aOutAncestor);
Matrix4x4 result = ToMatrix4x4(
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0), scaleFactor, nullptr, aOutAncestor));
// XXXjwatt: seems like this will double count offsets in the face of preserve-3d:
nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
/* Combine the raw transform with a translation to our parent. */
result *= gfx3DMatrix::Translation
result = result * Matrix4x4().Translate
(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
NSAppUnitsToFloatPixels(delta.y, scaleFactor),
0.0f);
@ -4784,18 +4785,18 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
toplevel->GetClientBounds(toplevelScreenBounds);
nsIntPoint translation = screenBounds.TopLeft() - toplevelScreenBounds.TopLeft();
gfx3DMatrix transformToTop;
Matrix4x4 transformToTop;
transformToTop._41 = translation.x;
transformToTop._42 = translation.y;
*aOutAncestor = docRootFrame;
gfx3DMatrix docRootTransformToTop =
Matrix4x4 docRootTransformToTop =
nsLayoutUtils::GetTransformToAncestor(docRootFrame, nullptr);
if (docRootTransformToTop.IsSingular()) {
NS_WARNING("Containing document is invisible, we can't compute a valid transform");
} else {
gfx3DMatrix topToDocRootTransform = docRootTransformToTop.Inverse();
return transformToTop*topToDocRootTransform;
docRootTransformToTop.Invert();
return transformToTop * docRootTransformToTop;
}
}
}
@ -4812,8 +4813,8 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
* the identity matrix.
*/
if (!*aOutAncestor)
return gfx3DMatrix();
return Matrix4x4();
/* Keep iterating while the frame can't possibly be transformed. */
while (!(*aOutAncestor)->IsTransformed() &&
!nsLayoutUtils::IsPopup(*aOutAncestor) &&
@ -4833,7 +4834,7 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
*/
nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
int32_t scaleFactor = PresContext()->AppUnitsPerDevPixel();
return gfx3DMatrix().Translation
return Matrix4x4().Translate
(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
NSAppUnitsToFloatPixels(delta.y, scaleFactor),
0.0f);
@ -4978,14 +4979,14 @@ nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult)
return false;
}
gfx3DMatrix transform3d;
gfx::Matrix4x4 transform3d;
if (!nsLayoutUtils::GetLayerTransformForFrame(this, &transform3d)) {
// We're not able to compute a layer transform that we know would
// be used at the next layers transaction, so we can't only update
// the transform and will need to schedule an invalidating paint.
return false;
}
gfxMatrix transform;
gfx::Matrix transform;
gfx::Matrix previousTransform;
// FIXME/bug 796690 and 796705: in general, changes to 3D
// transforms, or transform changes to properties other than
@ -5003,7 +5004,7 @@ nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult)
!gfx::FuzzyEqual(transform._12, previousTransform._12, kError)) {
return false;
}
layer->SetBaseTransformForNextTransaction(gfx::ToMatrix4x4(transform3d));
layer->SetBaseTransformForNextTransaction(transform3d);
*aLayerResult = layer;
return true;
}

View File

@ -33,7 +33,6 @@
#include "WritingModes.h"
#include <algorithm>
#include "nsITheme.h"
#include "gfx3DMatrix.h"
#include "nsLayoutUtils.h"
#include "nsFrameState.h"
#include "CaretAssociationHint.h"
@ -61,7 +60,6 @@
struct nsHTMLReflowState;
class nsHTMLReflowCommand;
class gfxMatrix;
class nsIAtom;
class nsPresContext;
class nsIPresShell;
@ -409,6 +407,7 @@ public:
typedef mozilla::layout::FrameChildListIterator ChildListIterator;
typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
typedef mozilla::gfx::Matrix Matrix;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
typedef mozilla::Sides Sides;
typedef mozilla::LogicalSides LogicalSides;
@ -1977,11 +1976,11 @@ public:
* document as this frame. If this frame IsTransformed(), then *aOutAncestor
* will be the parent frame (if not preserve-3d) or the nearest non-transformed
* ancestor (if preserve-3d).
* @return A gfxMatrix that converts points in this frame's coordinate space
* @return A Matrix4x4 that converts points in this frame's coordinate space
* into points in aOutAncestor's coordinate space.
*/
gfx3DMatrix GetTransformMatrix(const nsIFrame* aStopAtAncestor,
nsIFrame **aOutAncestor);
Matrix4x4 GetTransformMatrix(const nsIFrame* aStopAtAncestor,
nsIFrame **aOutAncestor);
/**
* Bit-flags to pass to IsFrameOfType()

View File

@ -5349,8 +5349,8 @@ SVGTextFrame::GetFontSizeScaleFactor() const
* it to the appropriate frame user space of aChildFrame according to
* which rendered run the point hits.
*/
gfxPoint
SVGTextFrame::TransformFramePointToTextChild(const gfxPoint& aPoint,
Point
SVGTextFrame::TransformFramePointToTextChild(const Point& aPoint,
nsIFrame* aChildFrame)
{
NS_ASSERTION(aChildFrame &&
@ -5368,9 +5368,9 @@ SVGTextFrame::TransformFramePointToTextChild(const gfxPoint& aPoint,
float cssPxPerDevPx = presContext->
AppUnitsToFloatCSSPixels(presContext->AppUnitsPerDevPixel());
float factor = presContext->AppUnitsPerCSSPixel();
gfxPoint framePosition(NSAppUnitsToFloatPixels(mRect.x, factor),
NSAppUnitsToFloatPixels(mRect.y, factor));
gfxPoint pointInUserSpace = aPoint * cssPxPerDevPx + framePosition;
Point framePosition(NSAppUnitsToFloatPixels(mRect.x, factor),
NSAppUnitsToFloatPixels(mRect.y, factor));
Point pointInUserSpace = aPoint * cssPxPerDevPx + framePosition;
// Find the closest rendered run for the text frames beneath aChildFrame.
TextRenderedRunIterator it(this, TextRenderedRunIterator::eAllFrames,
@ -5389,7 +5389,7 @@ SVGTextFrame::TransformFramePointToTextChild(const gfxPoint& aPoint,
if (!m.Invert()) {
return aPoint;
}
gfxPoint pointInRunUserSpace = m.Transform(pointInUserSpace);
gfxPoint pointInRunUserSpace = m.Transform(ThebesPoint(pointInUserSpace));
if (Inside(runRect, pointInRunUserSpace)) {
// The point was inside the rendered run's rect, so we choose it.
@ -5418,7 +5418,7 @@ SVGTextFrame::TransformFramePointToTextChild(const gfxPoint& aPoint,
// but taking into account mFontSizeScaleFactor.
gfxMatrix m = hit.GetTransformFromRunUserSpaceToFrameUserSpace(presContext);
m.Scale(mFontSizeScaleFactor, mFontSizeScaleFactor);
return m.Transform(pointInRun) / cssPxPerDevPx;
return ToPoint(m.Transform(pointInRun) / cssPxPerDevPx);
}
/**

View File

@ -253,6 +253,7 @@ class SVGTextFrame MOZ_FINAL : public SVGTextFrameBase
friend class nsDisplaySVGText;
typedef mozilla::gfx::Path Path;
typedef mozilla::gfx::Point Point;
typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
protected:
@ -403,8 +404,8 @@ public:
* converts it to the appropriate frame user space of aChildFrame,
* according to which rendered run the point hits.
*/
gfxPoint TransformFramePointToTextChild(const gfxPoint& aPoint,
nsIFrame* aChildFrame);
Point TransformFramePointToTextChild(const Point& aPoint,
nsIFrame* aChildFrame);
/**
* Takes a rectangle, aRect, in the <text> element's user space, and