📄 winrgn.c
字号:
/******************************************************************************
** Copyright 2006 National ASIC Center, All right Reserved** FILE NAME: winrgn.c* PROGRAMMER: ming.c* Date of Creation: 2006/08/8** DESCRIPTION:** NOTE:** FUNCTIONS LIST:* -----------------------------------------------------------------------------** -----------------------------------------------------------------------------** MODIFICATION HISTORY* LastModify 2006/09/27******************************************************************************/
#include "winrgn.h"
///////////////////////////////////////////////////////////////
#define NULLREGION 0x00
#define SIMPLEREGION 0x01
#define COMPLEXREGION 0x02
#define FreeClipRect(heap, cr) FreeBlock(heap, cr);
#define ClipRectAlloc(heap) AllocBlock(heap)
typedef void (*voidProcp1)(TREGION *region, const TClipRect *r1, const TClipRect *r1End,
const TClipRect *r2, const TClipRect *r2End, int top, int bottom);
typedef void (*voidProcp2)(TREGION *region, const TClipRect *r, const TClipRect *rEnd,
int top, int bottom);
///////////////////////////////////////////////////////////////
/*
* Allocate a new clipping rect and add it to the region.
*/
#define NEWCLIPRECT(region, rect) \
{\
rect = (TClipRect *)ClipRectAlloc(region->heap);\
rect->next = NULL;\
rect->prev = region->tail;\
if (region->tail)\
region->tail->next = rect;\
region->tail = rect;\
if (region->head == NULL)\
region->head = rect;\
}
//---------------------------------------------------------------------------
void OffsetRegion (TREGION *region, int x, int y)
{ TClipRect *cliprect = region->head;
while (cliprect) {
OffsetRect (&cliprect->rc, x, y);
cliprect = cliprect->next;
}
if (region->head) {
OffsetRect (®ion->rcBound, x, y);
}
}
//---------------------------------------------------------------------------
/* return TRUE if point is in region */
BOOL PointInRegion(TREGION *region, int x, int y)
{
int top;
TClipRect *cliprect = region->head;
/* check with bounding rect of clipping region */
if (y >= region->tail->rc.bottom || y < region->head->rc.top)
return false;
/* find the ban in which this point lies */
cliprect = region->head;
while (cliprect && y >= cliprect->rc.bottom) {
cliprect = cliprect->next;
}
if (!cliprect) return false;
/* check in this ban */
top = cliprect->rc.top;
while (cliprect && cliprect->rc.top == top) {
if (PointInRect (x, y,&cliprect->rc))
return true;
cliprect = cliprect->next;
}
return false;
}
//---------------------------------------------------------------------------
/* Returns true if rect is at least partly inside region */
BOOL RectInRegion(TREGION *region, const TRECT* rect)
{ TClipRect *cliprect = region->head;
BOOL ret = false;
if (cliprect && IsRectOverlap(®ion->rcBound, rect))
{
while (cliprect)
{ if (cliprect->rc.bottom <= rect->top)
{ cliprect = cliprect->next;
continue; /* not far enough down yet */
}
if (cliprect->rc.top >= rect->bottom)
{ ret = false; /* too far down */
break;
}
if (cliprect->rc.right <= rect->left)
{ cliprect = cliprect->next;
continue; /* not far enough over yet */
}
if (cliprect->rc.left >= rect->right)
{ cliprect = cliprect->next;
continue;
}
ret = true;
break;
}
}
return ret;
}
//---------------------------------------------------------------------------
BOOL RectIntersect(TRECT *tagRect,TRECT *srcRect)
{ tagRect->left=max(tagRect->left,srcRect->left);
tagRect->top=max(tagRect->top,srcRect->top);
tagRect->right=min(tagRect->right,srcRect->right);
tagRect->bottom=min(tagRect->bottom,srcRect->bottom);
return (tagRect->right>tagRect->left && tagRect->bottom>tagRect->top);
}
//---------------------------------------------------------------------------
// if we moved srcRect to cord (nx,ny), we'll get another rect area,for examle named srcRect2,
// srcRect sub the area of srcRect2, the left area will be stored to tagRects arrays, and the return value denotes the count of rect in tagRects;
int RectOffsetShadown(TRECT *tagRects,TRECT *srcRect,int nx,int ny)
{ int w=srcRect->right-srcRect->left;
int h=srcRect->bottom-srcRect->top;
if(nx>=srcRect->right || nx+w<=srcRect->left || ny>=srcRect->bottom || ny+h<=srcRect->top)
{ *tagRects=*srcRect;
return 1;
}
if(ny==srcRect->top)
{ if(nx==srcRect->left)
{ return 0;
}
else
{ *tagRects=*srcRect;
if(nx<srcRect->left) tagRects->left=nx+w;
else tagRects->right=nx;
return 1;
}
}
else if(ny<srcRect->top)
{ *tagRects=*srcRect;
tagRects->top=ny+h;
if(nx==srcRect->left)
{ return 1;
}
else
{ tagRects++;
if(nx<srcRect->left)
{ tagRects->left=nx+w;
tagRects->top=srcRect->top;
tagRects->right=srcRect->right;
tagRects->bottom=ny+h;
}
else
{ tagRects->left=srcRect->left;
tagRects->top=srcRect->top;
tagRects->right=nx;
tagRects->bottom=ny+h;
}
return 2;
}
}
else
{ *tagRects=*srcRect;
tagRects->bottom=ny;
if(nx==srcRect->left)
{ return 1;
}
else
{ tagRects++;
if(nx<srcRect->left)
{ tagRects->left=nx+w;
tagRects->top=ny;
tagRects->right=srcRect->right;
tagRects->bottom=srcRect->bottom;
}
else
{ tagRects->left=srcRect->left;
tagRects->top=ny;
tagRects->right=nx;
tagRects->bottom=srcRect->bottom;
}
return 2;
}
}
}
//---------------------------------------------------------------------------
/* Init a region */
void InitRegion(TREGION *pRgn, TBLOCKHEAP *heap)
{
pRgn->type = NULLREGION;
SetRectEmpty (&pRgn->rcBound);
pRgn->head = NULL;
pRgn->tail = NULL;
pRgn->heap = heap; // read-only field.
}
//---------------------------------------------------------------------------
/* return bound rect of a region */
void GetRegionBound(TREGION *pRgn, TRECT *pRect)
{ *pRect = pRgn->rcBound;
}
//---------------------------------------------------------------------------
void ClearRegion(TREGION *pRgn)
{
TClipRect *pCRect, *pTemp;
pCRect = pRgn->head;
while (pCRect) {
pTemp = pCRect->next;
FreeClipRect (pRgn->heap, pCRect);
pCRect = pTemp;
}
pRgn->type = NULLREGION;
SetRectEmpty (&pRgn->rcBound);
pRgn->head = NULL;
pRgn->tail = NULL;
}
/* Reset a region */
void RegionReset (TREGION *pRgn, const TRECT* pRect)
{ ClearRegion (pRgn);
if (!IsRectEmpty (pRect))
{ TClipRect *pClipRect;
// get a new clip rect from free list
pClipRect = (TClipRect *)ClipRectAlloc (pRgn->heap);
// set clip rect
pClipRect->rc = *pRect;
pClipRect->next = NULL;
pClipRect->prev = NULL;
pRgn->type = SIMPLEREGION;
pRgn->head = pRgn->tail = pClipRect;
pRgn->rcBound = *pRect;
}
}
//---------------------------------------------------------------------------
void RegionCopy (TREGION *pDstRgn, const TREGION* pSrcRgn)
{ if (pDstRgn != pSrcRgn)
{ TClipRect *pcr=pSrcRgn->head;
ClearRegion (pDstRgn);
if (pcr)
{ TClipRect *pnewcr, *prev;
pnewcr = (TClipRect *)ClipRectAlloc (pDstRgn->heap);
pDstRgn->head = pnewcr;
pnewcr->rc = pcr->rc;
prev = NULL;
while (pcr->next)
{ pnewcr->next = (TClipRect *)ClipRectAlloc (pDstRgn->heap);
pnewcr->prev = prev;
prev = pnewcr;
pcr = pcr->next;
pnewcr = pnewcr->next;
pnewcr->rc = pcr->rc;
}
pnewcr->prev = prev;
pnewcr->next = NULL;
pDstRgn->tail = pnewcr;
pDstRgn->type = pSrcRgn->type;
pDstRgn->rcBound = pSrcRgn->rcBound;
}
}
}
//---------------------------------------------------------------------------
/* Re-calculate the rcBound of a region */
static void REGION_SetExtents (TREGION *region)
{
TClipRect *cliprect;
TRECT *pExtents;
if (region->head == NULL) {
region->rcBound.left = 0; region->rcBound.top = 0;
region->rcBound.right = 0; region->rcBound.bottom = 0;
return;
}
pExtents = ®ion->rcBound;
/*
* Since head is the first rectangle in the region, it must have the
* smallest top and since tail is the last rectangle in the region,
* it must have the largest bottom, because of banding. Initialize left and
* right from head and tail, resp., as good things to initialize them
* to...
*/
pExtents->left = region->head->rc.left;
pExtents->top = region->head->rc.top;
pExtents->right = region->tail->rc.right;
pExtents->bottom = region->tail->rc.bottom;
cliprect = region->head;
while (cliprect) {
if (cliprect->rc.left < pExtents->left)
pExtents->left = cliprect->rc.left;
if (cliprect->rc.right > pExtents->right)
pExtents->right = cliprect->rc.right;
cliprect = cliprect->next;
}
}
/***********************************************************************
* REGION_Coalesce
*
* Attempt to merge the rects in the current band with those in the
* previous one. Used only by REGION_RegionOp.
*
* Results:
* The new index for the previous band.
*
* Side Effects:
* If coalescing takes place:
* - rectangles in the previous band will have their bottom fields
* altered.
* - some clipping rect will be deleted.
*
*/
static TClipRect * REGION_Coalesce (
TREGION *region, /* Region to coalesce */
TClipRect *prevStart, /* start of previous band */
TClipRect *curStart /* start of current band */
) {
TClipRect *newStart; /* Start of new band */
TClipRect *pPrevRect; /* Current rect in previous band */
TClipRect *pCurRect; /* Current rect in current band */
TClipRect *temp; /* Temporary clipping rect */
int curNumRects; /* Number of rectangles in current band */
int prevNumRects; /* Number of rectangles in previous band */
int bandtop; /* top coordinate for current band */
if (prevStart == NULL) prevStart = region->head;
if (curStart == NULL) curStart = region->head;
if (prevStart == curStart)
return prevStart;
newStart = pCurRect = curStart;
pPrevRect = prevStart;
temp = prevStart;
prevNumRects = 0;
while (temp != curStart) {
prevNumRects ++;
temp = temp->next;
}
/*
* Figure out how many rectangles are in the current band. Have to do
* this because multiple bands could have been added in REGION_RegionOp
* at the end when one region has been exhausted.
*/
pCurRect = curStart;
bandtop = pCurRect->rc.top;
curNumRects = 0;
while (pCurRect && (pCurRect->rc.top == bandtop)) {
curNumRects ++;
pCurRect = pCurRect->next;
}
if (pCurRect) {
/*
* If more than one band was added, we have to find the start
* of the last band added so the next coalescing job can start
* at the right place... (given when multiple bands are added,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -