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

📄 winrgn.c

📁 MinGUI 可视化程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 /******************************************************************************
** 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 (&region->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(&region->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 = &region->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 + -