474 lines
10 KiB
C
474 lines
10 KiB
C
|
/****************************** 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;
|
||
|
}
|