mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 05:10:49 +00:00
Bug 1217012 - Use doubles when untransforming points since we need the extra precision. r=kip
This commit is contained in:
parent
909c614d94
commit
545885b406
@ -185,8 +185,10 @@ Matrix4x4::TransformBounds(const RectTyped<UnknownUnits, F>& aRect) const
|
||||
return RectTyped<UnknownUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
}
|
||||
|
||||
Point4D ComputePerspectivePlaneIntercept(const Point4D& aFirst,
|
||||
const Point4D& aSecond)
|
||||
template<class F>
|
||||
Point4DTyped<UnknownUnits, F>
|
||||
ComputePerspectivePlaneIntercept(const Point4DTyped<UnknownUnits, F>& aFirst,
|
||||
const Point4DTyped<UnknownUnits, F>& aSecond)
|
||||
{
|
||||
// This function will always return a point with a w value of 0.
|
||||
// The X, Y, and Z components will point towards an infinite vanishing
|
||||
@ -203,7 +205,9 @@ Point4D ComputePerspectivePlaneIntercept(const Point4D& aFirst,
|
||||
return aFirst + (aSecond - aFirst) * t;
|
||||
}
|
||||
|
||||
Rect Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect &aClip) const
|
||||
template <class F>
|
||||
RectTyped<UnknownUnits, F>
|
||||
Matrix4x4::ProjectRectBounds(const RectTyped<UnknownUnits, F>& aRect, const RectTyped<UnknownUnits, F>& aClip) const
|
||||
{
|
||||
// This function must never return std::numeric_limits<Float>::max() or any
|
||||
// other arbitrary large value in place of inifinity. This often occurs when
|
||||
@ -229,26 +233,26 @@ Rect Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect &aClip) const
|
||||
|
||||
// Callers should pass an aClip value that represents the extents to clip
|
||||
// the result to, in the same coordinate system as aRect.
|
||||
Point4D points[4];
|
||||
Point4DTyped<UnknownUnits, F> points[4];
|
||||
|
||||
points[0] = ProjectPoint(aRect.TopLeft());
|
||||
points[1] = ProjectPoint(aRect.TopRight());
|
||||
points[2] = ProjectPoint(aRect.BottomRight());
|
||||
points[3] = ProjectPoint(aRect.BottomLeft());
|
||||
|
||||
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();
|
||||
F min_x = std::numeric_limits<F>::max();
|
||||
F min_y = std::numeric_limits<F>::max();
|
||||
F max_x = -std::numeric_limits<F>::max();
|
||||
F max_y = -std::numeric_limits<F>::max();
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
// Only use points that exist above the w=0 plane
|
||||
if (points[i].HasPositiveWCoord()) {
|
||||
Point point2d = aClip.ClampPoint(points[i].As2DPoint());
|
||||
min_x = std::min<Float>(point2d.x, min_x);
|
||||
max_x = std::max<Float>(point2d.x, max_x);
|
||||
min_y = std::min<Float>(point2d.y, min_y);
|
||||
max_y = std::max<Float>(point2d.y, max_y);
|
||||
PointTyped<UnknownUnits, F> point2d = aClip.ClampPoint(points[i].As2DPoint());
|
||||
min_x = std::min<F>(point2d.x, min_x);
|
||||
max_x = std::max<F>(point2d.x, max_x);
|
||||
min_y = std::min<F>(point2d.y, min_y);
|
||||
max_y = std::max<F>(point2d.y, max_y);
|
||||
}
|
||||
|
||||
int next = (i == 3) ? 0 : i + 1;
|
||||
@ -256,7 +260,8 @@ Rect Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect &aClip) const
|
||||
// If the line between two points crosses the w=0 plane, then interpolate
|
||||
// to find the point of intersection with the w=0 plane and use that
|
||||
// instead.
|
||||
Point4D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
|
||||
Point4DTyped<UnknownUnits, F> intercept =
|
||||
ComputePerspectivePlaneIntercept(points[i], points[next]);
|
||||
// Since intercept.w will always be 0 here, we interpret x,y,z as a
|
||||
// direction towards an infinite vanishing point.
|
||||
if (intercept.x < 0.0f) {
|
||||
@ -273,10 +278,10 @@ Rect Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect &aClip) const
|
||||
}
|
||||
|
||||
if (max_x < min_x || max_y < min_y) {
|
||||
return Rect(0, 0, 0, 0);
|
||||
return RectTyped<UnknownUnits, F>(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
return RectTyped<UnknownUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
@ -637,5 +642,14 @@ template
|
||||
RectDouble
|
||||
Matrix4x4::TransformBounds(const RectDouble& aRect) const;
|
||||
|
||||
template
|
||||
Rect
|
||||
Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect& aClip) const;
|
||||
|
||||
template
|
||||
RectDouble
|
||||
Matrix4x4::ProjectRectBounds(const RectDouble& aRect, const RectDouble& aClip) const;
|
||||
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
@ -507,20 +507,24 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Point4D ProjectPoint(const Point& aPoint) const {
|
||||
template<class F>
|
||||
Point4DTyped<UnknownUnits, F>
|
||||
ProjectPoint(const PointTyped<UnknownUnits, F>& 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;
|
||||
F z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
|
||||
|
||||
// Compute the transformed point
|
||||
return *this * Point4D(aPoint.x, aPoint.y, z, 1);
|
||||
return *this * Point4DTyped<UnknownUnits, F>(aPoint.x, aPoint.y, z, 1);
|
||||
}
|
||||
|
||||
Rect ProjectRectBounds(const Rect& aRect, const Rect &aClip) const;
|
||||
template<class F>
|
||||
RectTyped<UnknownUnits, F>
|
||||
ProjectRectBounds(const RectTyped<UnknownUnits, F>& aRect, const RectTyped<UnknownUnits, F>& aClip) const;
|
||||
|
||||
/**
|
||||
* TransformAndClipBounds transforms aRect as a bounding box, while clipping
|
||||
|
@ -174,7 +174,8 @@ template <typename TargetUnits, typename SourceUnits>
|
||||
static Maybe<gfx::IntPointTyped<TargetUnits>> UntransformTo(const gfx::Matrix4x4& aTransform,
|
||||
const gfx::IntPointTyped<SourceUnits>& aPoint)
|
||||
{
|
||||
gfx::Point4D point = aTransform.ProjectPoint(aPoint.ToUnknownPoint());
|
||||
gfx::Point p = aPoint.ToUnknownPoint();
|
||||
gfx::Point4D point = aTransform.ProjectPoint(p);
|
||||
if (!point.HasPositiveWCoord()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
@ -5951,15 +5951,15 @@ bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
|
||||
return false;
|
||||
}
|
||||
|
||||
Rect result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
|
||||
RectDouble result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
|
||||
|
||||
Rect childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.height, factor));
|
||||
RectDouble childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(aChildBounds.height, factor));
|
||||
|
||||
result = transform.Inverse().ProjectRectBounds(result, childGfxBounds);
|
||||
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
|
||||
@ -5975,17 +5975,17 @@ bool nsDisplayTransform::UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
// GetTransform always operates in dev pixels.
|
||||
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
Rect result(NSAppUnitsToFloatPixels(mVisibleRect.x, factor),
|
||||
NSAppUnitsToFloatPixels(mVisibleRect.y, factor),
|
||||
NSAppUnitsToFloatPixels(mVisibleRect.width, factor),
|
||||
NSAppUnitsToFloatPixels(mVisibleRect.height, factor));
|
||||
RectDouble 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);
|
||||
Rect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(childBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(childBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(childBounds.height, factor));
|
||||
RectDouble 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, childGfxBounds);
|
||||
|
Loading…
x
Reference in New Issue
Block a user