Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

226 lines
6.8 KiB

/******************************Module*Header**********************************\
*
* *******************
* * GDI SAMPLE CODE *
* *******************
*
* Module Name: clip.c
*
* Clipping code.
*
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
*****************************************************************************/
#include "precomp.h"
#include "gdi.h"
#include "clip.h"
//----------------------------*Public*Routine-------------------------------
// BOOL bIntersect
//
// Function:
// Check the integration of two input rectangles (RECTL* pRcl1,
// RECTL* pRcl2) and set the intersection result in (RECTL* pRclResult)
//
// Return:
// TRUE---If 'prcl1' and 'prcl2' intersect. The intersection will be in
// 'prclResult'
// FALSE--If they don't intersect. 'prclResult' is undefined.
//
//---------------------------------------------------------------------------
BOOL
bIntersect(RECTL* pRcl1,
RECTL* pRcl2,
RECTL* pRclResult)
{
DBG_GDI((7, "bIntersect called--pRcl1=0x%x, pRcl2=0x%x, pRclResult=0x%x",
pRcl1, pRcl2, pRclResult));
pRclResult->left = max(pRcl1->left, pRcl2->left);
pRclResult->right = min(pRcl1->right, pRcl2->right);
//
// Check if there an intersection horizontally
//
if ( pRclResult->left < pRclResult->right )
{
pRclResult->top = max(pRcl1->top, pRcl2->top);
pRclResult->bottom = min(pRcl1->bottom, pRcl2->bottom);
if (pRclResult->top < pRclResult->bottom)
{
//
// Check if there an intersection vertically
//
return(TRUE);
}
}
DBG_GDI((7, "bIntersect returned FALSE"));
//
// Return FALSE if there is no intersection
//
return(FALSE);
}// bIntersect()
//-----------------------------Public Routine-------------------------------
// LONG cIntersect
//
// This routine takes a list of rectangles from 'pRclIn' and clips them
// in-place to the rectangle 'pRclClip'. The input rectangles don't
// have to intersect 'prclClip'; the return value will reflect the
// number of input rectangles that did intersect, and the intersecting
// rectangles will be densely packed.
//
//--------------------------------------------------------------------------
LONG
cIntersect(RECTL* pRclClip,
RECTL* pRclIn,
LONG lNumOfRecs)
{
LONG cIntersections;
RECTL* pRclOut;
DBG_GDI((7, "cIntersect called--pRclClip=0x%x, pRclIn=0x%x,lNumOfRecs=%ld",
pRclClip, pRclIn, lNumOfRecs));
cIntersections = 0;
pRclOut = pRclIn; // Put the result in place as the input
//
// Validate input parameter
//
ASSERTDD( ((pRclIn != NULL ) && (pRclClip != NULL) && ( lNumOfRecs >= 0 )),
"Wrong input to cIntersect" );
for (; lNumOfRecs != 0; pRclIn++, lNumOfRecs--)
{
pRclOut->left = max(pRclIn->left, pRclClip->left);
pRclOut->right = min(pRclIn->right, pRclClip->right);
if ( pRclOut->left < pRclOut->right )
{
//
// Find intersection, horizontally, between current rectangle and
// the clipping rectangle.
//
pRclOut->top = max(pRclIn->top, pRclClip->top);
pRclOut->bottom = min(pRclIn->bottom, pRclClip->bottom);
if ( pRclOut->top < pRclOut->bottom )
{
//
// Find intersection, vertically, between current rectangle and
// the clipping rectangle. Put this rectangle in the result
// list and increment the counter. Ready for next input
//
pRclOut++;
cIntersections++;
}
}
}// loop through all the input rectangles
DBG_GDI((7, "cIntersect found %d intersections", cIntersections));
return(cIntersections);
}// cIntersect()
//-----------------------------Public Routine-------------------------------
// VOID vClipAndRender
//
// Clips the destination rectangle calling pfgn (the render function) as
// appropriate.
//
// Argumentes needed from function block (GFNPB)
//
// pco------pointer to clip object
// prclDst--pointer to destination rectangle
// psurfDst-pointer to destination Surf
// psurfSrc-pointer to destination Surf (NULL if no source)
// pptlSrc--pointer to source point
// prclSrc--pointer to source rectangle (used if pptlSrc == NULL)
// pgfn-----pointer to render function
//
// NOTES:
//
// pptlSrc and prclSrc are only used if psurfSrc == psurfDst. If there is
// no source psurfSrc must be set to NULL. If prclSrc is specified, pptlSrc
// is not used.
//
//--------------------------------------------------------------------------
VOID vClipAndRender(GFNPB * ppb)
{
CLIPOBJ * pco = ppb->pco;
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
{
ppb->pRects = ppb->prclDst;
ppb->lNumRects = 1;
ppb->pgfn(ppb);
}
else if (pco->iDComplexity == DC_RECT)
{
RECTL rcl;
if (bIntersect(ppb->prclDst, &pco->rclBounds, &rcl))
{
ppb->pRects = &rcl;
ppb->lNumRects = 1;
ppb->pgfn(ppb);
}
}
else
{
ClipEnum ce;
LONG c;
BOOL bMore;
ULONG ulDir = CD_ANY;
// determine direction if operation on same surface
if(ppb->psurfDst == ppb->psurfSrc)
{
LONG lXSrc, lYSrc, offset;
if(ppb->pptlSrc != NULL)
{
lXSrc = ppb->pptlSrc->x;
lYSrc = ppb->pptlSrc->y;
}
else
{
lXSrc = ppb->prclSrc->left;
lYSrc = ppb->prclSrc->top;
}
// NOTE: we can safely shift by 16 because the surface
// stride will never be greater the 2--16
offset = (ppb->prclDst->top - lYSrc) << 16;
offset += (ppb->prclDst->left - lXSrc);
if(offset > 0)
ulDir = CD_LEFTUP;
else
ulDir = CD_RIGHTDOWN;
}
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ulDir, 0);
do
{
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
c = cIntersect(ppb->prclDst, ce.arcl, ce.c);
if (c != 0)
{
ppb->pRects = ce.arcl;
ppb->lNumRects = c;
ppb->pgfn(ppb);
}
} while (bMore);
}
}