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.
 
 
 
 
 
 

373 lines
10 KiB

/******************************Module*Header*******************************\
* Module Name: fillddi.cxx
*
* Contains filling simulations code and help functions.
*
* Created: 04-Apr-1991 17:30:35
* Author: Wendy Wu [wendywu]
*
* Copyright (c) 1990-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
/******************************Member*Function*****************************\
* EngFillPath
*
* This routine first converts the given pathobj to rgnmemobj then
* calls EngPaint to fill.
*
* History:
* 07-Mar-1992 -by- Donald Sidoroff [donalds]
* Rewrote to call (Drv/Eng)Paint
*
* 13-Feb-1991 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL EngFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
PPOINTL pptlBrushOrg,
MIX mix,
FLONG flOptions
)
{
GDIFunctionID(EngFillPath);
ASSERTGDI(pso != (SURFOBJ *) NULL, "pso is NULL\n");
ASSERTGDI(ppo != (PATHOBJ *) NULL, "ppo is NULL\n");
ASSERTGDI(pco != (CLIPOBJ *) NULL, "pco is NULL\n");
PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
PDEVOBJ po(pSurf->hdev());
SUSPENDWATCH sw(po);
ASSERTGDI(pco->iMode == TC_RECTANGLES, "Invalid clip object iMode");
// Check if we have to flatten any Beziers:
if (ppo->fl & PO_BEZIERS)
if (!((EPATHOBJ*) ppo)->bFlatten())
return(FALSE);
// Before we touch any bits, make sure the device is happy about it.
po.vSync(pso,&pco->rclBounds,0);
// check if we can try the fast fill.
if (!( pSurf->flags() & HOOK_PAINT) &&
(pco->iDComplexity != DC_COMPLEX))
{
PRECTL prclClip = NULL;
if ((pco->iDComplexity == DC_RECT) ||
(pco->fjOptions & OC_BANK_CLIP))
{
RECTFX rcfx = ((EPATHOBJ*)ppo)->rcfxBoundBox();
// check the bound box, maybe it really is unclipped
if ((pco->rclBounds.left > (rcfx.xLeft >> 4)) ||
(pco->rclBounds.right < ((rcfx.xRight + 15) >> 4)) ||
(pco->rclBounds.top > (rcfx.yTop >> 4)) ||
(pco->rclBounds.bottom < ((rcfx.yBottom + 15) >> 4)))
{
prclClip = &pco->rclBounds;
}
}
// -1 - couldn't handle, 0 error, 1 success
LONG lRes = EngFastFill(pso,ppo,prclClip,pbo,pptlBrushOrg,mix,flOptions);
if (lRes >= 0)
return(lRes);
}
// Convert path to region.
RECTL Bounds,*pBounds;
if( pco->iDComplexity != DC_TRIVIAL )
{
Bounds.top = (pco->rclBounds.top) << 4;
Bounds.bottom = (pco->rclBounds.bottom) << 4;
pBounds = &Bounds;
}
else
{
pBounds = NULL;
}
RGNMEMOBJTMP rmo(*((EPATHOBJ *)ppo), flOptions, pBounds);
if (!rmo.bValid())
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
if (rmo.iComplexity() == NULLREGION)
return(TRUE);
// CLIPOBJ_bEnum will do the clipping if clipping is not complex.
ERECTL erclClip(pco->rclBounds);
if (pco->iDComplexity == DC_TRIVIAL)
{
ECLIPOBJ ecoPath(rmo.prgnGet(), erclClip);
if (ecoPath.erclExclude().bEmpty())
return(TRUE);
if (ecoPath.iDComplexity == DC_TRIVIAL)
ecoPath.iDComplexity = DC_RECT;
// Inc the target surface uniqueness
INC_SURF_UNIQ(pSurf);
BOOL bRet;
sw.Resume();
bRet = EngPaint(
pso, // Destination surface.
&ecoPath, // Clip object.
pbo, // Realized brush.
pptlBrushOrg, // Brush origin.
mix); // Mix mode.
return(bRet);
}
// Create a RGNMEMOBJ for bMerge since it will trash the target.
RGNMEMOBJTMP rmoTrg;
if (!rmoTrg.bValid())
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
// Merge the region we just constructed with the clip region.
if (!rmoTrg.bMerge(rmo, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
return(FALSE);
ERECTL ercl;
rmoTrg.vGet_rcl(&ercl);
ercl *= ((ECLIPOBJ *)pco)->erclExclude();
ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
if (co.erclExclude().bEmpty())
return(TRUE);
if (co.iDComplexity == DC_TRIVIAL)
co.iDComplexity = DC_RECT;
// Inc the target surface uniqueness
INC_SURF_UNIQ(pSurf);
sw.Resume();
sw.Resume();
return(EngPaint(
pso, // Destination surface.
&co, // Clip object.
pbo, // Realized brush.
pptlBrushOrg, // Brush origin.
mix)); // Mix mode.
}
/******************************Member*Function*****************************\
* EngStrokeAndFillPath
*
* Engine simulation for stroking and filling the given path.
*
* History:
* 06-Apr-1992 -by- J. Andrew Goossen [andrewgo]
* Re-wrote it to do region subtraction.
*
* 02-Oct-1991 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL EngStrokeAndFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
XFORMOBJ *pxo,
BRUSHOBJ *pboStroke,
LINEATTRS *pla,
BRUSHOBJ *pboFill,
POINTL *pptlBrushOrg,
MIX mix,
FLONG flOptions)
{
BOOL bRet = FALSE;
PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
MIX mixFill, mixStroke;
mixFill = mixStroke = mix;
if (!((EBRUSHOBJ *)pboFill)->bIsMasking())
{
mixFill = (mix & 0xff) | ((mix & 0xff) << 8);
}
if (!((EBRUSHOBJ *)pboStroke)->bIsMasking())
{
mixStroke = (mix & 0xff) | ((mix & 0xff) << 8);
}
ERECTL ercl;
// If we're not doing a wide-line, or if we're doing a wide-line and
// the mix is overwrite so we don't care about re-lighting pixels,
// make two calls out of it:
if (!(pla->fl & LA_GEOMETRIC) || ((mix & 0xFF) == R2_COPYPEN))
{
bRet = EngFillPath(pso,
ppo,
pco,
pboFill,
pptlBrushOrg,
mixFill,
flOptions) &&
EngStrokePath(pso,
ppo,
pco,
pxo,
pboStroke,
pptlBrushOrg,
pla,
mixStroke);
return(bRet);
}
// Okay, we have a wideline call with a weird mix mode. Because part
// of the wide-line overlaps part of the fill, we will convert both to
// regions, and subtract them so that they won't overlap.
// Convert the widened outline to a region. We have to widen the path
// before flattening it (for the fill) because the widener will produce
// better looking wide curves that way:
PATHMEMOBJ pmoStroke;
if (!pmoStroke.bValid() ||
!pmoStroke.bComputeWidenedBounds(*(EPATHOBJ*) ppo, pxo, pla) ||
!pmoStroke.bWiden(*(EPATHOBJ*) ppo, pxo, pla))
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
return(bRet);
}
// First flatten any curves and then convert the interior to a region:
if (ppo->fl & PO_BEZIERS)
{
if (!((EPATHOBJ*) ppo)->bFlatten())
{
return(bRet);
}
}
// Create the regions:
RGNMEMOBJTMP rmoStroke(pmoStroke, WINDING);
RGNMEMOBJTMP rmoFill(*((EPATHOBJ *)ppo), flOptions);
RGNMEMOBJTMP rmoNewFill;
if (rmoFill.bValid() &&
rmoStroke.bValid() &&
rmoNewFill.bValid() &&
rmoNewFill.bMerge(rmoFill, rmoStroke, gafjRgnOp[RGN_DIFF]))
{
// Create a RGNMEMOBJ for bMerge since it will trash the target.
RGNMEMOBJTMP rmoTrg;
if (rmoTrg.bValid())
{
PDEVOBJ pdo(pSurf->hdev());
// Paint the stroked outline:
if (rmoStroke.iComplexity() != NULLREGION)
{
// Merge the outline region with the clip region:
if (!rmoTrg.bMerge(rmoStroke, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
{
bRet = FALSE;
}
else
{
rmoTrg.vGet_rcl(&ercl);
ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
if (co.erclExclude().bEmpty())
{
bRet = TRUE;
}
else
{
INC_SURF_UNIQ(pSurf);
bRet = EngPaint(
pso,
&co,
pboStroke,
pptlBrushOrg,
mixStroke);
}
}
}
// Paint the filled interior:
if ((bRet == TRUE) &&
rmoNewFill.iComplexity() != NULLREGION)
{
// Merge the inside region with the clip region.
if (!rmoTrg.bMerge(rmoNewFill, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
{
bRet = FALSE;
}
else
{
rmoTrg.vGet_rcl(&ercl);
ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
if (co.erclExclude().bEmpty())
{
bRet = TRUE;
}
else
{
INC_SURF_UNIQ(pSurf);
bRet = EngPaint(pso,
&co,
pboFill,
pptlBrushOrg,
mixFill);
}
}
}
}
}
return(bRet);
}