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

📄 region.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   for (i = 0; i < srcObj->rdh.nCount; i++)
   {
      rc->left += x;
      rc->right += x;
      rc++;
   }
   REGION_IntersectRegion(destObj, destObj, srcObj);

   /* Original region moved to left */
   rc = (PRECT)srcObj->Buffer;
   for (i = 0; i < srcObj->rdh.nCount; i++)
   {
      rc->left -= 2 * x;
      rc->right -= 2 * x;
      rc++;
   }
   REGION_IntersectRegion(destObj, destObj, srcObj);

   /* Original region moved down */
   rc = (PRECT)srcObj->Buffer;
   for (i = 0; i < srcObj->rdh.nCount; i++)
   {
      rc->left += x;
      rc->right += x;
      rc->top += y;
      rc->bottom += y;
      rc++;
   }
   REGION_IntersectRegion(destObj, destObj, srcObj);

   /* Original region moved up */
   rc = (PRECT)srcObj->Buffer;
   for (i = 0; i < srcObj->rdh.nCount; i++)
   {
      rc->top -= 2 * y;
      rc->bottom -= 2 * y;
      rc++;
   }
   REGION_IntersectRegion(destObj, destObj, srcObj);

   /* Restore the original region */
   rc = (PRECT)srcObj->Buffer;
   for (i = 0; i < srcObj->rdh.nCount; i++)
   {
      rc->top += y;
      rc->bottom += y;
      rc++;
   }
   REGION_SubtractRegion(destObj, srcObj, destObj);

   RGNDATA_UnlockRgn(destObj);
   RGNDATA_UnlockRgn(srcObj);
   return TRUE;
}


BOOL FASTCALL REGION_LPTODP(HDC hdc, HRGN hDest, HRGN hSrc)
{
  RECT *pCurRect, *pEndRect;
  PROSRGNDATA srcObj = NULL;
  PROSRGNDATA destObj = NULL;

  DC * dc = DC_LockDc(hdc);
  RECT tmpRect;
  BOOL ret = FALSE;

  if(!dc)
    return ret;

  if(dc->Dc_Attr.iMapMode == MM_TEXT) // Requires only a translation
  {
    if(NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR)
      goto done;

    NtGdiOffsetRgn(hDest, dc->Dc_Attr.ptlViewportOrg.x - dc->Dc_Attr.ptlWindowOrg.x,
                                       dc->Dc_Attr.ptlViewportOrg.y - dc->Dc_Attr.ptlWindowOrg.y);
    ret = TRUE;
    goto done;
  }

  if(!( srcObj = (PROSRGNDATA) RGNDATA_LockRgn( hSrc ) ))
        goto done;
  if(!( destObj = (PROSRGNDATA) RGNDATA_LockRgn( hDest ) ))
  {
    RGNDATA_UnlockRgn( srcObj );
    goto done;
  }
  EMPTY_REGION(destObj);

  pEndRect = (PRECT)srcObj->Buffer + srcObj->rdh.nCount;
  for(pCurRect = (PRECT)srcObj->Buffer; pCurRect < pEndRect; pCurRect++)
  {
    tmpRect = *pCurRect;
    tmpRect.left = XLPTODP(dc, tmpRect.left);
    tmpRect.top = YLPTODP(dc, tmpRect.top);
    tmpRect.right = XLPTODP(dc, tmpRect.right);
    tmpRect.bottom = YLPTODP(dc, tmpRect.bottom);

    if(tmpRect.left > tmpRect.right)
      { INT tmp = tmpRect.left; tmpRect.left = tmpRect.right; tmpRect.right = tmp; }
    if(tmpRect.top > tmpRect.bottom)
      { INT tmp = tmpRect.top; tmpRect.top = tmpRect.bottom; tmpRect.bottom = tmp; }

    REGION_UnionRectWithRegion(&tmpRect, destObj);
  }
  ret = TRUE;

  RGNDATA_UnlockRgn( srcObj );
  RGNDATA_UnlockRgn( destObj );

done:
  DC_UnlockDc( dc );
  return ret;
}

HRGN FASTCALL RGNDATA_AllocRgn(INT n)
{
  HRGN hReg;
  PROSRGNDATA pReg;

  if ((hReg = (HRGN) GDIOBJ_AllocObj(GdiHandleTable, GDI_OBJECT_TYPE_REGION)))
    {
      if (NULL != (pReg = RGNDATA_LockRgn(hReg)))
        {
          if (1 == n)
            {
              /* Testing shows that > 95% of all regions have only 1 rect.
                 Including that here saves us from having to do another
                 allocation */
              pReg->Buffer = &pReg->rdh.rcBound;
            }
          else
            {
              pReg->Buffer = ExAllocatePoolWithTag(PagedPool, n * sizeof(RECT), TAG_REGION);
            }
          if (NULL != pReg->Buffer)
            {
              EMPTY_REGION(pReg);
              pReg->rdh.dwSize = sizeof(RGNDATAHEADER);
              pReg->rdh.nCount = n;
              pReg->rdh.nRgnSize = n*sizeof(RECT);

              RGNDATA_UnlockRgn(pReg);

              return hReg;
            }
        }
      else
        {
          RGNDATA_FreeRgn(hReg);
        }
    }

  return NULL;
}

BOOL INTERNAL_CALL
RGNDATA_Cleanup(PVOID ObjectBody)
{
  PROSRGNDATA pRgn = (PROSRGNDATA)ObjectBody;
  if(pRgn->Buffer && pRgn->Buffer != &pRgn->rdh.rcBound)
    ExFreePool(pRgn->Buffer);
  return TRUE;
}

// NtGdi Exported Functions
INT
STDCALL
NtGdiCombineRgn(HRGN  hDest,
                    HRGN  hSrc1,
                    HRGN  hSrc2,
                    INT  CombineMode)
{
  INT result = ERROR;
  PROSRGNDATA destRgn, src1Rgn, src2Rgn;

  destRgn = RGNDATA_LockRgn(hDest);
  if( destRgn )
    {
      src1Rgn = RGNDATA_LockRgn(hSrc1);
      if( src1Rgn )
	  {
	    if (CombineMode == RGN_COPY)
	      {
		if( !REGION_CopyRegion(destRgn, src1Rgn) )
		  return ERROR;
		result = destRgn->rdh.iType;
	      }
	    else
	    {
              src2Rgn = RGNDATA_LockRgn(hSrc2);
              if( src2Rgn )
		{
		  switch (CombineMode)
		    {
		      case RGN_AND:
			REGION_IntersectRegion(destRgn, src1Rgn, src2Rgn);
			break;
		      case RGN_OR:
			REGION_UnionRegion(destRgn, src1Rgn, src2Rgn);
			break;
		      case RGN_XOR:
			REGION_XorRegion(destRgn, src1Rgn, src2Rgn);
			break;
		      case RGN_DIFF:
			REGION_SubtractRegion(destRgn, src1Rgn, src2Rgn);
			break;
		    }
		  RGNDATA_UnlockRgn(src2Rgn);
		  result = destRgn->rdh.iType;
		}
		else if(hSrc2 == NULL)
                {
                  DPRINT1("NtGdiCombineRgn requires hSrc2 != NULL for combine mode %d!\n", CombineMode);
                }
	    }

            RGNDATA_UnlockRgn(src1Rgn);
	  }

      RGNDATA_UnlockRgn(destRgn);
    }
  else
    {
      DPRINT("NtGdiCombineRgn: hDest unavailable\n");
      result = ERROR;
    }

  return result;
}

HRGN
STDCALL
NtGdiCreateEllipticRgn(INT Left,
                       INT Top,
                       INT Right,
                       INT Bottom)
{
   return NtGdiCreateRoundRectRgn(Left, Top, Right, Bottom,
      Right - Left, Bottom - Top);
}

HRGN STDCALL
NtGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
{
   HRGN hRgn;

   /* Allocate region data structure with space for 1 RECT */
   if ((hRgn = RGNDATA_AllocRgn(1)))
   {
      if (NtGdiSetRectRgn(hRgn, LeftRect, TopRect, RightRect, BottomRect))
         return hRgn;
      NtGdiDeleteObject(hRgn);
   }

   SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
   return NULL;
}

HRGN
STDCALL
NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom,
   INT ellipse_width, INT ellipse_height)
{
    PROSRGNDATA obj;
    HRGN hrgn;
    int asq, bsq, d, xd, yd;
    RECT rect;

      /* Make the dimensions sensible */

    if (left > right) { INT tmp = left; left = right; right = tmp; }
    if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; }

    ellipse_width = abs(ellipse_width);
    ellipse_height = abs(ellipse_height);

      /* Check parameters */

    if (ellipse_width > right-left) ellipse_width = right-left;
    if (ellipse_height > bottom-top) ellipse_height = bottom-top;

      /* Check if we can do a normal rectangle instead */

    if ((ellipse_width < 2) || (ellipse_height < 2))
        return NtGdiCreateRectRgn( left, top, right, bottom );

      /* Create region */

    d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
    if (!(hrgn = RGNDATA_AllocRgn(d))) return 0;
    if (!(obj = RGNDATA_LockRgn(hrgn))) return 0;

      /* Ellipse algorithm, based on an article by K. Porter */
      /* in DDJ Graphics Programming Column, 8/89 */

    asq = ellipse_width * ellipse_width / 4;        /* a^2 */
    bsq = ellipse_height * ellipse_height / 4;      /* b^2 */
    d = bsq - asq * ellipse_height / 2 + asq / 4;   /* b^2 - a^2b + a^2/4 */
    xd = 0;
    yd = asq * ellipse_height;                      /* 2a^2b */

    rect.left   = left + ellipse_width / 2;
    rect.right  = right - ellipse_width / 2;

      /* Loop to draw first half of quadrant */

    while (xd < yd)
    {
	if (d > 0)  /* if nearest pixel is toward the center */
	{
	      /* move toward center */
	    rect.top = top++;
	    rect.bottom = rect.top + 1;
	    UnsafeIntUnionRectWithRgn( obj, &rect );
	    rect.top = --bottom;
	    rect.bottom = rect.top + 1;
	    UnsafeIntUnionRectWithRgn( obj, &rect );
	    yd -= 2*asq;
	    d  -= yd;
	}
	rect.left--;        /* next horiz point */
	rect.right++;
	xd += 2*bsq;
	d  += bsq + xd;
    }
      /* Loop to draw second half of quadrant */

    d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
    while (yd >= 0)
    {
	  /* next vertical point */
	rect.top = top++;
	rect.bottom = rect.top + 1;
	UnsafeIntUnionRectWithRgn( obj, &rect );
	rect.top = --bottom;
	rect.bottom = rect.top + 1;
	UnsafeIntUnionRectWithRgn( obj, &rect );
	if (d < 0)   /* if nearest pixel is outside ellipse */
	{
	    rect.left--;     /* move away from center */
	    rect.right++;
	    xd += 2*bsq;
	    d  += xd;
	}
	yd -= 2*asq;
	d  += asq - yd;
    }
      /* Add the inside rectangle */

    if (top <= bottom)
    {
	rect.top = top;
	rect.bottom = bottom;
	UnsafeIntUnionRectWithRgn( obj, &rect );
    }
    RGNDATA_UnlockRgn( obj );
    return hrgn;
}

BOOL
STDCALL
NtGdiEqualRgn(HRGN  hSrcRgn1,
                   HRGN  hSrcRgn2)
{
  PROSRGNDATA rgn1, rgn2;
  PRECT tRect1, tRect2;
  ULONG i;
  BOOL bRet = FALSE;

  if( !(rgn1 = RGNDATA_LockRgn(hSrcRgn1)))
	return ERROR;

  if( !(rgn2 = RGNDATA_LockRgn(hSrcRgn2))){
	RGNDATA_UnlockRgn( rgn1 );
	return ERROR;
  }

  if(rgn1->rdh.nCount != rgn2->rdh.nCount ||
     	rgn1->rdh.nCount == 0 ||
     	rgn1->rdh.rcBound.left   != rgn2->rdh.rcBound.left ||
     	rgn1->rdh.rcBound.right  != rgn2->rdh.rcBound.right ||
     	rgn1->rdh.rcBound.top    != rgn2->rdh.rcBound.top ||
     	rgn1->rdh.rcBound.bottom != rgn2->rdh.rcBound.bottom)
	goto exit;

  tRect1 = (PRECT)rgn1->Buffer;
  tRect2 = (PRECT)rgn2->Buffer;

  if( !tRect1 || !tRect2 )
	goto exit;

  for(i=0; i < rgn1->rdh.nCount; i++)
  {
    if(tRect1[i].left   != tRect2[i].left ||
       	tRect1[i].right  != tRect2[i].right ||
       	tRect1[i].top    != tRect2[i].top ||
       	tRect1[i].bottom != tRect2[i].bottom)
	   goto exit;
  }
  bRet = TRUE;

exit:
  RGNDATA_UnlockRgn( rgn1 );
  RGNDATA_UnlockRgn( rgn2 );
  return bRet;
}

HRGN
STDCALL
NtGdiExtCreateRegion(OPTIONAL LPXFORM Xform,
                          DWORD Count,
                          LPRGNDATA RgnData)
{
   HRGN hRgn;
   PROSRGNDATA Region;
   DWORD nCount = 0;
   NTSTATUS Status = STATUS_SUCCESS;

   if (Count < FIELD_OFFSET(RGNDATA, Buffer))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return NULL;
   }

   _SEH_TRY
   {
     ProbeForRead(RgnData,
                  Count,
                  1);
     nCount = RgnData->rdh.nCount;
     if((Count - FIELD_OFFSET(RGNDATA, Buffer)) / sizeof(RECT) < nCount)
     {
       Status = STATUS_INVALID_PARAMETER;
       _SEH_LEAVE;
     }
   }
   _SEH_HANDLE
   {
     Status = _SEH_GetExceptionCode();
   }
   _SEH_END;
   if (!NT_SUCCESS(Status))
   {
      SetLastNtError(Status);

⌨️ 快捷键说明

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