⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 region.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 *      None.
 *
 * \note Side Effects:
 *      Rectangles are overwritten in pReg->rects and pReg->numRects will
 *      be changed.
 *
 */
static void FASTCALL
REGION_UnionO (
	PROSRGNDATA pReg,
	PRECT       r1,
	PRECT       r1End,
	PRECT       r2,
	PRECT       r2End,
	INT         top,
	INT         bottom
	)
{
    RECT *pNextRect;

    pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;

#define MERGERECT(r) \
    if ((pReg->rdh.nCount != 0) &&  \
		((pNextRect-1)->top == top) &&  \
		((pNextRect-1)->bottom == bottom) &&  \
		((pNextRect-1)->right >= r->left))  \
    {  \
		if ((pNextRect-1)->right < r->right)  \
		{  \
		    (pNextRect-1)->right = r->right;  \
		}  \
    }  \
    else  \
    {  \
		MEMCHECK(pReg, pNextRect, pReg->Buffer);  \
		pNextRect->top = top;  \
		pNextRect->bottom = bottom;  \
		pNextRect->left = r->left;  \
		pNextRect->right = r->right;  \
		pReg->rdh.nCount += 1;  \
		pNextRect += 1;  \
    }  \
    r++;

    while ((r1 != r1End) && (r2 != r2End))
    {
		if (r1->left < r2->left)
		{
		    MERGERECT(r1);
		}
		else
		{
		    MERGERECT(r2);
		}
    }

    if (r1 != r1End)
    {
		do
		{
		    MERGERECT(r1);
		} while (r1 != r1End);
    }
    else while (r2 != r2End)
    {
		MERGERECT(r2);
    }
    return;
}

/***********************************************************************
 *	     REGION_UnionRegion
 */
static void FASTCALL REGION_UnionRegion(ROSRGNDATA *newReg, ROSRGNDATA *reg1,
			       ROSRGNDATA *reg2)
{
  /*  checks all the simple cases */

  /*
   * Region 1 and 2 are the same or region 1 is empty
   */
  if (reg1 == reg2 || 0 == reg1->rdh.nCount ||
      reg1->rdh.rcBound.right <= reg1->rdh.rcBound.left ||
      reg1->rdh.rcBound.bottom <= reg1->rdh.rcBound.top)
    {
      if (newReg != reg2)
	{
	  REGION_CopyRegion(newReg, reg2);
	}
      return;
    }

    /*
     * if nothing to union (region 2 empty)
     */
  if (0 == reg2->rdh.nCount ||
      reg2->rdh.rcBound.right <= reg2->rdh.rcBound.left ||
      reg2->rdh.rcBound.bottom <= reg2->rdh.rcBound.top)
    {
      if (newReg != reg1)
	{
	  REGION_CopyRegion(newReg, reg1);
	}
      return;
    }

  /*
   * Region 1 completely subsumes region 2
   */
  if (1 == reg1->rdh.nCount &&
      reg1->rdh.rcBound.left <= reg2->rdh.rcBound.left &&
      reg1->rdh.rcBound.top <= reg2->rdh.rcBound.top &&
      reg2->rdh.rcBound.right <= reg1->rdh.rcBound.right &&
      reg2->rdh.rcBound.bottom <= reg1->rdh.rcBound.bottom)
    {
      if (newReg != reg1)
	{
	  REGION_CopyRegion(newReg, reg1);
	}
      return;
    }

  /*
   * Region 2 completely subsumes region 1
   */
  if (1 == reg2->rdh.nCount &&
      reg2->rdh.rcBound.left <= reg1->rdh.rcBound.left &&
      reg2->rdh.rcBound.top <= reg1->rdh.rcBound.top &&
      reg1->rdh.rcBound.right <= reg2->rdh.rcBound.right &&
      reg1->rdh.rcBound.bottom <= reg2->rdh.rcBound.bottom)
    {
      if (newReg != reg2)
	{
	  REGION_CopyRegion(newReg, reg2);
	}
      return;
    }

  REGION_RegionOp ( newReg, reg1, reg2, REGION_UnionO,
		  REGION_UnionNonO, REGION_UnionNonO );
  newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left);
  newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top);
  newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right);
  newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom);
}

/***********************************************************************
 *	     Region Subtraction
 ***********************************************************************/

/*!
 *      Deal with non-overlapping band for subtraction. Any parts from
 *      region 2 we discard. Anything from region 1 we add to the region.
 *
 * Results:
 *      None.
 *
 * \note Side Effects:
 *      pReg may be affected.
 *
 */
static void FASTCALL
REGION_SubtractNonO1 (
	PROSRGNDATA pReg,
	PRECT       r,
	PRECT       rEnd,
	INT         top,
	INT         bottom
	)
{
    RECT *pNextRect;

    pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;

    while (r != rEnd)
    {
		MEMCHECK(pReg, pNextRect, pReg->Buffer);
		pNextRect->left = r->left;
		pNextRect->top = top;
		pNextRect->right = r->right;
		pNextRect->bottom = bottom;
		pReg->rdh.nCount += 1;
		pNextRect++;
		r++;
    }
    return;
}


/*!
 *      Overlapping band subtraction. x1 is the left-most point not yet
 *      checked.
 *
 * Results:
 *      None.
 *
 * \note Side Effects:
 *      pReg may have rectangles added to it.
 *
 */
static void FASTCALL
REGION_SubtractO (
	PROSRGNDATA pReg,
	PRECT       r1,
	PRECT       r1End,
	PRECT       r2,
	PRECT       r2End,
	INT         top,
	INT         bottom
	)
{
    RECT *pNextRect;
    INT left;

    left = r1->left;
    pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount;

    while ((r1 != r1End) && (r2 != r2End))
    {
		if (r2->right <= left)
		{
		    /*
		     * Subtrahend missed the boat: go to next subtrahend.
		     */
		    r2++;
		}
		else if (r2->left <= left)
		{
		    /*
		     * Subtrahend preceeds minuend: nuke left edge of minuend.
		     */
		    left = r2->right;
		    if (left >= r1->right)
		    {
			/*
			 * Minuend completely covered: advance to next minuend and
			 * reset left fence to edge of new minuend.
			 */
			r1++;
			if (r1 != r1End)
			    left = r1->left;
		    }
		    else
		    {
			/*
			 * Subtrahend now used up since it doesn't extend beyond
			 * minuend
			 */
			r2++;
		    }
		}
		else if (r2->left < r1->right)
		{
		    /*
		     * Left part of subtrahend covers part of minuend: add uncovered
		     * part of minuend to region and skip to next subtrahend.
		     */
		    MEMCHECK(pReg, pNextRect, pReg->Buffer);
		    pNextRect->left = left;
		    pNextRect->top = top;
		    pNextRect->right = r2->left;
		    pNextRect->bottom = bottom;
		    pReg->rdh.nCount += 1;
		    pNextRect++;
		    left = r2->right;
		    if (left >= r1->right)
		    {
			/*
			 * Minuend used up: advance to new...
			 */
			r1++;
			if (r1 != r1End)
			    left = r1->left;
		    }
		    else
		    {
			/*
			 * Subtrahend used up
			 */
			r2++;
		    }
		}
		else
		{
		    /*
		     * Minuend used up: add any remaining piece before advancing.
		     */
		    if (r1->right > left)
		    {
				MEMCHECK(pReg, pNextRect, pReg->Buffer);
				pNextRect->left = left;
				pNextRect->top = top;
				pNextRect->right = r1->right;
				pNextRect->bottom = bottom;
				pReg->rdh.nCount += 1;
				pNextRect++;
		    }
		    r1++;
		    left = r1->left;
		}
    }

    /*
     * Add remaining minuend rectangles to region.
     */
    while (r1 != r1End)
    {
		MEMCHECK(pReg, pNextRect, pReg->Buffer);
		pNextRect->left = left;
		pNextRect->top = top;
		pNextRect->right = r1->right;
		pNextRect->bottom = bottom;
		pReg->rdh.nCount += 1;
		pNextRect++;
		r1++;
		if (r1 != r1End)
		{
		    left = r1->left;
		}
    }
    return;
}

/*!
 *      Subtract regS from regM and leave the result in regD.
 *      S stands for subtrahend, M for minuend and D for difference.
 *
 * Results:
 *      TRUE.
 *
 * \note Side Effects:
 *      regD is overwritten.
 *
 */
static void FASTCALL REGION_SubtractRegion(ROSRGNDATA *regD, ROSRGNDATA *regM,
				                       ROSRGNDATA *regS )
{
   /* check for trivial reject */
    if ( (!(regM->rdh.nCount)) || (!(regS->rdh.nCount))  ||
		(!EXTENTCHECK(&regM->rdh.rcBound, &regS->rdh.rcBound)) )
    {
		REGION_CopyRegion(regD, regM);
		return;
    }

    REGION_RegionOp (regD, regM, regS, REGION_SubtractO,
		REGION_SubtractNonO1, NULL);

    /*
     * Can't alter newReg's extents before we call miRegionOp because
     * it might be one of the source regions and miRegionOp depends
     * on the extents of those regions being the unaltered. Besides, this
     * way there's no checking against rectangles that will be nuked
     * due to coalescing, so we have to examine fewer rectangles.
     */
    REGION_SetExtents (regD);
}

/***********************************************************************
 *	     REGION_XorRegion
 */
static void FASTCALL REGION_XorRegion(ROSRGNDATA *dr, ROSRGNDATA *sra,
							ROSRGNDATA *srb)
{
  HRGN htra, htrb;
  ROSRGNDATA *tra, *trb;

  if(!(htra = RGNDATA_AllocRgn(sra->rdh.nCount + 1)))
    return;
  if(!(htrb = RGNDATA_AllocRgn(srb->rdh.nCount + 1)))
  {
    NtGdiDeleteObject( htra );
    return;
  }
  tra = RGNDATA_LockRgn( htra );
  if(!tra ){
    NtGdiDeleteObject( htra );
    NtGdiDeleteObject( htrb );
    return;
  }

  trb = RGNDATA_LockRgn( htrb );
  if( !trb ){
    RGNDATA_UnlockRgn( tra );
    NtGdiDeleteObject( htra );
    NtGdiDeleteObject( htrb );
    return;
  }

  REGION_SubtractRegion(tra,sra,srb);
  REGION_SubtractRegion(trb,srb,sra);
  REGION_UnionRegion(dr,tra,trb);
  RGNDATA_UnlockRgn( tra );
  RGNDATA_UnlockRgn( trb );

  NtGdiDeleteObject( htra );
  NtGdiDeleteObject( htrb );
  return;
}


/*!
 * Adds a rectangle to a REGION
 */
void FASTCALL REGION_UnionRectWithRegion(const RECT *rect, ROSRGNDATA *rgn)
{
    ROSRGNDATA region;

    region.Buffer = &region.rdh.rcBound;
    region.rdh.nCount = 1;
    region.rdh.nRgnSize = sizeof( RECT );
    region.rdh.rcBound = *rect;
    REGION_UnionRegion(rgn, rgn, &region);
}

BOOL FASTCALL REGION_CreateFrameRgn(HRGN hDest, HRGN hSrc, INT x, INT y)
{
   PROSRGNDATA srcObj, destObj;
   PRECT rc;
   ULONG i;

   if (!(srcObj = (PROSRGNDATA)RGNDATA_LockRgn(hSrc)))
   {
      return FALSE;
   }
   if (!REGION_NOT_EMPTY(srcObj))
   {
      RGNDATA_UnlockRgn(srcObj);
      return FALSE;
   }
   if (!(destObj = (PROSRGNDATA)RGNDATA_LockRgn(hDest)))
   {
      RGNDATA_UnlockRgn(srcObj);
      return FALSE;
   }

   EMPTY_REGION(destObj);
   if (!REGION_CopyRegion(destObj, srcObj))
   {
      RGNDATA_UnlockRgn(destObj);
      RGNDATA_UnlockRgn(srcObj);
      return FALSE;
   }

   /* Original region moved to right */
   rc = (PRECT)srcObj->Buffer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -