|
|
/******************************Module*Header*******************************\
* Module Name: patblt.cxx * * This contains the special case blting code for P, Pn, DPx and Dn rops * with solid color and patterns. * * Created: 03-Mar-1991 22:01:14 * Author: Patrick Haluptzok patrickh * * Copyright (c) 1991-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
// The amount to shift cx and xDstStart left by
ULONG aulShiftFormat[7] = { 0, // BMF_DEVICE
0, // BMF_1BPP
2, // BMF_4BPP
3, // BMF_8BPP
4, // BMF_16BPP
0, // BMF_24BPP
5 // BMF_32BPP
};
PFN_PATBLT apfnPatBlt[][3] = { { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { vPatCpyRect8, vPatNotRect8, vPatXorRect8 }, { vPatCpyRect8, vPatNotRect8, vPatXorRect8 }, { vPatCpyRect8, vPatNotRect8, vPatXorRect8 }, { vPatCpyRect8, vPatNotRect8, vPatXorRect8 } };
ULONG aulMulFormat[] = { 0, // BMF_DEVICE
0, // BMF_1BPP
0, // BMF_4BPP
1, // BMF_8BPP
2, // BMF_16BPP
3, // BMF_24BPP
4 // BMF_32BPP
};
/******************************Public*Routine******************************\
* vDIBSolidBlt * * This does solid color and DstInvert blts. * * History: * 03-Feb-1992 -by- Donald Sidoroff [donalds] * Improved it. * * 01-Mar-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
VOID vDIBSolidBlt( SURFACE *pSurfDst, RECTL *prclDst, CLIPOBJ *pco, ULONG iColor, // the index to use for color.
BOOL bInvert) { PFN_SOLIDBLT pfnDibSolid; ULONG cShift; // Shift by this for format conversion
ULONG ircl; PBYTE pjDstBits; LONG lDeltaDst; BOOL bMore = FALSE; BOOL bClip = FALSE; CLIPENUMRECT clenr;
//ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibSo");
// Set ircl to be the format of the dst surface.
ircl = pSurfDst->iFormat();
// Assert the world is in order for our switch
ASSERTGDI((ircl >= BMF_1BPP) && (ircl <= BMF_32BPP), "ERROR GDI vDibPatBlt");
// Set up cShift, pfnDibSolid, and iColor.
cShift = aulShiftFormat[ircl];
if (bInvert) { if (ircl == BMF_24BPP) pfnDibSolid = vSolidXorRect24; else pfnDibSolid = vSolidXorRect1; } else { if (ircl == BMF_24BPP) pfnDibSolid = vSolidFillRect24; else pfnDibSolid = vSolidFillRect1; }
// Note cascaded fall through on switch to build up iColor.
// Also note that 24BPP doesn't change.
// Finally, note that the non-significant bits have to be masked off because
// we generate Pn in the calling routine with ~.
switch(ircl) { case BMF_1BPP:
if ((iColor &= 1) != 0) iColor = 0xFFFFFFFF; break;
case BMF_4BPP:
iColor &= 0x0F; iColor = iColor | (iColor << 4);
case BMF_8BPP:
iColor &= 0xFF; iColor = iColor | (iColor << 8);
case BMF_16BPP:
iColor &= 0xFFFF; iColor = iColor | (iColor << 16); }
if (pco != (CLIPOBJ *) NULL) { switch(pco->iDComplexity) { case DC_TRIVIAL: break; case DC_RECT: bClip = TRUE; clenr.c = 1; clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
break; case DC_COMPLEX: bClip = TRUE; bMore = TRUE; ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,CD_ANY,CLIPOBJ_ENUM_LIMIT); break; default: RIP("ERROR: vDIBSolidBlt - bad clipping type"); } }
pjDstBits = (PBYTE) pSurfDst->pvScan0(); lDeltaDst = pSurfDst->lDelta();
if (!bClip) { (*pfnDibSolid)( prclDst, 1, pjDstBits, lDeltaDst, iColor, cShift); } else do { if (bMore) bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
for (ircl = 0; ircl < clenr.c; ircl++) { PRECTL prcl = &clenr.arcl[ircl];
if (prcl->left < prclDst->left) prcl->left = prclDst->left;
if (prcl->right > prclDst->right) prcl->right = prclDst->right;
if (prcl->top < prclDst->top) prcl->top = prclDst->top;
if (prcl->bottom > prclDst->bottom) prcl->bottom = prclDst->bottom;
// We check for NULL or inverted rectanges because we may get them.
if ((prcl->top < prcl->bottom) && (prcl->left < prcl->right)) { (*pfnDibSolid)( prcl, 1, pjDstBits, lDeltaDst, iColor, cShift); }
} } while (bMore); }
/******************************Public*Routine******************************\
* vDIBPatBlt * * This does pattern blts * * History: * 20-Jan-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/
VOID vDIBPatBlt( SURFACE *pSurfDst, CLIPOBJ *pco, RECTL *prclDst, BRUSHOBJ *pbo, POINTL *pptlBrush, ULONG iMode) { PFN_PATBLT pfnPat; PATBLTFRAME pbf; CLIPENUMRECT clenr; ULONG ircl; BOOL bMore = FALSE; BOOL bClip = FALSE;
ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
// Set ircl to be the format of the dst surface.
ircl = pSurfDst->iFormat();
// Assert the world is in order for our switch
ASSERTGDI((ircl >= BMF_1BPP) && (ircl <= BMF_32BPP), "ERROR GDI vDibPatBlt");
// Set up pfnPat and cMul.
pfnPat = apfnPatBlt[ircl][iMode]; pbf.cMul = aulMulFormat[ircl];
if (pco != (CLIPOBJ *) NULL) { switch(pco->iDComplexity) { case DC_TRIVIAL: break; case DC_RECT: bClip = TRUE; clenr.c = 1; clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
break; case DC_COMPLEX: bClip = TRUE; bMore = TRUE; ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,CD_ANY,CLIPOBJ_ENUM_LIMIT); break; default: RIP("ERROR: vDibPatBlt - bad clipping type"); } }
pbf.pvTrg = pSurfDst->pvScan0(); pbf.lDeltaTrg = pSurfDst->lDelta(); pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat; pbf.lDeltaPat = ((EBRUSHOBJ *) pbo)->pengbrush()->lDeltaPat; pbf.cxPat = ((EBRUSHOBJ *) pbo)->pengbrush()->cxPat * pbf.cMul; pbf.cyPat = ((EBRUSHOBJ *) pbo)->pengbrush()->cyPat; pbf.xPat = pptlBrush->x * pbf.cMul; pbf.yPat = pptlBrush->y;
if (!bClip) { pbf.pvObj = (PVOID) prclDst; (*pfnPat)(&pbf); } else do { if (bMore) bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
for (ircl = 0; ircl < clenr.c; ircl++) { PRECTL prcl = &clenr.arcl[ircl];
if (prcl->left < prclDst->left) prcl->left = prclDst->left;
if (prcl->right > prclDst->right) prcl->right = prclDst->right;
if (prcl->top < prclDst->top) prcl->top = prclDst->top;
if (prcl->bottom > prclDst->bottom) prcl->bottom = prclDst->bottom;
// We check for NULL or inverted rectanges because we may get them.
if ((prcl->top < prcl->bottom) && (prcl->left < prcl->right)) { pbf.pvObj = (PVOID) prcl; (*pfnPat)(&pbf); } } } while (bMore); }
/******************************Public*Routine******************************\
* vDIBPatBltSrccopy8x8 * * This does only SRCCOPY blts of 8x8 patterns to DIBs. * lDelta for the pattern must be exactly # of bytes per pixel * 8. * * History: * 07-Nov-1992 -by- Michael Abrash [mikeab] * Wrote it. \**************************************************************************/
VOID vDIBPatBltSrccopy8x8( SURFACE *pSurfDst, CLIPOBJ *pco, RECTL *prclDst, BRUSHOBJ *pbo, POINTL *pptlBrush, PFN_PATBLT2 pfnPat) { PATBLTFRAME pbf; CLIPENUMRECT clenr; BOOL bMore; PRECTL prcl; INT ircl;
// Assert this is the right sort of destination
ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
pbf.pvTrg = pSurfDst->pvScan0(); pbf.lDeltaTrg = pSurfDst->lDelta(); pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat; pbf.lDeltaPat = ((EBRUSHOBJ *) pbo)->pengbrush()->lDeltaPat;
//
// Force the X and Y pattern origin coordinates into the ranges 0-7 and 0-7,
// so we don't have to do modulo arithmetic all over again at a lower level
//
pbf.xPat = pptlBrush->x & 0x07; pbf.yPat = pptlBrush->y & 0x07;
if (pco == (CLIPOBJ *) NULL) {
// Unclipped
pbf.pvObj = (PVOID) prclDst; pfnPat(&pbf, 1); return; } else { switch(pco->iDComplexity) { case DC_TRIVIAL: // unclipped
pbf.pvObj = (PVOID) prclDst; pfnPat(&pbf, 1); return;
case DC_RECT: // rectangle clipped
clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
// Clip the destination rectangle to the clip rectangle; it's
// guaranteed that the resulting rectangle will never be null
if (clenr.arcl[0].left <= prclDst->left) clenr.arcl[0].left = prclDst->left;
if (clenr.arcl[0].right >= prclDst->right) clenr.arcl[0].right = prclDst->right;
if (clenr.arcl[0].top <= prclDst->top) clenr.arcl[0].top = prclDst->top;
if (clenr.arcl[0].bottom >= prclDst->bottom) clenr.arcl[0].bottom = prclDst->bottom;
if ((clenr.arcl[0].left < clenr.arcl[0].right) && (clenr.arcl[0].top < clenr.arcl[0].bottom)) { pbf.pvObj = (PVOID) clenr.arcl; pfnPat(&pbf, 1); }
return;
case DC_COMPLEX: // complex region clipped
((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, CLIPOBJ_ENUM_LIMIT);
do {
// Get the next batch of rectangles in the clip region
bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
// If there are any rectangles in this enumeration, clip the
// destination rectangle to each clip region rectangle, then
// fill all the rectangles at once
if (clenr.c > 0) {
// Clip the rectangles
for (ircl = 0, prcl = clenr.arcl; ircl < (INT) clenr.c; ircl++, prcl++) { if (prcl->left < prclDst->left) prcl->left = prclDst->left;
if (prcl->right > prclDst->right) prcl->right = prclDst->right;
if (prcl->top < prclDst->top) prcl->top = prclDst->top;
if (prcl->bottom > prclDst->bottom) prcl->bottom = prclDst->bottom;
//
// make sure rectangle is not inverted,
// this can happen for single scan line
// clip regions clipped to dst. If found,
// set to NULL rectangle
//
if (prcl->right < prcl->left) { prcl->right = prcl->left; }
if (prcl->bottom < prcl->top) { prcl->bottom = prcl->top; }
}
// Draw the rectangles
pbf.pvObj = (PVOID) clenr.arcl; pfnPat(&pbf, (INT) clenr.c); }
} while (bMore);
return;
default: RIP("ERROR: vDIBPatBltSrccopy8x8 - bad clipping type"); } } }
/******************************Public*Routine******************************\
* vDIBnPatBltSrccopy6x6 * * This does SRCCOPY pattern blts to 6x6 4-bpp DIBs and 1-bpp DIBs. * lDelta for the pattern must be exactly 6 pixels (4 bytes). * * History: * 07-Nov-1992 -by- Michael Abrash [mikeab] * Wrote it. * * 17-Nov-1992 -by- Stephen Estrop [StephenE] * Made it take a pointer to a \**************************************************************************/
VOID vDIBnPatBltSrccopy6x6( SURFACE *pSurfDst, CLIPOBJ *pco, RECTL *prclDst, BRUSHOBJ *pbo, POINTL *pptlBrush, PFN_PATBLT2 pfnPatBlt) { PATBLTFRAME pbf; CLIPENUMRECT clenr; BOOL bMore; PRECTL prcl; ULONG ircl;
// Assert this is the right sort of destination
ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
pbf.pvTrg = pSurfDst->pvScan0(); pbf.lDeltaTrg = pSurfDst->lDelta(); pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat;
// Force the X and Y pattern origin coordinates into the ranges 0-5 and 0-5,
// so we don't have to do modulo arithmetic all over again at a lower level
if (pptlBrush->x >= 0) pbf.xPat = pptlBrush->x % 0x06; else pbf.xPat = (6 - 1) - ((-pptlBrush->x - 1) % 6);
if (pptlBrush->y >= 0) pbf.yPat = pptlBrush->y % 0x06; else pbf.yPat = (6 - 1) - ((-pptlBrush->y - 1) % 6);
if (pco == (CLIPOBJ *) NULL) {
// Unclipped
pbf.pvObj = (PVOID) prclDst; (*pfnPatBlt)(&pbf, 1); return; } else { switch(pco->iDComplexity) { case DC_TRIVIAL: // unclipped
pbf.pvObj = (PVOID) prclDst; (*pfnPatBlt)(&pbf, 1); return;
case DC_RECT: // rectangle clipped
clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
// Clip the destination rectangle to the clip rectangle
if (clenr.arcl[0].left <= prclDst->left) clenr.arcl[0].left = prclDst->left;
if (clenr.arcl[0].right >= prclDst->right) clenr.arcl[0].right = prclDst->right;
if (clenr.arcl[0].top <= prclDst->top) clenr.arcl[0].top = prclDst->top;
if (clenr.arcl[0].bottom >= prclDst->bottom) clenr.arcl[0].bottom = prclDst->bottom;
if ((clenr.arcl[0].left < clenr.arcl[0].right) && (clenr.arcl[0].top < clenr.arcl[0].bottom)) { pbf.pvObj = (PVOID) clenr.arcl; (*pfnPatBlt)(&pbf, 1); }
return;
case DC_COMPLEX: // complex region clipped
((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, CLIPOBJ_ENUM_LIMIT);
do {
// Get the next batch of rectangles in the clip region
bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
// If there are any rectangles in this enumeration, clip the
// destination rectangle to each clip region rectangle, then
// fill all the rectangles at once
if (clenr.c > 0) {
// Clip the rectangles
for (ircl = 0, prcl = clenr.arcl; ircl < clenr.c; ircl++, prcl++) { if (prcl->left < prclDst->left) prcl->left = prclDst->left;
if (prcl->right > prclDst->right) prcl->right = prclDst->right;
if (prcl->top < prclDst->top) prcl->top = prclDst->top;
if (prcl->bottom > prclDst->bottom) prcl->bottom = prclDst->bottom; }
// Draw the rectangles
pbf.pvObj = (PVOID) clenr.arcl; (*pfnPatBlt)(&pbf, clenr.c); }
} while (bMore);
return;
default: RIP("ERROR: vDIBnSrccopyPatBlt - bad clipping type"); } } }
|