mirror of https://github.com/lianthony/NT4.0
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.
358 lines
9.7 KiB
358 lines
9.7 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: engbrush.cxx
|
|
*
|
|
* Brush realization for the engine.
|
|
*
|
|
* Created: 13-May-1991 23:25:49
|
|
* Author: Patrick Haluptzok patrickh
|
|
*
|
|
* Copyright (c) 1990 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#if DBG
|
|
ULONG engbrushalloc = 0, engbrushcachecheck = 0;
|
|
ULONG engbrushcachegrabbed = 0, engbrushcachehit = 0;
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngRealizeBrush
|
|
*
|
|
* Realizes a brush for the engine simulations.
|
|
*
|
|
* We realize a brush by converting psoPattern to have the same bpp and color
|
|
* format as the destination surface. We copy the monochrome mask unmodified.
|
|
*
|
|
* psoPattern is assumed never to be NULL.
|
|
*
|
|
* Returns: TRUE for success, FALSE for failure.
|
|
*
|
|
* History:
|
|
* 21-Nov-1993 -by- Michael Abrash [mikeab]
|
|
* Removed impossible case of psoPattern == NULL, cleaned up.
|
|
*
|
|
* 20-Jan-1992 -by- Donald Sidoroff [donalds]
|
|
* Tiled pattern and mask to DWORD boundaries
|
|
*
|
|
* 25-Apr-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL EngRealizeBrush(
|
|
BRUSHOBJ *pbo,
|
|
SURFOBJ *psoTarget,
|
|
SURFOBJ *psoPattern,
|
|
SURFOBJ *psoMask,
|
|
XLATEOBJ *pxlo,
|
|
ULONG iHatch)
|
|
{
|
|
PSURFACE pSurfTarg = SURFOBJ_TO_SURFACE(psoTarget);
|
|
PSURFACE pSurfPat = SURFOBJ_TO_SURFACE(psoPattern);
|
|
PSURFACE pSurfMsk = SURFOBJ_TO_SURFACE(psoMask);
|
|
ULONG ulSizeTotal;
|
|
ULONG ulSizePat;
|
|
ULONG cjScanPat, cjScanMsk;
|
|
SIZEL sizlPat;
|
|
SIZEL sizlMsk;
|
|
LONG cxPatRealized;
|
|
LONG cxMskRealized;
|
|
ULONG iFormat;
|
|
POINTL ptlSrc;
|
|
RECTL rclDst;
|
|
DEVBITMAPINFO dbmi;
|
|
|
|
ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
|
|
ASSERTGDI(pSurfTarg != NULL, "ERROR GDI EngRealizeBrush NULL psoTarg");
|
|
ASSERTGDI(pSurfPat != NULL, "ERROR GDI EngRealizeBrush NULL psoPattern");
|
|
ASSERTGDI(!(iHatch & RB_DITHERCOLOR),
|
|
"ERROR GDI EngRealizeBrush RB_DITHERCOLOR set");
|
|
|
|
DONTUSE(iHatch); // used only for dither and realize, which the engine
|
|
// can't do because it never dithers
|
|
|
|
//
|
|
// Calculate the space needed for the pattern.
|
|
//
|
|
iFormat = pSurfTarg->iFormat();
|
|
|
|
//
|
|
// Check if they are having the engine simulate to a bitmap compatible
|
|
// with their surface. The brushobj has the device's surfobj in it
|
|
// but we assume if they got here it's because they created a bitmap
|
|
// compatible with thier format and
|
|
// are drawing on it. Maybe we should have the pvGetEngBrush pass
|
|
// the pSurfTarg along so we know what it is here, because from
|
|
// here we haven't got access to the real surfobj being painted on.
|
|
//
|
|
|
|
ASSERTGDI(pSurfPat->iType() == STYPE_BITMAP, "ERROR GDI EngRealizeBrush2");
|
|
sizlPat = pSurfPat->sizl();
|
|
|
|
switch(iFormat)
|
|
{
|
|
case BMF_1BPP:
|
|
ulSizePat = 1;
|
|
if ((sizlPat.cx == 32) ||
|
|
(sizlPat.cx == 16) ||
|
|
(sizlPat.cx == 8))
|
|
{
|
|
cxPatRealized = 32;
|
|
}
|
|
else
|
|
{
|
|
cxPatRealized = (sizlPat.cx + 63) & ~31;
|
|
}
|
|
break;
|
|
case BMF_4BPP:
|
|
ulSizePat = 4;
|
|
if (sizlPat.cx == 8)
|
|
{
|
|
cxPatRealized = 8;
|
|
}
|
|
else
|
|
{
|
|
cxPatRealized = (sizlPat.cx + 15) & ~7;
|
|
}
|
|
break;
|
|
case BMF_8BPP:
|
|
ulSizePat = 8;
|
|
cxPatRealized = (sizlPat.cx + 7) & ~3;
|
|
break;
|
|
case BMF_16BPP:
|
|
ulSizePat = 16;
|
|
cxPatRealized = (sizlPat.cx + 7) & ~3;
|
|
break;
|
|
case BMF_24BPP:
|
|
ulSizePat = 24;
|
|
cxPatRealized = (sizlPat.cx + 7) & ~3;
|
|
break;
|
|
case BMF_32BPP:
|
|
ulSizePat = 32;
|
|
cxPatRealized = sizlPat.cx;
|
|
break;
|
|
default:
|
|
RIP("ERROR GDI EngRealizeBrush3");
|
|
}
|
|
|
|
//
|
|
// Calculate the size to hold the pattern in the Target's format.
|
|
//
|
|
cjScanPat = (ulSizePat * cxPatRealized) >> 3;
|
|
|
|
ulSizeTotal = sizeof(ENGBRUSH) + (ulSizePat = sizlPat.cy * cjScanPat);
|
|
|
|
//
|
|
// Calculate the additional space needed if we have a mask passed down.
|
|
//
|
|
if (pSurfMsk != NULL)
|
|
{
|
|
ASSERTGDI(pSurfMsk->iFormat() == BMF_1BPP, "ERROR GDI EngRealizeBrush4");
|
|
ASSERTGDI(pSurfMsk->iType() == STYPE_BITMAP, "ERROR GDI EngRealizeBrush5");
|
|
sizlMsk = pSurfMsk->sizl();
|
|
if ((sizlMsk.cx == 32) ||
|
|
(sizlMsk.cx == 16) ||
|
|
(sizlMsk.cx == 8))
|
|
{
|
|
cxMskRealized = 32;
|
|
}
|
|
else
|
|
{
|
|
cxMskRealized = (sizlMsk.cx + 63) & ~31;
|
|
}
|
|
cjScanMsk = cxMskRealized >> 3;
|
|
ulSizeTotal += sizlMsk.cy * cjScanMsk;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for the realization.
|
|
//
|
|
PENGBRUSH pengbrush;
|
|
|
|
#if DBG
|
|
engbrushalloc++;
|
|
#endif
|
|
|
|
//
|
|
// If there's a cached ENGBRUSH, try to use it instead of allocating
|
|
//
|
|
if (gpCachedEngbrush != NULL)
|
|
{
|
|
|
|
#if DBG
|
|
engbrushcachecheck++;
|
|
#endif
|
|
|
|
//
|
|
// Try to grab the cached ENGBRUSH
|
|
//
|
|
if ((pengbrush =
|
|
(PENGBRUSH) InterlockedExchange((LPLONG)&gpCachedEngbrush,
|
|
(LONG)NULL))
|
|
!= NULL)
|
|
{
|
|
|
|
#if DBG
|
|
engbrushcachegrabbed++;
|
|
#endif
|
|
|
|
//
|
|
// Got the cached ENGBRUSH; see if it's big enough
|
|
//
|
|
// Note: -4 because we define the realization buffer start as aj[0]
|
|
if (pengbrush->ulSizeGet() >= (sizeof(ENGBRUSH) - 4 + ulSizeTotal))
|
|
{
|
|
|
|
#if DBG
|
|
engbrushcachehit++;
|
|
#endif
|
|
|
|
//
|
|
// It's big enough, so we'll use it and we're done
|
|
//
|
|
goto BrushAllocated;
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// Not big enough; free it and do a normal allocation
|
|
//
|
|
VFREEMEM(pengbrush);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Note: -4 because we define the realization buffer start as aj[0]
|
|
if ((pengbrush = (PENGBRUSH)
|
|
PALLOCNOZ(SIZE_T(sizeof(ENGBRUSH) - 4 + ulSizeTotal),'rbeG'))
|
|
== NULL)
|
|
{
|
|
WARNING("GDI EngRealizeBrush Couldn't allocate for engine realization");
|
|
return(FALSE);
|
|
}
|
|
|
|
BrushAllocated:
|
|
|
|
//
|
|
// Store the pointer to the realization in the brush.
|
|
//
|
|
((EBRUSHOBJ *) pbo)->pengbrush(pengbrush);
|
|
|
|
//
|
|
// Remember the size of the allocation, for caching.
|
|
//
|
|
pengbrush->ulSizeSet(sizeof(ENGBRUSH) - 4 + ulSizeTotal);
|
|
|
|
//
|
|
// Set up the Pat part. The pattern can never be NULL.
|
|
//
|
|
pengbrush->lDeltaPat = cjScanPat;
|
|
pengbrush->cxPatR = cxPatRealized;
|
|
pengbrush->cxPat = sizlPat.cx;
|
|
pengbrush->cyPat = sizlPat.cy;
|
|
pengbrush->pjPat = pengbrush->aj;
|
|
|
|
dbmi.iFormat = iFormat;
|
|
dbmi.cxBitmap = cxPatRealized;
|
|
dbmi.cyBitmap = sizlPat.cy;
|
|
dbmi.hpal = 0;
|
|
dbmi.fl = BMF_TOPDOWN;
|
|
|
|
SURFMEM SurfDimo;
|
|
SurfDimo.bCreateDIB(&dbmi, pengbrush->pjPat);
|
|
|
|
if (!SurfDimo.bValid())
|
|
{
|
|
// hmgr logs out of memory error
|
|
return(FALSE);
|
|
}
|
|
|
|
ptlSrc.x = 0;
|
|
ptlSrc.y = 0;
|
|
|
|
rclDst.left = 0;
|
|
rclDst.top = 0;
|
|
rclDst.right = sizlPat.cx;
|
|
rclDst.bottom = sizlPat.cy;
|
|
|
|
while (rclDst.left != cxPatRealized)
|
|
{
|
|
EngCopyBits(
|
|
SurfDimo.pSurfobj(), // Target surface
|
|
pSurfPat->pSurfobj(), // Source surface
|
|
(CLIPOBJ *) NULL, // Clip through this
|
|
pxlo, // Color translation
|
|
&rclDst, // Target offset and extent
|
|
&ptlSrc);
|
|
|
|
rclDst.left = rclDst.right;
|
|
rclDst.right += sizlPat.cx;
|
|
if (rclDst.right > cxPatRealized)
|
|
rclDst.right = cxPatRealized;
|
|
}
|
|
|
|
//
|
|
// Set up the Msk part.
|
|
//
|
|
if (pSurfMsk == (PSURFACE) NULL)
|
|
{
|
|
//
|
|
// Flag that there's no mask.
|
|
//
|
|
pengbrush->pjMsk = (PBYTE) NULL;
|
|
}
|
|
else
|
|
{
|
|
pengbrush->lDeltaMsk = cjScanMsk;
|
|
pengbrush->cxMskR = cxMskRealized;
|
|
pengbrush->cxMsk = sizlMsk.cx;
|
|
pengbrush->cyMsk = sizlMsk.cy;
|
|
pengbrush->pjMsk = pengbrush->aj + ulSizePat;
|
|
|
|
dbmi.iFormat = BMF_1BPP;
|
|
dbmi.cxBitmap = cxMskRealized;
|
|
dbmi.cyBitmap = sizlMsk.cy;
|
|
dbmi.hpal = (HPALETTE)0;
|
|
dbmi.fl = BMF_TOPDOWN;
|
|
|
|
SURFMEM SurfDimo;
|
|
SurfDimo.bCreateDIB(&dbmi, pengbrush->pjMsk);
|
|
|
|
if (!SurfDimo.bValid())
|
|
{
|
|
// hmgr logs out of memory error
|
|
return(FALSE);
|
|
}
|
|
|
|
ptlSrc.x = 0;
|
|
ptlSrc.y = 0;
|
|
|
|
rclDst.left = 0;
|
|
rclDst.top = 0;
|
|
rclDst.right = sizlMsk.cx;
|
|
rclDst.bottom = sizlMsk.cy;
|
|
|
|
while (rclDst.left != cxMskRealized)
|
|
{
|
|
EngCopyBits(
|
|
SurfDimo.pSurfobj(), // target surface
|
|
pSurfMsk->pSurfobj(), // source surface
|
|
(CLIPOBJ *) NULL, // no clipping
|
|
NULL, // no color translation
|
|
&rclDst, // target offset and extent
|
|
&ptlSrc // source start point
|
|
);
|
|
|
|
rclDst.left = rclDst.right;
|
|
rclDst.right += sizlMsk.cx;
|
|
if (rclDst.right > cxMskRealized)
|
|
{
|
|
rclDst.right = cxMskRealized;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|