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.
633 lines
18 KiB
633 lines
18 KiB
/******************************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");
|
|
}
|
|
}
|
|
}
|
|
|