Windows2000/private/ntos/w32/ntuser/rtl/rect.c

474 lines
10 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/****************************** Module Header ******************************\
* Module Name: rect.c
* Copyright (c) 1985 - 1999, Microsoft Corporation
* This module contains the various rectangle manipulation APIs.
* History:
* 10-20-90 DarrinM Grabbed 'C' rect routines from Portable PM.
*/
#ifdef _USERK_
#define VALIDATERECT(prc, retval) UserAssert(prc)
#else
#define VALIDATERECT(prc, retval) if (prc == NULL) return retval
#endif
/*
* SetRect (API)
* This function fills a rectangle structure with the passed in coordinates.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY SetRect(
LPRECT prc,
int left,
int top,
int right,
int bottom)
{
VALIDATERECT(prc, FALSE);
prc->left = left;
prc->top = top;
prc->right = right;
prc->bottom = bottom;
return TRUE;
}
/*
* CopyInflateRect (API)
* This function copies the rect from prcSrc to prcDst, and inflates it.
* History:
* 12-16-93 FritzS
*/
BOOL APIENTRY CopyInflateRect(
LPRECT prcDst,
CONST RECT *prcSrc,
int cx, int cy)
{
prcDst->left = prcSrc->left - cx;
prcDst->right = prcSrc->right + cx;
prcDst->top = prcSrc->top - cy;
prcDst->bottom = prcSrc->bottom + cy;
return TRUE;
}
/*
* CopyOffsetRect (API)
* This function copies the rect from prcSrc to prcDst, and offsets it.
* History:
* 01-03-94 FritzS
*/
BOOL APIENTRY CopyOffsetRect(
LPRECT prcDst,
CONST RECT *prcSrc,
int cx, int cy)
{
prcDst->left = prcSrc->left + cx;
prcDst->right = prcSrc->right + cx;
prcDst->top = prcSrc->top + cy;
prcDst->bottom = prcSrc->bottom + cy;
return TRUE;
}
/*
* IsRectEmpty (API)
* This function returns TRUE if *prc is an empty rect, FALSE
* otherwise. An empty rect is one that has no area: right is
* less than or equal to left, bottom is less than or equal to top.
* Warning:
* This function assumes that the rect is in device coordinates
* mode where left and top coordinate are smaller than right and
* bottom.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY IsRectEmpty(
CONST RECT *prc)
{
VALIDATERECT(prc, TRUE);
return ((prc->left >= prc->right) || (prc->top >= prc->bottom));
}
/*
* PtInRect (API)
* This function returns TRUE if *ppt falls inside of *prc.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY PtInRect(
CONST RECT *prc,
POINT pt)
{
VALIDATERECT(prc, FALSE);
return ((pt.x >= prc->left) && (pt.x < prc->right) &&
(pt.y >= prc->top) && (pt.y < prc->bottom));
}
/*
* OffsetRect (API)
* This function offsets the coordinates of *prc by adding cx to
* both the left and right coordinates, and cy to both the top and
* bottom coordinates.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY OffsetRect(
LPRECT prc,
int cx,
int cy)
{
VALIDATERECT(prc, FALSE);
prc->left += cx;
prc->right += cx;
prc->bottom += cy;
prc->top += cy;
return TRUE;
}
/*
* InflateRect (API)
* This function expands the given rect by cx horizantally and cy
* vertically on all sides. If cx or cy are negative, the rect
* is inset. cx is subtracted from the left and added to the right,
* and cy is subtracted from the top and added to the bottom.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY InflateRect(
LPRECT prc,
int cx,
int cy)
{
VALIDATERECT(prc, FALSE);
prc->left -= cx;
prc->right += cx;
prc->top -= cy;
prc->bottom += cy;
return TRUE;
}
/*
* IntersectRect (API)
* Calculates the intersection between *prcSrc1 and *prcSrc2,
* returning the resulting rect in *prcDst. Returns TRUE if
* *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
* intersection, an empty rect is returned in *prcDst
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY IntersectRect(
LPRECT prcDst,
CONST RECT *prcSrc1,
CONST RECT *prcSrc2)
{
VALIDATERECT(prcDst, FALSE);
VALIDATERECT(prcSrc1, FALSE);
VALIDATERECT(prcSrc2, FALSE);
prcDst->left = max(prcSrc1->left, prcSrc2->left);
prcDst->right = min(prcSrc1->right, prcSrc2->right);
/*
* check for empty rect
*/
if (prcDst->left < prcDst->right) {
prcDst->top = max(prcSrc1->top, prcSrc2->top);
prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
/*
* check for empty rect
*/
if (prcDst->top < prcDst->bottom) {
return TRUE; // not empty
}
}
/*
* empty rect
*/
SetRectEmpty(prcDst);
return FALSE;
}
/*
* UnionRect (API)
* This function calculates a rect that bounds *prcSrc1 and
* *prcSrc2, returning the result in *prcDst. If either
* *prcSrc1 or *prcSrc2 are empty, then the other rect is
* returned. Returns TRUE if *prcDst is a non-empty rect,
* FALSE otherwise.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
BOOL APIENTRY UnionRect(
LPRECT prcDst,
CONST RECT *prcSrc1,
CONST RECT *prcSrc2)
{
BOOL frc1Empty, frc2Empty;
VALIDATERECT(prcDst, FALSE);
VALIDATERECT(prcSrc1, FALSE);
VALIDATERECT(prcSrc2, FALSE);
frc1Empty = ((prcSrc1->left >= prcSrc1->right) ||
(prcSrc1->top >= prcSrc1->bottom));
frc2Empty = ((prcSrc2->left >= prcSrc2->right) ||
(prcSrc2->top >= prcSrc2->bottom));
if (frc1Empty && frc2Empty) {
SetRectEmpty(prcDst);
return FALSE;
}
if (frc1Empty) {
*prcDst = *prcSrc2;
return TRUE;
}
if (frc2Empty) {
*prcDst = *prcSrc1;
return TRUE;
}
/*
* form the union of the two non-empty rects
*/
prcDst->left = min(prcSrc1->left, prcSrc2->left);
prcDst->top = min(prcSrc1->top, prcSrc2->top);
prcDst->right = max(prcSrc1->right, prcSrc2->right);
prcDst->bottom = max(prcSrc1->bottom, prcSrc2->bottom);
return TRUE;
}
/*
* EqualRect (API)
* This function returns TRUE if *prc1 and *prc2 are identical,
* FALSE otherwise.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
#undef EqualRect // don't let macro interfere with API
BOOL APIENTRY EqualRect(
CONST RECT *prc1,
CONST RECT *prc2)
{
VALIDATERECT(prc1, FALSE);
VALIDATERECT(prc2, FALSE);
/*
* Test equality only. This is what win31 does. win31 does not check to
* see if the rectangles are "empty" first.
*/
return RtlEqualMemory(prc1, prc2, sizeof(RECT));
}
/*
* SubtractRect (API)
* This function subtracts *prc2 from *prc1, returning the result in *prcDst
* Returns FALSE if *lprDst is empty, TRUE otherwise.
* Warning:
* Subtracting one rect from another may not always result in a
* rectangular area; in this case SubtractRect will return *prc1 in
* *prcDst. For this reason, SubractRect provides only an
* approximation of subtraction. However, the area described by
* *prcDst will always be greater than or equal to the "true" result
* of the subtraction.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowsese.
*/
BOOL APIENTRY SubtractRect(
LPRECT prcDst,
CONST RECT *prcSrc1,
CONST RECT *prcSrc2)
{
int cSidesOut;
BOOL fIntersect;
RECT rcInt;
VALIDATERECT(prcDst, FALSE);
VALIDATERECT(prcSrc1, FALSE);
VALIDATERECT(prcSrc2, FALSE);
fIntersect = IntersectRect(&rcInt, prcSrc1, prcSrc2);
/*
* this is done after the intersection in case prcDst is the same
* pointer as prcSrc2
*/
*prcDst = *prcSrc1;
if (fIntersect) {
/*
* exactly any 3 sides of prc2 must be outside prc1 to subtract
*/
cSidesOut = 0;
if (rcInt.left <= prcSrc1->left)
cSidesOut++;
if (rcInt.top <= prcSrc1->top)
cSidesOut++;
if (rcInt.right >= prcSrc1->right)
cSidesOut++;
if (rcInt.bottom >= prcSrc1->bottom)
cSidesOut++;
if (cSidesOut == 4) {
/*
* result is the empty rect
*/
SetRectEmpty(prcDst);
return FALSE;
}
if (cSidesOut == 3) {
/*
* subtract the intersecting rect
*/
if (rcInt.left > prcSrc1->left)
prcDst->right = rcInt.left;
else if (rcInt.right < prcSrc1->right)
prcDst->left = rcInt.right;
else if (rcInt.top > prcSrc1->top)
prcDst->bottom = rcInt.top;
else if (rcInt.bottom < prcSrc1->bottom)
prcDst->top = rcInt.bottom;
}
}
if ((prcDst->left >= prcDst->right) || (prcDst->top >= prcDst->bottom))
return FALSE;
return TRUE;
}
/*
* CopyRect (API)
* This function copies the rect from prcSrc to prcDst.
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
#undef CopyRect // don't let macro interfere with API
BOOL APIENTRY CopyRect(
LPRECT prcDst,
CONST RECT *prcSrc)
{
VALIDATERECT(prcDst, FALSE);
VALIDATERECT(prcSrc, FALSE);
*prcDst = *prcSrc;
return TRUE;
}
/*
* SetRectEmpty (API)
* This fuction sets *prc to an empty rect by setting each field to 0.
* Equivalent to SetRect(prc, 0, 0, 0, 0).
* History:
* 10-20-90 DarrinM Translated from PMese to Windowses.
*/
#undef SetRectEmpty // don't let macro interfere with API
BOOL APIENTRY SetRectEmpty(
LPRECT prc)
{
VALIDATERECT(prc, FALSE);
RtlZeroMemory(prc, sizeof(RECT));
return TRUE;
}
/*
* RECTFromSIZERECT
* This function converts a SIZERECT to a RECT.
* History:
* 24-Sep-1996 adams Created.
*/
void
RECTFromSIZERECT(PRECT prc, PCSIZERECT psrc)
{
prc->left = psrc->x;
prc->top = psrc->y;
prc->right = psrc->x + psrc->cx;
prc->bottom = psrc->y + psrc->cy;
}
/*
* SIZERECTFromRECT
* Converts a RECT to a SIZERECT.
* History:
* 09-May-1997 adams Created.
*/
void
SIZERECTFromRECT(PSIZERECT psrc, LPCRECT prc)
{
psrc->x = prc->left;
psrc->y = prc->top;
psrc->cx = prc->right - prc->left;
psrc->cy = prc->bottom - prc->top;
}