зеркало из https://github.com/mozilla/pjs.git
Bug 505115 - Part 8c - Use ray tracing to untransform 2d points on a 3d plane. r=roc
This commit is contained in:
Родитель
a1dcca3e9c
Коммит
85e14ced8b
|
@ -921,16 +921,12 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem)
|
|||
static void
|
||||
RestrictVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible)
|
||||
{
|
||||
gfxMatrix transform;
|
||||
if (!aLayer->GetTransform().Is2D(&transform))
|
||||
return;
|
||||
gfx3DMatrix transform = aLayer->GetTransform();
|
||||
|
||||
// if 'transform' is not invertible, then nothing will be displayed
|
||||
// for the layer, so it doesn't really matter what we do here
|
||||
gfxMatrix inverse = transform;
|
||||
inverse.Invert();
|
||||
gfxRect itemVisible(aItemVisible.x, aItemVisible.y, aItemVisible.width, aItemVisible.height);
|
||||
gfxRect layerVisible = inverse.TransformBounds(itemVisible);
|
||||
gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible);
|
||||
layerVisible.RoundOut();
|
||||
|
||||
nsIntRect visibleRect;
|
||||
|
|
|
@ -451,19 +451,16 @@ static nsRect GetDisplayPortBounds(nsDisplayListBuilder* aBuilder,
|
|||
PRBool aIgnoreTransform)
|
||||
{
|
||||
nsIFrame* frame = aItem->GetUnderlyingFrame();
|
||||
nscoord auPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
gfx3DMatrix transform;
|
||||
const nsRect* displayport = aBuilder->GetDisplayPort();
|
||||
|
||||
if (!aIgnoreTransform) {
|
||||
transform = nsLayoutUtils::GetTransformToAncestor(frame,
|
||||
aBuilder->ReferenceFrame());
|
||||
transform.Invert();
|
||||
if (aIgnoreTransform) {
|
||||
return *displayport;
|
||||
}
|
||||
|
||||
const nsRect* displayport = aBuilder->GetDisplayPort();
|
||||
return nsLayoutUtils::MatrixTransformRect(
|
||||
return nsLayoutUtils::TransformRectToBoundsInAncestor(
|
||||
frame,
|
||||
nsRect(0, 0, displayport->width, displayport->height),
|
||||
transform, auPerDevPixel);
|
||||
aBuilder->ReferenceFrame());
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -2482,13 +2479,13 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
|
|||
* Thus we have to invert the matrix, which normally does
|
||||
* the reverse operation (e.g. regular->transformed)
|
||||
*/
|
||||
matrix.Invert();
|
||||
|
||||
/* Now, apply the transform and pass it down the channel. */
|
||||
nsRect resultingRect;
|
||||
if (aRect.width == 1 && aRect.height == 1) {
|
||||
gfxPoint point = matrix.Transform(gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.y, factor)));
|
||||
gfxPoint point = matrix.Inverse().ProjectPoint(
|
||||
gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.y, factor)));
|
||||
|
||||
resultingRect = nsRect(NSFloatPixelsToAppUnits(float(point.x), factor),
|
||||
NSFloatPixelsToAppUnits(float(point.y), factor),
|
||||
|
@ -2500,7 +2497,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
|
|||
NSAppUnitsToFloatPixels(aRect.width, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.height, factor));
|
||||
|
||||
gfxRect rect = matrix.TransformBounds(originalRect);
|
||||
gfxRect rect = matrix.Inverse().ProjectRectBounds(originalRect);;
|
||||
|
||||
resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
|
||||
NSFloatPixelsToAppUnits(float(rect.Y()), factor),
|
||||
|
@ -2693,14 +2690,21 @@ PRBool nsDisplayTransform::UntransformRect(const nsRect &aUntransformedBounds,
|
|||
*/
|
||||
float factor = nsPresContext::AppUnitsPerCSSPixel();
|
||||
gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor, nsnull);
|
||||
if (matrix.IsSingular() || !matrix.Is2D())
|
||||
if (matrix.IsSingular())
|
||||
return PR_FALSE;
|
||||
|
||||
/* We want to untransform the matrix, so invert the transformation first! */
|
||||
matrix.Invert();
|
||||
gfxRect result(NSAppUnitsToFloatPixels(aUntransformedBounds.x, factor),
|
||||
NSAppUnitsToFloatPixels(aUntransformedBounds.y, factor),
|
||||
NSAppUnitsToFloatPixels(aUntransformedBounds.width, factor),
|
||||
NSAppUnitsToFloatPixels(aUntransformedBounds.height, factor));
|
||||
|
||||
*aOutRect = nsLayoutUtils::MatrixTransformRect(aUntransformedBounds, matrix,
|
||||
factor);
|
||||
/* We want to untransform the matrix, so invert the transformation first! */
|
||||
result = matrix.Inverse().ProjectRectBounds(result);
|
||||
|
||||
*aOutRect = nsRect(NSFloatPixelsToAppUnits(float(result.x), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.y), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.width), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.height), factor));
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxPoint3D.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -1111,43 +1112,81 @@ nsLayoutUtils::MatrixTransformPoint(const nsPoint &aPoint,
|
|||
NSFloatPixelsToAppUnits(float(image.y), aFactor));
|
||||
}
|
||||
|
||||
gfx3DMatrix nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame,
|
||||
nsIFrame* aStopAtAncestor)
|
||||
{
|
||||
gfx3DMatrix ctm;
|
||||
|
||||
/* Starting at the specified frame, we'll use the GetTransformMatrix
|
||||
* function of the frame, which gives us a matrix from this frame up
|
||||
* to some other ancestor frame. If aStopAtAncestor frame is not reached,
|
||||
* we stop at root. We get the CTM by simply accumulating all of these
|
||||
* matrices together.
|
||||
*/
|
||||
while (aFrame && aFrame != aStopAtAncestor) {
|
||||
ctm *= aFrame->GetTransformMatrix(&aFrame);
|
||||
}
|
||||
NS_ASSERTION(aFrame == aStopAtAncestor, "How did we manage to miss the ancestor?");
|
||||
return ctm;
|
||||
}
|
||||
|
||||
nsPoint
|
||||
nsLayoutUtils::InvertTransformsToRoot(nsIFrame *aFrame,
|
||||
const nsPoint &aPoint)
|
||||
static gfxPoint
|
||||
InvertTransformsToAncestor(nsIFrame *aFrame,
|
||||
const gfxPoint &aPoint,
|
||||
nsIFrame *aStopAtAncestor = nsnull)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "Why are you inverting transforms when there is no frame?");
|
||||
|
||||
/* To invert everything to the root, we'll get the CTM, invert it, and use it to transform
|
||||
* the point.
|
||||
*/
|
||||
gfx3DMatrix ctm = GetTransformToAncestor(aFrame);
|
||||
nsIFrame *parent = nsnull;
|
||||
gfx3DMatrix ctm = aFrame->GetTransformMatrix(&parent);
|
||||
gfxPoint result = aPoint;
|
||||
|
||||
/* If the ctm is singular, hand back (0, 0) as a sentinel. */
|
||||
if (ctm.IsSingular())
|
||||
return nsPoint(0, 0);
|
||||
if (parent && parent != aStopAtAncestor) {
|
||||
result = InvertTransformsToAncestor(parent, aPoint, aStopAtAncestor);
|
||||
}
|
||||
|
||||
/* TODO: Correctly handle 3d transforms when they start being used */
|
||||
result = ctm.Inverse().ProjectPoint(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Otherwise, invert the CTM and use it to transform the point. */
|
||||
return MatrixTransformPoint(aPoint, ctm.Invert(), aFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
static gfxRect
|
||||
InvertGfxRectToAncestor(nsIFrame *aFrame,
|
||||
const gfxRect &aRect,
|
||||
nsIFrame *aStopAtAncestor = nsnull)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "Why are you inverting transforms when there is no frame?");
|
||||
|
||||
/* To invert everything to the root, we'll get the CTM, invert it, and use it to transform
|
||||
* the point.
|
||||
*/
|
||||
nsIFrame *parent = nsnull;
|
||||
gfx3DMatrix ctm = aFrame->GetTransformMatrix(&parent);
|
||||
gfxRect result = aRect;
|
||||
|
||||
if (parent && parent != aStopAtAncestor) {
|
||||
result = InvertGfxRectToAncestor(parent, aRect, aStopAtAncestor);
|
||||
}
|
||||
|
||||
result = ctm.Inverse().ProjectRectBounds(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsPoint
|
||||
nsLayoutUtils::InvertTransformsToRoot(nsIFrame *aFrame,
|
||||
const nsPoint &aPoint)
|
||||
{
|
||||
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
gfxPoint result(NSAppUnitsToFloatPixels(aPoint.x, factor),
|
||||
NSAppUnitsToFloatPixels(aPoint.y, factor));
|
||||
|
||||
result = InvertTransformsToAncestor(aFrame, result);
|
||||
|
||||
return nsPoint(NSFloatPixelsToAppUnits(float(result.x), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.y), factor));
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsLayoutUtils::TransformRectToBoundsInAncestor(nsIFrame* aFrame,
|
||||
const nsRect &aRect,
|
||||
nsIFrame* aStopAtAncestor)
|
||||
{
|
||||
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
gfxRect result(NSAppUnitsToFloatPixels(aRect.x, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.y, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.width, factor),
|
||||
NSAppUnitsToFloatPixels(aRect.height, factor));
|
||||
|
||||
result = InvertGfxRectToAncestor(aFrame, result, aStopAtAncestor);
|
||||
|
||||
return nsRect(NSFloatPixelsToAppUnits(float(result.x), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.y), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.width), factor),
|
||||
NSFloatPixelsToAppUnits(float(result.height), factor));
|
||||
}
|
||||
|
||||
static nsIntPoint GetWidgetOffset(nsIWidget* aWidget, nsIWidget*& aRootWidget) {
|
||||
|
|
|
@ -510,17 +510,11 @@ public:
|
|||
PRBool aShouldIgnoreSuppression = PR_FALSE,
|
||||
PRBool aIgnoreRootScrollFrame = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Returns the CTM at the specified frame. This matrix can be used to map
|
||||
* coordinates from aFrame's to aStopAtAncestor's coordinate system.
|
||||
*
|
||||
* @param aFrame The frame at which we should calculate the CTM.
|
||||
* @param aStopAtAncestor is an ancestor frame to stop at. If it's nsnull,
|
||||
* matrix accumulating stops at root.
|
||||
* @return The CTM at the specified frame.
|
||||
*/
|
||||
static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame,
|
||||
nsIFrame* aStopAtAncestor = nsnull);
|
||||
|
||||
|
||||
static nsRect TransformRectToBoundsInAncestor(nsIFrame* aFrame,
|
||||
const nsRect& aRect,
|
||||
nsIFrame* aStopAtAncestor);
|
||||
|
||||
/**
|
||||
* Given a point in the global coordinate space, returns that point expressed
|
||||
|
@ -534,7 +528,6 @@ public:
|
|||
static nsPoint InvertTransformsToRoot(nsIFrame* aFrame,
|
||||
const nsPoint &aPt);
|
||||
|
||||
|
||||
/**
|
||||
* Helper function that, given a rectangle and a matrix, returns the smallest
|
||||
* rectangle containing the image of the source rectangle.
|
||||
|
|
|
@ -4544,7 +4544,7 @@ nsIFrame::GetTransformMatrix(nsIFrame **aOutAncestor)
|
|||
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0),
|
||||
scaleFactor);
|
||||
/* Combine the raw transform with a translation to our parent. */
|
||||
result = result * gfx3DMatrix::Translation
|
||||
result *= gfx3DMatrix::Translation
|
||||
(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
|
||||
NSAppUnitsToFloatPixels(delta.y, scaleFactor),
|
||||
0.0f);
|
||||
|
|
Загрузка…
Ссылка в новой задаче