446 lines
10 KiB
C
446 lines
10 KiB
C
|
/****************************************************************************\
|
||
|
*
|
||
|
* Dirty region calculation
|
||
|
*
|
||
|
* 14-Feb-1995 mikeke Created
|
||
|
*
|
||
|
* Copyright (c) 1994 Microsoft Corporation
|
||
|
\****************************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
PXLIST XLISTAlloc(
|
||
|
__GLGENbuffers *buffers)
|
||
|
{
|
||
|
PXLIST pxlist;
|
||
|
|
||
|
if (buffers->pxlist != NULL) {
|
||
|
pxlist = buffers->pxlist;
|
||
|
buffers->pxlist = pxlist->pnext;
|
||
|
} else {
|
||
|
pxlist = (PXLIST)ALLOC(sizeof(XLIST));
|
||
|
if (pxlist == NULL) return NULL;
|
||
|
}
|
||
|
|
||
|
pxlist->pnext = NULL;
|
||
|
return pxlist;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void XLISTFree(
|
||
|
__GLGENbuffers *buffers,
|
||
|
PXLIST pxlist)
|
||
|
{
|
||
|
pxlist->pnext = buffers->pxlist;
|
||
|
buffers->pxlist = pxlist;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
PXLIST XLISTCopy(
|
||
|
__GLGENbuffers *buffers,
|
||
|
PXLIST pxlist)
|
||
|
{
|
||
|
PXLIST pxlistNew = XLISTAlloc(buffers);
|
||
|
|
||
|
if (pxlistNew != NULL) {
|
||
|
pxlistNew->s = pxlist->s;
|
||
|
pxlistNew->e = pxlist->e;
|
||
|
}
|
||
|
|
||
|
return pxlistNew;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
BOOL YLISTAddSpan(
|
||
|
__GLGENbuffers *buffers,
|
||
|
PYLIST pylist,
|
||
|
int xs,
|
||
|
int xe)
|
||
|
{
|
||
|
PXLIST *ppxlist = &(pylist->pxlist);
|
||
|
PXLIST pxlist = XLISTAlloc(buffers);
|
||
|
|
||
|
if (pxlist == NULL) return FALSE;
|
||
|
|
||
|
//
|
||
|
// Create new x span
|
||
|
//
|
||
|
|
||
|
pxlist->s = xs;
|
||
|
pxlist->e = xe;
|
||
|
|
||
|
//
|
||
|
// Insert it in sorted order
|
||
|
//
|
||
|
|
||
|
while (
|
||
|
((*ppxlist) != NULL)
|
||
|
&& ((*ppxlist)->s < xs)
|
||
|
) {
|
||
|
ppxlist = &((*ppxlist)->pnext);
|
||
|
}
|
||
|
pxlist->pnext = *ppxlist;
|
||
|
*ppxlist = pxlist;
|
||
|
|
||
|
//
|
||
|
// Combine any overlapping spans
|
||
|
//
|
||
|
|
||
|
pxlist = pylist->pxlist;
|
||
|
while (TRUE) {
|
||
|
PXLIST pxlistNext = pxlist->pnext;
|
||
|
|
||
|
if (pxlistNext == NULL) return TRUE;
|
||
|
|
||
|
if (pxlist->e >= pxlistNext->s) {
|
||
|
if (pxlistNext->e > pxlist->e) {
|
||
|
pxlist->e = pxlistNext->e;
|
||
|
}
|
||
|
pxlist->pnext = pxlistNext->pnext;
|
||
|
XLISTFree(buffers, pxlistNext);
|
||
|
} else {
|
||
|
pxlist = pxlist->pnext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
PYLIST YLISTAlloc(
|
||
|
__GLGENbuffers *buffers)
|
||
|
{
|
||
|
PYLIST pylist;
|
||
|
|
||
|
if (buffers->pylist != NULL) {
|
||
|
pylist = buffers->pylist;
|
||
|
buffers->pylist = pylist->pnext;
|
||
|
} else {
|
||
|
pylist = (PYLIST)ALLOC(sizeof(YLIST));
|
||
|
if (pylist == NULL) return NULL;
|
||
|
}
|
||
|
|
||
|
pylist->pxlist = NULL;
|
||
|
pylist->pnext = NULL;
|
||
|
return pylist;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void YLISTFree(
|
||
|
__GLGENbuffers *buffers,
|
||
|
PYLIST pylist)
|
||
|
{
|
||
|
PXLIST pxlist = pylist->pxlist;
|
||
|
PXLIST pxlistKill;
|
||
|
|
||
|
while (pxlist != NULL) {
|
||
|
pxlistKill = pxlist;
|
||
|
pxlist = pxlist->pnext;
|
||
|
XLISTFree(buffers, pxlistKill);
|
||
|
}
|
||
|
|
||
|
pylist->pnext = buffers->pylist;
|
||
|
buffers->pylist = pylist;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
PYLIST YLISTCopy(
|
||
|
__GLGENbuffers *buffers,
|
||
|
PYLIST pylist)
|
||
|
{
|
||
|
PXLIST pxlist = pylist->pxlist;
|
||
|
PXLIST *ppxlist;
|
||
|
PYLIST pylistNew = YLISTAlloc(buffers);
|
||
|
|
||
|
if (pylistNew != NULL) {
|
||
|
pylistNew->s = pylist->s;
|
||
|
pylistNew->e = pylist->e;
|
||
|
|
||
|
ppxlist = &(pylistNew->pxlist);
|
||
|
while (pxlist != NULL) {
|
||
|
*ppxlist = XLISTCopy(buffers, pxlist);
|
||
|
if (*ppxlist == NULL) {
|
||
|
YLISTFree(buffers, pylistNew);
|
||
|
return NULL;
|
||
|
}
|
||
|
ppxlist = &((*ppxlist)->pnext);
|
||
|
pxlist = pxlist->pnext;
|
||
|
}
|
||
|
*ppxlist = NULL;
|
||
|
}
|
||
|
|
||
|
return pylistNew;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void RECTLISTAddRect(
|
||
|
PRECTLIST prl,
|
||
|
int xs,
|
||
|
int ys,
|
||
|
int xe,
|
||
|
int ye)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl->buffers);
|
||
|
PYLIST* ppylist;
|
||
|
PYLIST pylistNew;
|
||
|
|
||
|
ppylist = &(prl->pylist);
|
||
|
while ((*ppylist) != NULL) {
|
||
|
if (ys < (*ppylist)->e) break;
|
||
|
ppylist = &((*ppylist)->pnext);
|
||
|
}
|
||
|
|
||
|
while ((*ppylist) != NULL) {
|
||
|
if (ys < (*ppylist)->s) {
|
||
|
PYLIST pylistNew = YLISTAlloc(buffers);
|
||
|
if (pylistNew == NULL) {
|
||
|
OutOfMemory:
|
||
|
RECTLISTSetEmpty(prl);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pylistNew->s = ys;
|
||
|
pylistNew->e = ye;
|
||
|
if (!YLISTAddSpan(buffers, pylistNew, xs, xe)) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
pylistNew->pnext = *ppylist;
|
||
|
*ppylist = pylistNew;
|
||
|
ppylist = &((*ppylist)->pnext);
|
||
|
|
||
|
if (ye <= (*ppylist)->s) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pylistNew->e = (*ppylist)->s;
|
||
|
ys = (*ppylist)->s;
|
||
|
} else if (ys == (*ppylist)->s) {
|
||
|
if (ye >= (*ppylist)->e) {
|
||
|
if (!YLISTAddSpan(buffers, *ppylist, xs, xe)) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
ys = (*ppylist)->e;
|
||
|
if (ys == ye) return;
|
||
|
ppylist = &((*ppylist)->pnext);
|
||
|
} else {
|
||
|
PYLIST pylistNew = YLISTCopy(buffers, *ppylist);
|
||
|
if (pylistNew == NULL) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
pylistNew->e = ye;
|
||
|
if (!YLISTAddSpan(buffers, pylistNew, xs, xe)) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
(*ppylist)->s = ye;
|
||
|
|
||
|
pylistNew->pnext = *ppylist;
|
||
|
*ppylist = pylistNew;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
PYLIST pylistNew = YLISTCopy(buffers, *ppylist);
|
||
|
if (pylistNew == NULL) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
pylistNew->e = ys;
|
||
|
(*ppylist)->s = ys;
|
||
|
|
||
|
pylistNew->pnext = *ppylist;
|
||
|
*ppylist = pylistNew;
|
||
|
ppylist = &((*ppylist)->pnext);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pylistNew = YLISTAlloc(buffers);
|
||
|
if (pylistNew == NULL) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
pylistNew->s = ys;
|
||
|
pylistNew->e = ye;
|
||
|
if (!YLISTAddSpan(buffers, pylistNew, xs, xe)) {
|
||
|
goto OutOfMemory;
|
||
|
}
|
||
|
|
||
|
pylistNew->pnext = *ppylist;
|
||
|
*ppylist = pylistNew;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
#ifdef LATER
|
||
|
// these functions are not required in the server implementation
|
||
|
|
||
|
#define MAXRECTS 1024
|
||
|
|
||
|
HRGN RECTLISTCreateRegion(
|
||
|
PRECTLIST prl)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl->buffers);
|
||
|
PYLIST pylist = prl->pylist;
|
||
|
int irect = 0;
|
||
|
PRGNDATA prgndata;
|
||
|
PRECT prc;
|
||
|
HRGN hrgn;
|
||
|
|
||
|
prgndata = (PRGNDATA)ALLOC(sizeof(RGNDATAHEADER) + MAXRECTS * sizeof(RECT));
|
||
|
if (prgndata == NULL) return NULL;
|
||
|
|
||
|
prc = (PRECT)(prgndata->Buffer);
|
||
|
|
||
|
while (pylist != NULL) {
|
||
|
PXLIST pxlist = pylist->pxlist;
|
||
|
while (pxlist != NULL) {
|
||
|
prc->left = pxlist->s;
|
||
|
prc->right = pxlist->e;
|
||
|
prc->top = pylist->s;
|
||
|
prc->bottom = pylist->e;
|
||
|
prc++;
|
||
|
irect++;
|
||
|
if (irect == MAXRECTS) {
|
||
|
//Error("maxrect");
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
pxlist = pxlist->pnext;
|
||
|
}
|
||
|
pylist = pylist->pnext;
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
prgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
|
||
|
prgndata->rdh.iType = RDH_RECTANGLES;
|
||
|
prgndata->rdh.nCount = irect;
|
||
|
prgndata->rdh.nRgnSize = 0;
|
||
|
prgndata->rdh.rcBound.left = 0;
|
||
|
prgndata->rdh.rcBound.right = 4096;
|
||
|
prgndata->rdh.rcBound.top = 0;
|
||
|
prgndata->rdh.rcBound.bottom = 4096;
|
||
|
|
||
|
hrgn = GreExtCreateRegion(NULL, irect * sizeof(RECT) + sizeof(RGNDATAHEADER), prgndata);
|
||
|
|
||
|
#ifdef LATER
|
||
|
if (hrgn == NULL) {
|
||
|
Error1("ExtCreateRegion() Error %d\n", GetLastError());
|
||
|
Error1("%d rects\n", irect);
|
||
|
prc = (PRECT)(prgndata->Buffer);
|
||
|
for (;irect>0; irect--) {
|
||
|
//printf("(%5d, %5d, %5d, %5d)\n", prc->left, prc->right, prc->top, prc->bottom);
|
||
|
prc++;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
FREE(prgndata);
|
||
|
|
||
|
return hrgn;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
//
|
||
|
// !!! make this do everything in one pass
|
||
|
//
|
||
|
|
||
|
void RECTLISTOr(
|
||
|
PRECTLIST prl1,
|
||
|
PRECTLIST prl2)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl1->buffers);
|
||
|
PYLIST pylist = prl2->pylist;
|
||
|
|
||
|
while (pylist != NULL) {
|
||
|
PXLIST pxlist = pylist->pxlist;
|
||
|
|
||
|
while (pxlist != NULL) {
|
||
|
RECTLISTAddRect(prl1, pxlist->s, pylist->s, pxlist->e, pylist->e);
|
||
|
pxlist = pxlist->pnext;
|
||
|
}
|
||
|
pylist = pylist->pnext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void RECTLISTOrAndClear(
|
||
|
PRECTLIST prl1,
|
||
|
PRECTLIST prl2)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl1->buffers);
|
||
|
|
||
|
if (RECTLISTIsMax(prl2)) {
|
||
|
RECTLISTSetMax(prl1);
|
||
|
RECTLISTSetEmpty(prl2);
|
||
|
} else {
|
||
|
if (RECTLISTIsEmpty(prl1)) {
|
||
|
//
|
||
|
// If the clear region is empty just swap them
|
||
|
//
|
||
|
RECTLISTSwap(prl1, prl2);
|
||
|
} else {
|
||
|
//
|
||
|
// The clear region isn't empty so maximize it.
|
||
|
//
|
||
|
RECTLISTSetMax(prl1);
|
||
|
RECTLISTSetEmpty(prl2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void RECTLISTSwap(
|
||
|
PRECTLIST prl1,
|
||
|
PRECTLIST prl2)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl1->buffers);
|
||
|
RECTLIST rlTemp = *prl1;
|
||
|
|
||
|
*prl1 = *prl2;
|
||
|
*prl2 = rlTemp;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
void RECTLISTSetEmpty(
|
||
|
PRECTLIST prl)
|
||
|
{
|
||
|
__GLGENbuffers *buffers = (__GLGENbuffers *)(prl->buffers);
|
||
|
PYLIST pylist = prl->pylist;
|
||
|
PYLIST pylistKill;
|
||
|
|
||
|
while (pylist != NULL) {
|
||
|
pylistKill = pylist;
|
||
|
pylist = pylist->pnext;
|
||
|
YLISTFree(buffers, pylistKill);
|
||
|
}
|
||
|
|
||
|
prl->pylist = NULL;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************/
|
||
|
|
||
|
BOOL RECTLISTIsEmpty(
|
||
|
PRECTLIST prl)
|
||
|
{
|
||
|
return (prl->pylist == NULL);
|
||
|
}
|