Bug 655877 - Part 40: Factor out 'distance from point to rect' calculation from text frame selection routine. r=roc

This commit is contained in:
Cameron McCormack 2012-08-08 21:37:14 +10:00
parent de15c57651
commit e9aaa26845
2 changed files with 63 additions and 33 deletions

View File

@ -40,6 +40,8 @@ class nsHTMLImageElement;
#include "nsIFrameLoader.h"
#include "FrameMetrics.h"
#include <limits>
class nsBlockFrame;
class gfxDrawable;
@ -1676,6 +1678,22 @@ public:
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint);
/**
* Updates a pair of x and y distances if a given point is closer to a given
* rectangle than the original distance values. If aPoint is closer to
* aRect than aClosestXDistance and aClosestYDistance indicate, then those
* two variables are updated with the distance between aPoint and aRect,
* and true is returned. If aPoint is not closer, then aClosestXDistance
* and aClosestYDistance are left unchanged, and false is returned.
*
* Distances are measured in the two dimensions separately; a closer x
* distance beats a closer y distance.
*/
template<typename PointType, typename RectType, typename CoordType>
static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect,
CoordType& aClosestXDistance,
CoordType& aClosestYDistance);
#ifdef DEBUG
/**
* Assert that there are no duplicate continuations of the same frame
@ -1700,6 +1718,47 @@ private:
static PRUint32 sFontSizeInflationLineThreshold;
};
template<typename PointType, typename RectType, typename CoordType>
/* static */ bool
nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect,
CoordType& aClosestXDistance,
CoordType& aClosestYDistance)
{
CoordType fromLeft = aPoint.x - aRect.x;
CoordType fromRight = aPoint.x - aRect.XMost();
CoordType xDistance;
if (fromLeft >= 0 && fromRight <= 0) {
xDistance = 0;
} else {
xDistance = NS_MIN(abs(fromLeft), abs(fromRight));
}
if (xDistance <= aClosestXDistance) {
if (xDistance < aClosestXDistance) {
aClosestYDistance = std::numeric_limits<CoordType>::max();
}
CoordType fromTop = aPoint.y - aRect.y;
CoordType fromBottom = aPoint.y - aRect.YMost();
CoordType yDistance;
if (fromTop >= 0 && fromBottom <= 0) {
yDistance = 0;
} else {
yDistance = NS_MIN(abs(fromTop), abs(fromBottom));
}
if (yDistance < aClosestYDistance) {
aClosestXDistance = xDistance;
aClosestYDistance = yDistance;
return true;
}
}
return false;
}
namespace mozilla {
namespace layout {

View File

@ -3416,39 +3416,10 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint,
if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty())
continue;
nsRect rect = kid->GetRect();
nscoord fromLeft = aPoint.x - rect.x;
nscoord fromRight = aPoint.x - rect.XMost();
nscoord xDistance;
if (fromLeft >= 0 && fromRight <= 0) {
xDistance = 0;
} else {
xDistance = NS_MIN(abs(fromLeft), abs(fromRight));
}
if (xDistance <= closestXDistance)
{
if (xDistance < closestXDistance)
closestYDistance = HUGE_DISTANCE;
nscoord fromTop = aPoint.y - rect.y;
nscoord fromBottom = aPoint.y - rect.YMost();
nscoord yDistance;
if (fromTop >= 0 && fromBottom <= 0)
yDistance = 0;
else
yDistance = NS_MIN(abs(fromTop), abs(fromBottom));
if (yDistance < closestYDistance)
{
closestXDistance = xDistance;
closestYDistance = yDistance;
closestFrame = kid;
}
}
if (nsLayoutUtils::PointIsCloserToRect(aPoint, kid->GetRect(),
closestXDistance,
closestYDistance))
closestFrame = kid;
}
if (closestFrame)
return GetSelectionClosestFrameForChild(closestFrame, aPoint, aFlags);