Bug 641426. Part 7: Create Rect template. r=joe,sr=cjones

This commit is contained in:
Robert O'Callahan 2011-04-19 15:07:48 +12:00
Родитель fc7faceefc
Коммит 2c059fb8c2
10 изменённых файлов: 380 добавлений и 660 удалений

314
gfx/src/BaseRect.h Normal file
Просмотреть файл

@ -0,0 +1,314 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <robert@ocallahan.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MOZILLA_BASERECT_H_
#define MOZILLA_BASERECT_H_
#include "nsAlgorithm.h"
namespace mozilla {
/**
* Rectangles have two interpretations: a set of (zero-size) points,
* and a rectangular area of the plane. Most rectangle operations behave
* the same no matter what interpretation is being used, but some operations
* differ:
* -- Equality tests behave differently. When a rectangle represents an area,
* all zero-width and zero-height rectangles are equal to each other since they
* represent the empty area. But when a rectangle represents a set of
* mathematical points, zero-width and zero-height rectangles can be unequal.
* -- The union operation can behave differently. When rectangles represent
* areas, taking the union of a zero-width or zero-height rectangle with
* another rectangle can just ignore the empty rectangle. But when rectangles
* represent sets of mathematical points, we may need to extend the latter
* rectangle to include the points of a zero-width or zero-height rectangle.
*
* To ensure that these interpretations are explicitly disambiguated, we
* deny access to the == and != operators and require use of IsEqualEdges and
* IsEqualInterior instead. Similarly we provide separate Union and UnionEdges
* methods.
*
* Do not use this class directly. Subclass it, pass that subclass as the
* Sub parameter, and only use that subclass.
*/
template <class T, class Sub, class Point, class SizeT, class Margin>
struct BaseRect {
T x, y, width, height;
// Constructors
BaseRect() : x(0), y(0), width(0), height(0) {}
BaseRect(const Point& aOrigin, const SizeT &aSize) :
x(aOrigin.x), y(aOrigin.y), width(aSize.width), height(aSize.height)
{
}
BaseRect(T aX, T aY, T aWidth, T aHeight) :
x(aX), y(aY), width(aWidth), height(aHeight)
{
}
// Emptiness. An empty rect is one that has no area, i.e. its height or width
// is <= 0
bool IsEmpty() const { return height <= 0 || width <= 0; }
void SetEmpty() { width = height = 0; }
// Returns true if this rectangle contains the interior of aRect. Always
// returns true if aRect is empty, and always returns false is aRect is
// nonempty but this rect is empty.
bool Contains(const Sub& aRect) const
{
return aRect.IsEmpty() ||
(x <= aRect.x && aRect.XMost() <= XMost() &&
y <= aRect.y && aRect.YMost() <= YMost());
}
// Returns true if this rectangle contains the rectangle (aX,aY,1,1).
bool Contains(T aX, T aY) const
{
return x <= aX && aX + 1 <= XMost() &&
y <= aY && aY + 1 <= YMost();
}
// Returns true if this rectangle contains the rectangle (aPoint.x,aPoint.y,1,1).
bool Contains(const Point& aPoint) const { return Contains(aPoint.x, aPoint.y); }
// Intersection. Returns TRUE if the receiver's area has non-empty
// intersection with aRect's area, and FALSE otherwise.
// Always returns false if aRect is empty or 'this' is empty.
bool Intersects(const Sub& aRect) const
{
return x < aRect.XMost() && aRect.x < XMost() &&
y < aRect.YMost() && aRect.y < YMost();
}
// Returns the rectangle containing the intersection of the points
// (including edges) of *this and aRect. If there are no points in that
// intersection, returns an empty rectangle with x/y set to the max of the x/y
// of *this and aRect.
Sub Intersect(const Sub& aRect) const
{
Sub result;
result.x = NS_MAX(x, aRect.x);
result.y = NS_MAX(y, aRect.y);
result.width = NS_MIN(XMost(), aRect.XMost()) - result.x;
result.height = NS_MIN(YMost(), aRect.YMost()) - result.y;
if (result.width < 0 || result.height < 0) {
result.SizeTo(0, 0);
}
return result;
}
// Sets *this to be the rectangle containing the intersection of the points
// (including edges) of *this and aRect. If there are no points in that
// intersection, sets *this to be an empty rectangle with x/y set to the max
// of the x/y of *this and aRect.
//
// 'this' can be the same object as either aRect1 or aRect2
bool IntersectRect(const Sub& aRect1, const Sub& aRect2)
{
*static_cast<Sub*>(this) = aRect1.Intersect(aRect2);
return !IsEmpty();
}
// Returns the smallest rectangle that contains both the area of both
// this and aRect2.
// Thus, empty input rectangles are ignored.
// If both rectangles are empty, returns this.
Sub Union(const Sub& aRect) const
{
if (IsEmpty()) {
return aRect;
} else if (aRect.IsEmpty()) {
return *static_cast<const Sub*>(this);
} else {
return UnionEdges(aRect);
}
}
// Returns the smallest rectangle that contains both the points (including
// edges) of both aRect1 and aRect2.
// Thus, empty input rectangles are allowed to affect the result.
Sub UnionEdges(const Sub& aRect) const
{
Sub result;
result.x = NS_MIN(x, aRect.x);
result.y = NS_MIN(y, aRect.y);
result.width = NS_MAX(XMost(), aRect.XMost()) - result.x;
result.height = NS_MAX(YMost(), aRect.YMost()) - result.y;
return result;
}
// Computes the smallest rectangle that contains both the area of both
// aRect1 and aRect2, and fills 'this' with the result.
// Thus, empty input rectangles are ignored.
// If both rectangles are empty, sets 'this' to aRect2.
//
// 'this' can be the same object as either aRect1 or aRect2
void UnionRect(const Sub& aRect1, const Sub& aRect2)
{
*static_cast<Sub*>(this) = aRect1.Union(aRect2);
}
// Computes the smallest rectangle that contains both the points (including
// edges) of both aRect1 and aRect2.
// Thus, empty input rectangles are allowed to affect the result.
//
// 'this' can be the same object as either aRect1 or aRect2
void UnionRectEdges(const Sub& aRect1, const Sub& aRect2)
{
*static_cast<Sub*>(this) = aRect1.UnionEdges(aRect2);
}
void SetRect(T aX, T aY, T aWidth, T aHeight)
{
x = aX; y = aY; width = aWidth; height = aHeight;
}
void SetRect(const Point& aPt, const SizeT& aSize)
{
SetRect(aPt.x, aPt.y, aSize.width, aSize.height);
}
void MoveTo(T aX, T aY) { x = aX; y = aY; }
void MoveTo(const Point& aPoint) { x = aPoint.x; y = aPoint.y; }
void MoveBy(T aDx, T aDy) { x += aDx; y += aDy; }
void MoveBy(const Point& aPoint) { x += aPoint.x; y += aPoint.y; }
void SizeTo(T aWidth, T aHeight) { width = aWidth; height = aHeight; }
void SizeTo(const SizeT& aSize) { width = aSize.width; height = aSize.height; }
void Inflate(T aDx, T aDy)
{
x -= aDx;
y -= aDy;
width += 2 * aDx;
height += 2 * aDy;
}
void Inflate(const Margin& aMargin)
{
x -= aMargin.left;
y -= aMargin.top;
width += aMargin.LeftRight();
height += aMargin.TopBottom();
}
void Deflate(T aDx, T aDy)
{
x += aDx;
y += aDy;
width = NS_MAX(T(0), width - 2 * aDx);
height = NS_MAX(T(0), height - 2 * aDy);
}
void Deflate(const Margin& aMargin)
{
x += aMargin.left;
y += aMargin.top;
width = NS_MAX(T(0), width - aMargin.LeftRight());
height = NS_MAX(T(0), height - aMargin.TopBottom());
}
// Return true if the rectangles contain the same set of points, including
// points on the edges.
// Use when we care about the exact x/y/width/height values being
// equal (i.e. we care about differences in empty rectangles).
bool IsEqualEdges(const Sub& aRect) const
{
return x == aRect.x && y == aRect.y &&
width == aRect.width && height == aRect.height;
}
// Return true if the rectangles contain the same area of the plane.
// Use when we do not care about differences in empty rectangles.
bool IsEqualInterior(const Sub& aRect) const
{
return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
}
Sub operator+(const Point& aPoint) const
{
return Sub(x + aPoint.x, y + aPoint.y, width, height);
}
Sub operator-(const Point& aPoint) const
{
return Sub(x - aPoint.x, y - aPoint.y, width, height);
}
Sub& operator+=(const Point& aPoint)
{
MoveBy(aPoint);
return *static_cast<Sub*>(this);
}
Sub& operator-=(const Point& aPoint)
{
MoveBy(-aPoint);
return *static_cast<Sub*>(this);
}
// Find difference as a Margin
Margin operator-(const Sub& aRect) const
{
return Margin(aRect.x - x, aRect.y - y,
XMost() - aRect.XMost(), YMost() - aRect.YMost());
}
// Helpers for accessing the vertices
Point TopLeft() const { return Point(x, y); }
Point TopRight() const { return Point(XMost(), y); }
Point BottomLeft() const { return Point(x, YMost()); }
Point BottomRight() const { return Point(XMost(), YMost()); }
Point Center() const { return Point(x, y) + Point(width, height)/2; }
SizeT Size() const { return SizeT(width, height); }
// Helper methods for computing the extents
T X() const { return x; }
T Y() const { return y; }
T Width() const { return width; }
T Height() const { return height; }
T XMost() const { return x + width; }
T YMost() const { return y + height; }
// Scale 'this' by aScale, converting coordinates to integers so that the result is
// the smallest integer-coordinate rectangle containing the unrounded result.
void ScaleRoundOut(double aScale) { ScaleRoundOut(aScale, aScale); }
void ScaleRoundOut(double aXScale, double aYScale)
{
T right = static_cast<T>(NS_ceil(double(XMost()) * aXScale));
T bottom = static_cast<T>(NS_ceil(double(YMost()) * aYScale));
x = static_cast<T>(NS_floor(double(x) * aXScale));
y = static_cast<T>(NS_floor(double(y) * aYScale));
width = right - x;
height = bottom - y;
}
private:
// Do not use the default operator== or operator!= !
// Use IsEqualEdges or IsEqualInterior explicitly.
bool operator==(const Sub& aRect) const { return false; }
bool operator!=(const Sub& aRect) const { return false; }
};
}
#endif /* MOZILLA_BASERECT_H_ */

Просмотреть файл

@ -64,6 +64,7 @@ EXPORTS_NAMESPACES = mozilla
EXPORTS_mozilla = \
BaseMargin.h \
BasePoint.h \
BaseRect.h \
BaseSize.h \
$(NULL)

Просмотреть файл

@ -44,167 +44,9 @@
// the mozilla::css::Side sequence must match the nsMargin nscoord sequence
PR_STATIC_ASSERT((NS_SIDE_TOP == 0) && (NS_SIDE_RIGHT == 1) && (NS_SIDE_BOTTOM == 2) && (NS_SIDE_LEFT == 3));
/* static */
const nsIntRect nsIntRect::kMaxSizedIntRect(0, 0, INT_MAX, INT_MAX);
// Containment
PRBool nsRect::Contains(nscoord aX, nscoord aY) const
{
return (PRBool) ((aX >= x) && (aY >= y) &&
(aX < XMost()) && (aY < YMost()));
}
//Also Returns true if aRect is Empty
PRBool nsRect::Contains(const nsRect &aRect) const
{
return aRect.IsEmpty() ||
((PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost())));
}
// Intersection. Returns TRUE if the receiver overlaps aRect and
// FALSE otherwise
PRBool nsRect::Intersects(const nsRect &aRect) const
{
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
(aRect.x < XMost()) && (aRect.y < YMost()));
}
// Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect.
PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2)
{
nscoord xmost1 = aRect1.XMost();
nscoord ymost1 = aRect1.YMost();
nscoord xmost2 = aRect2.XMost();
nscoord ymost2 = aRect2.YMost();
nscoord temp;
x = PR_MAX(aRect1.x, aRect2.x);
y = PR_MAX(aRect1.y, aRect2.y);
// Compute the destination width
temp = PR_MIN(xmost1, xmost2);
if (temp <= x) {
width = 0;
} else {
width = temp - x;
}
// Compute the destination height
temp = PR_MIN(ymost1, ymost2);
if (temp <= y) {
height = 0;
} else {
height = temp - y;
}
return !IsEmpty();
}
// Computes the smallest rectangle that contains both aRect1 and aRect2 and
// fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
// empty and TRUE otherwise
PRBool nsRect::UnionRect(const nsRect &aRect1, const nsRect &aRect2)
{
PRBool result = PR_TRUE;
// Is aRect1 empty?
if (aRect1.IsEmpty()) {
if (aRect2.IsEmpty()) {
// Both rectangles are empty which is an error
Empty();
result = PR_FALSE;
} else {
// aRect1 is empty so set the result to aRect2
*this = aRect2;
}
} else if (aRect2.IsEmpty()) {
// aRect2 is empty so set the result to aRect1
*this = aRect1;
} else {
UnionRectEdges(aRect1, aRect2);
}
return result;
}
void nsRect::UnionRectEdges(const nsRect &aRect1, const nsRect &aRect2)
{
nscoord xmost1 = aRect1.XMost();
nscoord xmost2 = aRect2.XMost();
nscoord ymost1 = aRect1.YMost();
nscoord ymost2 = aRect2.YMost();
// Compute the origin
x = PR_MIN(aRect1.x, aRect2.x);
y = PR_MIN(aRect1.y, aRect2.y);
// Compute the size
width = PR_MAX(xmost1, xmost2) - x;
height = PR_MAX(ymost1, ymost2) - y;
}
// Inflate the rect by the specified width and height
void nsRect::Inflate(nscoord aDx, nscoord aDy)
{
x -= aDx;
y -= aDy;
width += 2 * aDx;
height += 2 * aDy;
}
// Inflate the rect by the specified margin
void nsRect::Inflate(const nsMargin &aMargin)
{
x -= aMargin.left;
y -= aMargin.top;
width += aMargin.left + aMargin.right;
height += aMargin.top + aMargin.bottom;
}
// Deflate the rect by the specified width and height
void nsRect::Deflate(nscoord aDx, nscoord aDy)
{
x += aDx;
y += aDy;
width = PR_MAX(0, width - 2 * aDx);
height = PR_MAX(0, height - 2 * aDy);
}
// Deflate the rect by the specified margin
void nsRect::Deflate(const nsMargin &aMargin)
{
x += aMargin.left;
y += aMargin.top;
width = PR_MAX(0, width - aMargin.LeftRight());
height = PR_MAX(0, height - aMargin.TopBottom());
}
// Find difference between rects as an nsMargin
nsMargin nsRect::operator-(const nsRect& aRect) const
{
nsMargin margin;
margin.left = aRect.x - x;
margin.right = XMost() - aRect.XMost();
margin.top = aRect.y - y;
margin.bottom = YMost() - aRect.YMost();
return margin;
}
// scale the rect but round to smallest containing rect
nsRect& nsRect::ScaleRoundOut(float aXScale, float aYScale)
{
nscoord right = NSToCoordCeil(float(XMost()) * aXScale);
nscoord bottom = NSToCoordCeil(float(YMost()) * aYScale);
x = NSToCoordFloor(float(x) * aXScale);
y = NSToCoordFloor(float(y) * aYScale);
width = (right - x);
height = (bottom - y);
return *this;
}
#ifdef DEBUG
static bool IsFloatInteger(float aFloat)
{
@ -259,85 +101,3 @@ FILE* operator<<(FILE* out, const nsRect& rect)
}
#endif // DEBUG
// Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect.
PRBool nsIntRect::IntersectRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
{
PRInt32 xmost1 = aRect1.XMost();
PRInt32 ymost1 = aRect1.YMost();
PRInt32 xmost2 = aRect2.XMost();
PRInt32 ymost2 = aRect2.YMost();
PRInt32 temp;
x = PR_MAX(aRect1.x, aRect2.x);
y = PR_MAX(aRect1.y, aRect2.y);
// Compute the destination width
temp = PR_MIN(xmost1, xmost2);
if (temp <= x) {
Empty();
return PR_FALSE;
}
width = temp - x;
// Compute the destination height
temp = PR_MIN(ymost1, ymost2);
if (temp <= y) {
Empty();
return PR_FALSE;
}
height = temp - y;
return PR_TRUE;
}
// Computes the smallest rectangle that contains both aRect1 and aRect2 and
// fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
// empty and TRUE otherwise
PRBool nsIntRect::UnionRect(const nsIntRect &aRect1, const nsIntRect &aRect2)
{
PRBool result = PR_TRUE;
// Is aRect1 empty?
if (aRect1.IsEmpty()) {
if (aRect2.IsEmpty()) {
// Both rectangles are empty which is an error
Empty();
result = PR_FALSE;
} else {
// aRect1 is empty so set the result to aRect2
*this = aRect2;
}
} else if (aRect2.IsEmpty()) {
// aRect2 is empty so set the result to aRect1
*this = aRect1;
} else {
PRInt32 xmost1 = aRect1.XMost();
PRInt32 xmost2 = aRect2.XMost();
PRInt32 ymost1 = aRect1.YMost();
PRInt32 ymost2 = aRect2.YMost();
// Compute the origin
x = PR_MIN(aRect1.x, aRect2.x);
y = PR_MIN(aRect1.y, aRect2.y);
// Compute the size
width = PR_MAX(xmost1, xmost2) - x;
height = PR_MAX(ymost1, ymost2) - y;
}
return result;
}
// scale the rect but round to smallest containing rect
nsIntRect& nsIntRect::ScaleRoundOut(float aXScale, float aYScale)
{
nscoord right = NSToCoordCeil(float(XMost()) * aXScale);
nscoord bottom = NSToCoordCeil(float(YMost()) * aYScale);
x = NSToCoordFloor(float(x) * aXScale);
y = NSToCoordFloor(float(y) * aYScale);
width = (right - x);
height = (bottom - y);
return *this;
}

Просмотреть файл

@ -46,30 +46,33 @@
#include "nsMargin.h"
#include "gfxCore.h"
#include "nsTraceRefcnt.h"
#include "mozilla/BaseRect.h"
struct nsIntRect;
struct NS_GFX nsRect {
nscoord x, y;
nscoord width, height;
struct NS_GFX nsRect :
public mozilla::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> {
typedef mozilla::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> Super;
static void VERIFY_COORD(nscoord aValue) { ::VERIFY_COORD(aValue); }
// Constructors
nsRect() : x(0), y(0), width(0), height(0) {
nsRect() : Super()
{
MOZ_COUNT_CTOR(nsRect);
}
nsRect(const nsRect& aRect) {
nsRect(const nsRect& aRect) : Super(aRect)
{
MOZ_COUNT_CTOR(nsRect);
*this = aRect;
}
nsRect(const nsPoint& aOrigin, const nsSize &aSize) {
nsRect(const nsPoint& aOrigin, const nsSize &aSize) : Super(aOrigin, aSize)
{
MOZ_COUNT_CTOR(nsRect);
x = aOrigin.x; y = aOrigin.y;
width = aSize.width; height = aSize.height;
}
nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {
nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) :
Super(aX, aY, aWidth, aHeight)
{
MOZ_COUNT_CTOR(nsRect);
x = aX; y = aY; width = aWidth; height = aHeight;
VERIFY_COORD(x); VERIFY_COORD(y); VERIFY_COORD(width); VERIFY_COORD(height);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -77,114 +80,8 @@ struct NS_GFX nsRect {
MOZ_COUNT_DTOR(nsRect);
}
#endif
// Emptiness. An empty rect is one that has no area, i.e. its height or width
// is <= 0
PRBool IsEmpty() const {
return (PRBool) ((height <= 0) || (width <= 0));
}
void SetEmpty() {width = height = 0;}
// Returns true if this rectangle contains the interior of aRect. Always
// returns true if aRect is empty, and always returns false is aRect is
// nonempty but this rect is empty.
PRBool Contains(const nsRect& aRect) const;
// Returns true if this rectangle contains the given point; if the point
// is on the edge of the rectangle, this returns true.
PRBool Contains(nscoord aX, nscoord aY) const;
PRBool Contains(const nsPoint& aPoint) const {return Contains(aPoint.x, aPoint.y);}
// Intersection. Returns TRUE if the receiver's area has non-empty
// intersection with aRect's area, and FALSE otherwise.
// Always returns false if aRect is empty or 'this' is empty.
PRBool Intersects(const nsRect& aRect) const;
// Sets 'this' to be a rectangle containing the intersection of the points
// (including edges) of aRect1 and aRect2, or 0,0,0,0 if that intersection is
// empty. Returns false if the resulting rectangle is empty.
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool IntersectRect(const nsRect& aRect1, const nsRect& aRect2);
// Computes the smallest rectangle that contains both the area of both
// aRect1 and aRect2, and fills 'this' with the result.
// Thus, empty input rectangles are ignored.
// Returns FALSE and sets 'this' rect to be an empty rect if both aRect1
// and aRect2 are empty.
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool UnionRect(const nsRect& aRect1, const nsRect& aRect2);
// Computes the smallest rectangle that contains both the points (including
// edges) of both aRect1 and aRect2.
// Thus, empty input rectangles are allowed to affect the result.
//
// 'this' can be the same object as either aRect1 or aRect2
void UnionRectEdges(const nsRect& aRect1, const nsRect& aRect2);
// Accessors
void SetRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {
x = aX; y = aY; width = aWidth; height = aHeight;
}
void SetRect(const nsPoint& aPt, const nsSize& aSize) {
SetRect(aPt.x, aPt.y, aSize.width, aSize.height);
}
void MoveTo(nscoord aX, nscoord aY) {x = aX; y = aY;}
void MoveTo(const nsPoint& aPoint) {x = aPoint.x; y = aPoint.y;}
void MoveBy(nscoord aDx, nscoord aDy) {x += aDx; y += aDy;}
void MoveBy(const nsPoint& aPoint) {x += aPoint.x; y += aPoint.y;}
void SizeTo(nscoord aWidth, nscoord aHeight) {width = aWidth; height = aHeight;}
void SizeTo(const nsSize& aSize) {SizeTo(aSize.width, aSize.height);}
void SizeBy(nscoord aDeltaWidth, nscoord aDeltaHeight) {width += aDeltaWidth;
height += aDeltaHeight;}
// Inflate the rect by the specified width/height or margin
void Inflate(nscoord aDx, nscoord aDy);
void Inflate(const nsSize& aSize) {Inflate(aSize.width, aSize.height);}
void Inflate(const nsMargin& aMargin);
// Deflate the rect by the specified width/height or margin
void Deflate(nscoord aDx, nscoord aDy);
void Deflate(const nsSize& aSize) {Deflate(aSize.width, aSize.height);}
void Deflate(const nsMargin& aMargin);
// Return true if the rectangles contain the same set of points, including
// points on the edges.
// Use when we care about the exact x/y/width/height values being
// equal (i.e. we care about differences in empty rectangles).
PRBool IsEqualEdges(const nsRect& aRect) const {
return x == aRect.x && y == aRect.y &&
width == aRect.width && height == aRect.height;
}
// Return true if the rectangles contain the same area of the plane.
// Use when we do not care about differences in empty rectangles.
PRBool IsEqualInterior(const nsRect& aRect) const {
return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
}
// Arithmetic with nsPoints
nsRect operator+(const nsPoint& aPoint) const {
return nsRect(x + aPoint.x, y + aPoint.y, width, height);
}
nsRect operator-(const nsPoint& aPoint) const {
return nsRect(x - aPoint.x, y - aPoint.y, width, height);
}
nsRect& operator+=(const nsPoint& aPoint) {x += aPoint.x; y += aPoint.y; return *this;}
nsRect& operator-=(const nsPoint& aPoint) {x -= aPoint.x; y -= aPoint.y; return *this;}
// Arithmetic with nsMargins
nsMargin operator-(const nsRect& aRect) const; // Find difference as nsMargin
nsRect& operator+=(const nsMargin& aMargin) { Inflate(aMargin); return *this; }
nsRect& operator-=(const nsMargin& aMargin) { Deflate(aMargin); return *this; }
nsRect operator+(const nsMargin& aMargin) const { return nsRect(*this) += aMargin; }
nsRect operator-(const nsMargin& aMargin) const { return nsRect(*this) -= aMargin; }
// Scale by aScale, converting coordinates to integers so that the result is
// the smallest integer-coordinate rectangle containing the unrounded result.
nsRect& ScaleRoundOut(float aScale) { return ScaleRoundOut(aScale, aScale); }
nsRect& ScaleRoundOut(float aXScale, float aYScale);
// Extend the rect outwards such that the edges are on integer boundaries
// Extend the rect outwards such that the edges are on integer boundaries
// and the edges scaled by aXMult/aYMult are also on integer boundaries.
// aXMult/aYMult must be N or 1/N for integer N.
nsRect& ExtendForScaling(float aXMult, float aYMult);
@ -196,169 +93,42 @@ struct NS_GFX nsRect {
inline nsRect ConvertAppUnitsRoundOut(PRInt32 aFromAPP, PRInt32 aToAPP) const;
inline nsRect ConvertAppUnitsRoundIn(PRInt32 aFromAPP, PRInt32 aToAPP) const;
// Helpers for accessing the vertices
nsPoint TopLeft() const { return nsPoint(x, y); }
nsPoint TopRight() const { return nsPoint(XMost(), y); }
nsPoint BottomLeft() const { return nsPoint(x, YMost()); }
nsPoint BottomRight() const { return nsPoint(XMost(), YMost()); }
nsSize Size() const { return nsSize(width, height); }
// Helper methods for computing the extents
nscoord XMost() const {return x + width;}
nscoord YMost() const {return y + height;}
inline nsIntRect ToNearestPixels(nscoord aAppUnitsPerPixel) const;
inline nsIntRect ToOutsidePixels(nscoord aAppUnitsPerPixel) const;
inline nsIntRect ToInsidePixels(nscoord aAppUnitsPerPixel) const;
};
struct NS_GFX nsIntRect {
PRInt32 x, y;
PRInt32 width, height;
struct NS_GFX nsIntRect :
public mozilla::BaseRect<PRInt32, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> {
typedef mozilla::BaseRect<PRInt32, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> Super;
// Constructors
nsIntRect() : x(0), y(0), width(0), height(0) {}
nsIntRect(const nsIntRect& aRect) {*this = aRect;}
nsIntRect(const nsIntPoint& aOrigin, const nsIntSize &aSize) {
x = aOrigin.x; y = aOrigin.y;
width = aSize.width; height = aSize.height;
}
nsIntRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) {
x = aX; y = aY; width = aWidth; height = aHeight;
}
// Emptiness. An empty rect is one that has no area, i.e. its height or width
// is <= 0
PRBool IsEmpty() const {
return (PRBool) ((height <= 0) || (width <= 0));
}
void Empty() {width = height = 0;}
// Inflate the rect by the specified width/height or margin
void Inflate(PRInt32 aDx, PRInt32 aDy) {
x -= aDx;
y -= aDy;
width += aDx*2;
height += aDy*2;
}
void Inflate(const nsIntMargin &aMargin) {
x -= aMargin.left;
y -= aMargin.top;
width += aMargin.left + aMargin.right;
height += aMargin.top + aMargin.bottom;
}
// Deflate the rect by the specified width/height or margin
void Deflate(PRInt32 aDx, PRInt32 aDy) {
x += aDx;
y += aDy;
width -= aDx*2;
height -= aDy*2;
}
void Deflate(const nsIntMargin &aMargin) {
x += aMargin.left;
y += aMargin.top;
width -= (aMargin.left + aMargin.right);
height -= (aMargin.top + aMargin.bottom);
}
// Overloaded operators. Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator.
PRBool operator==(const nsIntRect& aRect) const {
return IsEqualEdges(aRect);
}
// Return true if the rectangles contain the same set of points, including
// points on the edges.
// Use when we care about the exact x/y/width/height values being
// equal (i.e. we care about differences in empty rectangles).
PRBool IsEqualEdges(const nsIntRect& aRect) const {
return x == aRect.x && y == aRect.y &&
width == aRect.width && height == aRect.height;
}
// Return true if the rectangles contain the same area of the plane.
// Use when we do not care about differences in empty rectangles.
PRBool IsEqualInterior(const nsIntRect& aRect) const {
return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
}
nsIntRect operator+(const nsIntPoint& aPoint) const {
return nsIntRect(x + aPoint.x, y + aPoint.y, width, height);
}
nsIntRect operator-(const nsIntPoint& aPoint) const {
return nsIntRect(x - aPoint.x, y - aPoint.y, width, height);
}
nsIntRect& operator+=(const nsIntPoint& aPoint) {x += aPoint.x; y += aPoint.y; return *this;}
nsIntRect& operator-=(const nsIntPoint& aPoint) {x -= aPoint.x; y -= aPoint.y; return *this;}
void SetRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) {
x = aX; y = aY; width = aWidth; height = aHeight;
}
void MoveTo(PRInt32 aX, PRInt32 aY) {x = aX; y = aY;}
void MoveTo(const nsIntPoint& aPoint) {x = aPoint.x; y = aPoint.y;}
void MoveBy(PRInt32 aDx, PRInt32 aDy) {x += aDx; y += aDy;}
void MoveBy(const nsIntPoint& aPoint) {x += aPoint.x; y += aPoint.y;}
void SizeTo(PRInt32 aWidth, PRInt32 aHeight) {width = aWidth; height = aHeight;}
void SizeTo(const nsIntSize& aSize) {SizeTo(aSize.width, aSize.height);}
void SizeBy(PRInt32 aDeltaWidth, PRInt32 aDeltaHeight) {width += aDeltaWidth;
height += aDeltaHeight;}
PRBool Contains(const nsIntRect& aRect) const
nsIntRect() : Super()
{
return aRect.IsEmpty() ||
(PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
}
PRBool Contains(PRInt32 aX, PRInt32 aY) const
nsIntRect(const nsIntRect& aRect) : Super(aRect)
{
return (PRBool) ((aX >= x) && (aY >= y) &&
(aX < XMost()) && (aY < YMost()));
}
PRBool Contains(const nsIntPoint& aPoint) const { return Contains(aPoint.x, aPoint.y); }
// Intersection. Returns TRUE if the receiver overlaps aRect and
// FALSE otherwise
PRBool Intersects(const nsIntRect& aRect) const {
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
(aRect.x < XMost()) && (aRect.y < YMost()));
nsIntRect(const nsIntPoint& aOrigin, const nsIntSize &aSize) : Super(aOrigin, aSize)
{
}
nsIntRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) :
Super(aX, aY, aWidth, aHeight)
{
}
// Computes the area in which aRect1 and aRect2 overlap, and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect, and sets 'this'
// rect to be an empty rect.
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool IntersectRect(const nsIntRect& aRect1, const nsIntRect& aRect2);
// Computes the smallest rectangle that contains both aRect1 and aRect2 and
// fills 'this' with the result. Returns FALSE and sets 'this' rect to be an
// empty rect if both aRect1 and aRect2 are empty
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool UnionRect(const nsIntRect& aRect1, const nsIntRect& aRect2);
// Helpers for accessing the vertices
nsIntPoint TopLeft() const { return nsIntPoint(x, y); }
nsIntPoint TopRight() const { return nsIntPoint(XMost(), y); }
nsIntPoint BottomLeft() const { return nsIntPoint(x, YMost()); }
nsIntPoint BottomRight() const { return nsIntPoint(XMost(), YMost()); }
nsIntSize Size() const { return nsIntSize(width, height); }
// Helper methods for computing the extents
PRInt32 XMost() const {return x + width;}
PRInt32 YMost() const {return y + height;}
inline nsRect ToAppUnits(nscoord aAppUnitsPerPixel) const;
nsIntRect& ScaleRoundOut(float aXScale, float aYScale);
// Returns a special nsIntRect that's used in some places to signify
// "all available space".
static const nsIntRect& GetMaxSizedIntRect() { return kMaxSizedIntRect; }
// This is here only to keep IPDL-generated code happy. DO NOT USE.
bool operator==(const nsIntRect& aRect) const
{
return IsEqualEdges(aRect);
}
protected:
static const nsIntRect kMaxSizedIntRect;
};

Просмотреть файл

@ -39,54 +39,6 @@
#include "nsMathUtils.h"
gfxRect
gfxRect::Intersect(const gfxRect& aRect) const
{
gfxRect result(0,0,0,0);
gfxFloat x = PR_MAX(aRect.X(), X());
gfxFloat xmost = PR_MIN(aRect.XMost(), XMost());
if (x >= xmost)
return result;
gfxFloat y = PR_MAX(aRect.Y(), Y());
gfxFloat ymost = PR_MIN(aRect.YMost(), YMost());
if (y >= ymost)
return result;
result = gfxRect(x, y, xmost - x, ymost - y);
return result;
}
gfxRect
gfxRect::Union(const gfxRect& aRect) const
{
if (IsEmpty())
return aRect;
if (aRect.IsEmpty())
return *this;
gfxFloat x = PR_MIN(aRect.X(), X());
gfxFloat xmost = PR_MAX(aRect.XMost(), XMost());
gfxFloat y = PR_MIN(aRect.Y(), Y());
gfxFloat ymost = PR_MAX(aRect.YMost(), YMost());
return gfxRect(x, y, xmost - x, ymost - y);
}
PRBool
gfxRect::Contains(const gfxRect& aRect) const
{
return aRect.X() >= X() && aRect.XMost() <= XMost() &&
aRect.Y() >= Y() && aRect.YMost() <= YMost();
}
PRBool
gfxRect::Contains(const gfxPoint& aPoint) const
{
return aPoint.x >= X() && aPoint.x <= XMost() &&
aPoint.y >= Y() && aPoint.y <= YMost();
}
static PRBool
WithinEpsilonOfInteger(gfxFloat aX, gfxFloat aEpsilon)
{

Просмотреть файл

@ -41,7 +41,19 @@
#include "gfxTypes.h"
#include "gfxPoint.h"
#include "gfxCore.h"
#include "nsDebug.h"
#include "nsDebug.h"
#include "mozilla/BaseMargin.h"
#include "mozilla/BaseRect.h"
struct gfxMargin : public mozilla::BaseMargin<gfxFloat, gfxMargin> {
typedef mozilla::BaseMargin<gfxFloat, gfxMargin> Super;
// Constructors
gfxMargin() : Super() {}
gfxMargin(const gfxMargin& aMargin) : Super(aMargin) {}
gfxMargin(gfxFloat aLeft, gfxFloat aTop, gfxFloat aRight, gfxFloat aBottom)
: Super(aLeft, aTop, aRight, aBottom) {}
};
namespace mozilla {
namespace css {
@ -73,77 +85,15 @@ static inline mozilla::css::Corner operator++(mozilla::css::Corner& corner, int)
return corner;
}
struct THEBES_API gfxRect
{
gfxFloat x, y;
gfxFloat width, height;
struct THEBES_API gfxRect :
public mozilla::BaseRect<gfxFloat, gfxRect, gfxPoint, gfxSize, gfxMargin> {
typedef mozilla::BaseRect<gfxFloat, gfxRect, gfxPoint, gfxSize, gfxMargin> Super;
gfxRect() {}
gfxRect(const gfxPoint& _pos, const gfxSize& _size) :
x(_pos.x), y(_pos.y), width(_size.width), height(_size.height) {}
gfxRect(gfxFloat _x, gfxFloat _y, gfxFloat _width, gfxFloat _height) :
x(_x), y(_y), width(_width), height(_height) {}
int operator==(const gfxRect& s) const {
return x == s.x && y == s.y && width == s.width && height == s.height;
}
PRBool IsEqualEdges(const gfxRect& aRect) const {
return x == aRect.x && y == aRect.y &&
width == aRect.width && height == aRect.height;
}
// Return true if the rectangles contain the same area of the plane.
// Use when we do not care about differences in empty rectangles.
PRBool IsEqualInterior(const gfxRect& aRect) const {
return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
}
void MoveTo(const gfxPoint& aPt) { x = aPt.x; y = aPt.y; }
const gfxRect& MoveBy(const gfxPoint& aPt) {
x += aPt.x;
y += aPt.y;
return *this;
}
void SizeTo(const gfxSize& aSize) { width = aSize.width; height = aSize.height; }
gfxRect operator+(const gfxPoint& aPt) const {
return gfxRect(x + aPt.x, y + aPt.y, width, height);
}
gfxRect operator-(const gfxPoint& aPt) const {
return gfxRect(x - aPt.x, y - aPt.y, width, height);
}
gfxRect operator+(const gfxSize& aSize) const {
return gfxRect(x + aSize.width, y + aSize.height, width, height);
}
gfxRect operator-(const gfxSize& aSize) const {
return gfxRect(x - aSize.width, y - aSize.height, width, height);
}
gfxRect operator*(const gfxFloat aScale) const {
return gfxRect(x * aScale, y * aScale, width * aScale, height * aScale);
}
const gfxRect& operator+=(const gfxPoint& aPt) {
x += aPt.x;
y += aPt.y;
return *this;
}
const gfxRect& operator-=(const gfxPoint& aPt) {
x -= aPt.x;
y -= aPt.y;
return *this;
}
gfxFloat Width() const { return width; }
gfxFloat Height() const { return height; }
gfxFloat X() const { return x; }
gfxFloat Y() const { return y; }
gfxFloat XMost() const { return x + width; }
gfxFloat YMost() const { return y + height; }
PRBool IsEmpty() const { return width <= 0 || height <= 0; }
gfxRect Intersect(const gfxRect& aRect) const;
gfxRect Union(const gfxRect& aRect) const;
PRBool Contains(const gfxRect& aRect) const;
PRBool Contains(const gfxPoint& aPoint) const;
gfxRect() : Super() {}
gfxRect(const gfxPoint& aPos, const gfxSize& aSize) :
Super(aPos, aSize) {}
gfxRect(gfxFloat aX, gfxFloat aY, gfxFloat aWidth, gfxFloat aHeight) :
Super(aX, aY, aWidth, aHeight) {}
/**
* Return true if all components of this rect are within
@ -153,20 +103,12 @@ struct THEBES_API gfxRect
*/
PRBool WithinEpsilonOfIntegerPixels(gfxFloat aEpsilon) const;
gfxSize Size() const { return gfxSize(width, height); }
void Inset(gfxFloat k) {
x += k;
y += k;
width = PR_MAX(0.0, width - k * 2.0);
height = PR_MAX(0.0, height - k * 2.0);
Deflate(k, k);
}
void Inset(gfxFloat top, gfxFloat right, gfxFloat bottom, gfxFloat left) {
x += left;
y += top;
width = PR_MAX(0.0, width - (right+left));
height = PR_MAX(0.0, height - (bottom+top));
Deflate(gfxMargin(left, top, right, bottom));
}
void Inset(const gfxFloat *sides) {
@ -174,25 +116,15 @@ struct THEBES_API gfxRect
}
void Inset(const gfxIntSize& aSize) {
Inset(aSize.height, aSize.width, aSize.height, aSize.width);
Deflate(aSize.width, aSize.height);
}
void Outset(gfxFloat k) {
x -= k;
y -= k;
width = PR_MAX(0.0, width + k * 2.0);
height = PR_MAX(0.0, height + k * 2.0);
Inflate(k, k);
}
void Outset(gfxFloat top, gfxFloat right, gfxFloat bottom, gfxFloat left) {
x -= left;
y -= top;
width = PR_MAX(0.0, width + (right+left));
height = PR_MAX(0.0, height + (bottom+top));
}
void Outset(const gfxFloat *sides) {
Outset(sides[0], sides[1], sides[2], sides[3]);
Inflate(gfxMargin(left, top, right, bottom));
}
void Outset(const gfxIntSize& aSize) {
@ -220,13 +152,6 @@ struct THEBES_API gfxRect
// resulting rectangle contains the original rectangle.
void RoundOut();
// grabbing specific points
gfxPoint TopLeft() const { return gfxPoint(x, y); }
gfxPoint TopRight() const { return gfxPoint(x, y) + gfxPoint(width, 0.0); }
gfxPoint BottomLeft() const { return gfxPoint(x, y) + gfxPoint(0.0, height); }
gfxPoint BottomRight() const { return gfxPoint(x, y) + gfxPoint(width, height); }
gfxPoint Center() const { return gfxPoint(x, y) + gfxPoint(width, height)/2.0; }
gfxPoint AtCorner(mozilla::css::Corner corner) const {
switch (corner) {
case NS_CORNER_TOP_LEFT: return TopLeft();

Просмотреть файл

@ -1009,10 +1009,8 @@ nsRect
nsLayoutUtils::RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor)
{
/* Get a new gfxRect whose units are app units by scaling by the specified factor. */
gfxRect scaledRect = aRect * aFactor;
/* Round outward. */
scaledRect.RoundOut();
gfxRect scaledRect = aRect;
scaledRect.ScaleRoundOut(aFactor);
/* We now need to constrain our results to the max and min values for coords. */
ConstrainToCoordValues(scaledRect.x);

Просмотреть файл

@ -1746,7 +1746,7 @@ nsObjectFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
window.clipRect.bottom = window.height;
window.type = NPWindowTypeDrawable;
Rect gwBounds;
::Rect gwBounds;
::SetRect(&gwBounds, 0, 0, window.width, window.height);
nsTArray<char> buffer(window.width * window.height * 4);

Просмотреть файл

@ -1356,7 +1356,7 @@ nsMenuPopupFrame::GetConstraintRect(const nsRect& aAnchorRect,
}
// keep a 3 pixel margin to the right and bottom of the screen for the WinXP dropshadow
screenRectPixels.SizeBy(-3, -3);
screenRectPixels.SizeTo(screenRectPixels.width - 3, screenRectPixels.height - 3);
nsRect screenRect = screenRectPixels.ToAppUnits(presContext->AppUnitsPerDevPixel());
if (mInContentShell) {

Просмотреть файл

@ -112,9 +112,9 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext,
nsRect rect = frameToResize->GetScreenRectInAppUnits();
switch (frameToResize->GetStylePosition()->mBoxSizing) {
case NS_STYLE_BOX_SIZING_CONTENT:
rect -= frameToResize->GetUsedPadding();
rect.Deflate(frameToResize->GetUsedPadding());
case NS_STYLE_BOX_SIZING_PADDING:
rect -= frameToResize->GetUsedBorder();
rect.Deflate(frameToResize->GetUsedBorder());
default:
break;
}