|
|
/******************************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; } } }
|