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.
 
 
 
 
 
 

870 lines
20 KiB

/******************************Module*Header*******************************\
* Module Name: solid.cxx
*
* This contains the special case blting code for P, Pn, DPx and Dn rops
* with solid colors.
*
* Created: 03-Mar-1991 22:01:14
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1991-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
// Array of masks for blting
ULONG aulMsk[] =
{
0xFFFFFFFF,
0xFFFFFF7F,
0xFFFFFF3F,
0xFFFFFF1F,
0xFFFFFF0F,
0xFFFFFF07,
0xFFFFFF03,
0xFFFFFF01,
0xFFFFFF00,
0xFFFF7F00,
0xFFFF3F00,
0xFFFF1F00,
0xFFFF0F00,
0xFFFF0700,
0xFFFF0300,
0xFFFF0100,
0xFFFF0000,
0xFF7F0000,
0xFF3F0000,
0xFF1F0000,
0xFF0F0000,
0xFF070000,
0xFF030000,
0xFF010000,
0xFF000000,
0x7F000000,
0x3F000000,
0x1F000000,
0x0F000000,
0x07000000,
0x03000000,
0x01000000,
};
#define DBG_SOLID 0
#if DBG_SOLID
ULONG DbgSolid = 0;
#endif
/******************************Public*Routine******************************\
* vSolidFillRect1
*
* Does a solid blt to a DIB of 1, 4, 8, 16 or 32 bpp.
*
* History:
*
* 17-Nov-1992 -by- Jim Thomas [jimt]
* Change call to work on list of rectangles.
* Change center loop to call RtlFillMemory only for wide
* scan lines
*
* 03-Feb-1992 -by- Donald Sidoroff [donalds]
* Rewrote it.
*
* 01-Mar-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID vSolidFillRect1(
PRECTL prcl,
ULONG cRcl,
PBYTE pjDst,
LONG lDeltaDst,
ULONG iColor,
ULONG cShift)
{
ULONG ulMskLeft;
ULONG ulMskRight;
ULONG cLeft;
ULONG cRight;
ULONG cxDword;
ULONG yRow;
ULONG ulColor;
PULONG pulTmp;
PULONG pulDst;
ULONG cx;
ULONG cy;
ULONG xDstStart;
#if DBG_SOLID
if (DbgSolid >= 1) {
DbgPrint("SolidFillRect1:\n");
DbgPrint(" pjDst = 0x%08lx\n",pjDst);
if (DbgSolid >= 2) {
DbgPrint(" prcl = 0x%08lx\n",prcl);
DbgPrint(" cRcl = %li\n",cRcl);
DbgPrint(" lDeltaDst = %li\n",lDeltaDst);
DbgPrint(" iColor = 0x%08lx\n",iColor);
DbgPrint(" cShift = %li\n",cShift);
}
}
#endif
//
// loop through each rectangle
//
for ( ;cRcl > 0;cRcl--, prcl++ )
{
//
// make sure rectangle is well ordered
//
ASSERTGDI(prcl != NULL,"ERROR: prcl = NULL");
ASSERTGDI(prcl->right > prcl->left,"ERROR: left >= right");
ASSERTGDI(prcl->bottom > prcl->top, "ERROR: top >= bottom");
#if DBG_SOLID
if (DbgSolid >= 1) {
DbgPrint(" Rect: %li,%li to %li,%li\n",
prcl->left,prcl->top,
prcl->right,prcl->bottom);
}
#endif
pulDst = (PULONG)(pjDst + prcl->top * lDeltaDst);
cy = prcl->bottom - prcl->top;
//
// cx is the number of bits in the scan line to fill
//
cx = (prcl->right - prcl->left) << cShift;
//
// Starting bit
//
xDstStart = prcl->left << cShift;
//
// starting and ending DWORD offset
//
cLeft = xDstStart >> 5;
cRight = (xDstStart + cx) >> 5;
//
// generate left and right bit masks
//
ulMskLeft = aulMsk[xDstStart & 0x1f];
ulMskRight = aulMsk[(xDstStart+cx) & 0x1f];
//
// if cLeft equals cRight then onyl 1 DWORD needs to be modified,
// combine left and right masks. Do entire strip.
//
if (cLeft == cRight) {
ulMskLeft &= ~ulMskRight;
ulColor = iColor & ulMskLeft;
ulMskLeft = ~ulMskLeft;
pulTmp = pulDst + cLeft;
while (cy--) {
*pulTmp = (*pulTmp & ulMskLeft) | ulColor;
pulTmp = (PULONG)((PBYTE)pulTmp + lDeltaDst);
}
} else {
//
// do solid fill in three portions,
//
// left edge (partial DWORD)
// center (full DWORD)
// right edge (partial DWORD)
//
//
// left strip
//
if (ulMskLeft != ~0) {
pulTmp = pulDst + cLeft;
ulColor = iColor & ulMskLeft;
ulMskLeft = ~ulMskLeft;
yRow = cy;
while (yRow--) {
*pulTmp = (*pulTmp & ulMskLeft) | ulColor;
pulTmp = (PULONG)((PBYTE)pulTmp + lDeltaDst);
}
cLeft++;
}
//
// center calc number of DWORDS
//
cxDword = cRight - cLeft;
pulTmp = pulDst + cLeft;
if (cxDword != 0) {
yRow = cy;
while (yRow--) {
switch (cxDword) {
case 7:
*(pulTmp+6) = iColor;
case 6:
*(pulTmp+5) = iColor;
case 5:
*(pulTmp+4) = iColor;
case 4:
*(pulTmp+3) = iColor;
case 3:
*(pulTmp+2) = iColor;
case 2:
*(pulTmp+1) = iColor;
case 1:
*(pulTmp) = iColor;
break;
default:
RtlFillMemoryUlong((PVOID)pulTmp,cxDword<<2,iColor);
}
pulTmp = (PULONG)((PBYTE)pulTmp + lDeltaDst);
}
}
//
// right edge
//
if (ulMskRight != ~0) {
pulTmp = pulDst + cRight;
ulColor = iColor & ~ulMskRight;
while (cy--) {
*pulTmp = (*pulTmp & ulMskRight) | ulColor;
pulTmp = (PULONG)((PBYTE)pulTmp + lDeltaDst);
}
}
}
}
}
/******************************Public*Routine******************************\
* vSolidFillRect24
*
* Does a solid blt to a 24 bpp DIB.
*
* History:
*
* 17-Nov-1992 -by- Jim Thomas [jimt]
* Change call to list of rects
*
* 02-Mar-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID vSolidFillRect24(
PRECTL prcl,
ULONG cRcl,
PBYTE pjDst,
LONG lDeltaDst,
ULONG iColor,
ULONG cShift)
{
PBYTE pjDstRow;
BYTE jRed,jGreen,jBlue;
ULONG cxTemp;
ULONG cx;
ULONG cy;
LONG lDelta;
DONTUSE(cShift);
//
// place any asserts here
//
jRed = (BYTE)iColor;
jGreen = (BYTE)(iColor >> 8);
jBlue = (BYTE)(iColor >> 16);
//
// loop through each rectangle
//
for ( ;cRcl > 0;cRcl--, prcl++ )
{
pjDstRow = pjDst + (prcl->top * lDeltaDst) + 3 * prcl->left;
cy = prcl->bottom - prcl->top;
cx = prcl->right - prcl->left;
//
// lDelta is adjusted to go from the end of one scan
// line to the start of the next.
//
lDelta = lDeltaDst - 3*cx;
while (cy--) {
cxTemp = cx;
while (cxTemp--) {
*(pjDstRow) = jRed;
*(pjDstRow+1) = jGreen;
*(pjDstRow+2) = jBlue;
pjDstRow += 3;
}
pjDstRow += lDelta;
}
}
}
/******************************Public*Routine******************************\
* vSolidXorRect1
*
* Does an xor blt to a DIB or 1, 4, 8, 16 or 32 bpp.
*
* History:
*
* 17-Nov-1992 -by- Jim Thomas [jimt]
* Change call to list of rects
*
*
* 03-Feb-1992 -by- Donald Sidoroff [donalds]
* Rewrote it.
*
* 01-Mar-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID vSolidXorRect1(
PRECTL prcl,
ULONG cRcl,
PBYTE pjDst,
LONG lDeltaDst,
ULONG iColor,
ULONG cShift)
{
ULONG ulMskLeft;
ULONG ulMskRight;
ULONG iLeft;
ULONG iRight;
ULONG cLeft;
ULONG cRight;
ULONG culFill;
ULONG yRow;
PULONG pulTmp;
PULONG pulDst;
ULONG cx;
ULONG cy;
ULONG xDstStart;
BOOL bSimple;
#if DBG_SOLID
if (DbgSolid >= 1) {
DbgPrint("SolidXorRect1:\n");
DbgPrint(" pjDst = 0x%08lx\n",pjDst);
if (DbgSolid >= 2) {
DbgPrint(" prcl = 0x%08lx\n",prcl);
DbgPrint(" cRcl = %li\n",cRcl);
DbgPrint(" lDeltaDst = %li\n",lDeltaDst);
DbgPrint(" iColor = 0x%08lx\n",iColor);
DbgPrint(" cShift = %li\n",cShift);
}
}
#endif
//
// loop through each rectangle
//
for ( ; cRcl > 0;cRcl--, prcl++ )
{
//
// init rect params
//
ASSERTGDI(prcl != NULL,"ERROR: prcl = NULL");
ASSERTGDI(prcl->right > prcl->left,"ERROR: left >= right");
ASSERTGDI(prcl->bottom > prcl->top, "ERROR: top >= bottom");
pulDst = (PULONG)(pjDst + prcl->top * lDeltaDst);
cx = (prcl->right - prcl->left) << cShift;
cy = prcl->bottom - prcl->top;
xDstStart = (prcl->left << cShift);
//
// calc index of leftmost and rightmost DWORDS
//
cLeft = xDstStart >> 5;
cRight = (xDstStart + cx) >> 5;
//
// calc number of bits used in leftmost and rightmost DWORDs
//
iLeft = xDstStart & 31;
iRight = (xDstStart + cx) & 31;
//
// generate DWORD store masks
//
ulMskLeft = aulMsk[iLeft];
ulMskRight = ~aulMsk[iRight];
//
// If the leftmost and rightmost DWORDs are the same, then only one
// strip is needed. Merge the two masks together and note this.
//
bSimple = FALSE;
if (cLeft == cRight)
{
ulMskLeft &= ulMskRight;
bSimple = TRUE;
}
#if DBG_SOLID
if (DbgSolid >= 1) {
DbgPrint(" Rect: %li,%li to %li,%li\n",
prcl->left,prcl->top,
prcl->right,prcl->bottom);
}
#endif
//
// Lay down the left edge, if needed.
//
if (bSimple || (iLeft != 0))
{
pulTmp = pulDst + cLeft;
ulMskLeft &= iColor;
for (yRow = 0; yRow != cy; yRow++)
{
*pulTmp ^= ulMskLeft;
pulTmp = (ULONG *) ((BYTE *) pulTmp + lDeltaDst);
}
cLeft++;
}
if (!bSimple) {
//
// Lay down the center strip, if needed.
//
culFill = cRight - cLeft;
if (culFill != 0)
{
pulTmp = pulDst + cLeft;
for (yRow = 0; yRow != cy; yRow++)
{
cx = culFill;
while (cx--)
*pulTmp++ ^= iColor;
pulTmp -= culFill;
pulTmp = (ULONG *) ((BYTE *) pulTmp + lDeltaDst);
}
}
//
// Lay down the right edge, if needed.
//
if (iRight != 0)
{
pulTmp = pulDst + cRight;
ulMskRight &= iColor;
for (yRow = 0; yRow != cy; yRow++)
{
*pulTmp ^= ulMskRight;
pulTmp = (ULONG *) ((BYTE *) pulTmp + lDeltaDst);
}
}
}
}
}
/******************************Public*Routine******************************\
* vSolidXorRect24
*
* Does a solid blt to a 24 bpp DIB.
*
* History:
*
* 17-Nov-1992 -by- Jim Thomes [jimt]
* change call to list of rects
*
* 03-Feb-1992 -by- Donald Sidoroff [donalds]
* Rewrote it.
*
* 02-Mar-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID vSolidXorRect24(
PRECTL prcl,
ULONG cRcl,
PBYTE pjDst,
LONG lDeltaDst,
ULONG iColor,
ULONG cShift)
{
PBYTE pjDstTmp;
BYTE jRed, jGreen, jBlue;
ULONG cxTemp;
ULONG cx;
ULONG cy;
LONG lDelta;
DONTUSE(cShift);
//
// lDelta is adjusted to go from the end of one scan
// line to the start of the next.
//
jRed = (BYTE) iColor;
jGreen = (BYTE) (iColor >> 8);
jBlue = (BYTE) (iColor >> 16);
for ( ;cRcl > 0;cRcl--, prcl++ )
{
//
// init rect params
//
pjDstTmp = pjDst + prcl->top * lDeltaDst + prcl->left * 3;
cx = prcl->right - prcl->left;
cy = prcl->bottom - prcl->top;
lDelta = lDeltaDst - (3 * cx);
ASSERTGDI(cx != 0, "ERROR vDibSolidBlt32");
ASSERTGDI(cy != 0, "ERROR vDibSolidBlt32");
while(cy--)
{
cxTemp = cx;
while(cxTemp--)
{
*(pjDstTmp) ^= jRed;
*(pjDstTmp+1) ^= jGreen;
*(pjDstTmp+2) ^= jBlue;
pjDstTmp += 3;
}
pjDstTmp = pjDstTmp + lDelta;
}
}
}
/******************************Public*Routine******************************\
* vSolidFillRow1
*
* Blt a list of adjacent rows to a DIB of of 1, 4, 8, 16 or 32 bpp.
*
* History:
* 11-Oct-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
VOID vSolidFillRow1(
PROW prow,
ULONG crow,
LONG yTop,
PBYTE pjBits,
ULONG iColor,
LONG lDelta,
ULONG cShift)
{
pjBits += yTop * lDelta;
for (UINT i = 0; i < crow; i++, prow++, pjBits += lDelta)
{
ULONG *pulDst = (PULONG)pjBits;
LONG cx = (prow->right - prow->left) << cShift;
ULONG xDstStart = prow->left << cShift;
BOOL bSimple = FALSE;
ULONG cLeft = xDstStart >> 5; // Index of leftmost DWORD
ULONG cRght = (xDstStart + cx) >> 5; // Index of rightmost DWORD
ULONG iLeft = xDstStart & 31; // Bits used in leftmost DWORD
ULONG iRght = (xDstStart + cx) & 31; // Bits used in rightmost DWORD
ULONG ulMskLeft = aulMsk[iLeft];
ULONG ulMskRght = ~aulMsk[iRght];
// If the leftmost and rightmost DWORDs are the same, then only one
// strip is needed. Merge the two masks together and note this.
if (cLeft == cRght)
{
ulMskLeft &= ulMskRght;
bSimple = TRUE;
}
// Lay down the left edge, if needed.
if (bSimple || (iLeft != 0))
{
pulDst[cLeft] = (pulDst[cLeft] & ~ulMskLeft) | (iColor & ulMskLeft);
if (bSimple)
continue;
cLeft++;
}
// Lay down the center strip, if needed.
ULONG cjFill = (cRght - cLeft) << 2;
if (cjFill != 0)
RtlFillMemoryUlong((PVOID) (pulDst+cLeft), cjFill, iColor);
// Lay down the right edge, if needed.
if (iRght != 0)
pulDst[cRght] = (pulDst[cRght] & ~ulMskRght) | (iColor & ulMskRght);
}
}
/******************************Public*Routine******************************\
* vSolidFillRow24
*
* Blt a list of adjacent rows to a 24 bpp DIB.
*
* History:
* 12-Oct-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
VOID vSolidFillRow24(
PROW prow,
ULONG crow,
LONG yTop,
PBYTE pjBits,
ULONG iColor,
LONG lDelta,
ULONG cShift)
{
BYTE jRed, jGreen, jBlue;
jRed = (BYTE) iColor;
jGreen = (BYTE) (iColor >> 8);
jBlue = (BYTE) (iColor >> 16);
pjBits += (yTop * lDelta);
for (UINT i = 0; i < crow; i++, prow++, pjBits += lDelta)
{
LONG cx = (prow->right - prow->left) << cShift;
ULONG xDstStart = prow->left << cShift;
BYTE* pjDst = pjBits + (3 * xDstStart);
ULONG cxTemp = cx;
while(cxTemp--)
{
*(pjDst++) = jRed;
*(pjDst++) = jGreen;
*(pjDst++) = jBlue;
}
}
}
/******************************Public*Routine******************************\
* vSolidXorRow1
*
* Does an xor blt of a list of adjacent rows to a DIB or 1, 4, 8, 16 or 32 bpp.
*
* History:
* 12-Oct-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
VOID vSolidXorRow1(
PROW prow,
ULONG crow,
LONG yTop,
PBYTE pjBits,
ULONG iColor,
LONG lDelta,
ULONG cShift)
{
pjBits += yTop * lDelta;
for (UINT i = 0; i < crow; i++, prow++,pjBits += lDelta)
{
ULONG* pulDst = (ULONG *) pjBits;
LONG cx = (prow->right - prow->left) << cShift;
ULONG xDstStart = prow->left << cShift;
ULONG ulMskLeft;
ULONG ulMskRght;
ULONG iLeft;
ULONG iRght;
ULONG cLeft;
ULONG cRght;
ULONG culFill;
BOOL bSimple = FALSE;
cLeft = xDstStart >> 5; // Index of leftmost DWORD
cRght = (xDstStart + cx) >> 5; // Index of rightmost DWORD
iLeft = xDstStart & 31; // Bits used in leftmost DWORD
iRght = (xDstStart + cx) & 31; // Bits used in rightmost DWORD
ulMskLeft = aulMsk[iLeft];
ulMskRght = ~aulMsk[iRght];
// If the leftmost and rightmost DWORDs are the same, then only one
// strip is needed. Merge the two masks together and note this.
if (cLeft == cRght)
{
ulMskLeft &= ulMskRght;
bSimple = TRUE;
}
// Lay down the left edge, if needed.
if (bSimple || (iLeft != 0))
{
ulMskLeft &= iColor;
pulDst[cLeft] ^= ulMskLeft;
if (bSimple)
continue;
cLeft++;
}
// Lay down the center strip, if needed.
culFill = cRght - cLeft;
if (culFill != 0)
{
PULONG pulTmp = pulDst + cLeft;
cx = culFill;
while (cx--)
*pulTmp++ ^= iColor;
}
// Lay down the right edge, if needed.
if (iRght != 0)
{
ulMskRght &= iColor;
pulDst[cRght] ^= ulMskRght;
}
}
}
/******************************Public*Routine******************************\
* vSolidXorRow24
*
* Does a solid blt with a list of adjacent rows to a 24 bpp DIB.
*
* History:
* 12-Oct-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
VOID vSolidXorRow24(
PROW prow,
ULONG crow,
LONG yTop,
PBYTE pjBits,
ULONG iColor,
LONG lDelta,
ULONG cShift)
{
BYTE jRed, jGreen, jBlue;
jRed = (BYTE) iColor;
jGreen = (BYTE) (iColor >> 8);
jBlue = (BYTE) (iColor >> 16);
pjBits += yTop * lDelta;
for (UINT i = 0; i < crow; i++, prow++, pjBits += lDelta)
{
LONG cx = (prow->right - prow->left) << cShift;
ULONG xDstStart = prow->left << cShift;
BYTE* pjDst = pjBits + (3 * xDstStart);
ULONG cxTemp = cx;
while(cxTemp--)
{
*(pjDst++) ^= jRed;
*(pjDst++) ^= jGreen;
*(pjDst++) ^= jBlue;
}
}
}