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.
 
 
 
 
 
 

289 lines
8.0 KiB

/******************************Module*Header*******************************\
* Module Name: Brush.c
*
* Brush support.
*
* Copyright (c) 1992-1993 Microsoft Corporation
*
\**************************************************************************/
#include "driver.h"
/****************************************************************************
* DrvRealizeBrush
***************************************************************************/
BOOL DrvRealizeBrush(
BRUSHOBJ* pbo,
SURFOBJ* psoTarget,
SURFOBJ* psoPattern,
SURFOBJ* psoMask,
XLATEOBJ* pxlo,
ULONG iHatch)
{
RBRUSH* prb; // Pointer to where realization goes
ULONG* pulSrc; // Temporary pointer
ULONG* pulDst; // Temporary pointer
BYTE* pjSrc;
BYTE* pjDst;
ULONG* pulRBits; // Points to RBRUSH pattern bits
BYTE jBkColor;
BYTE jFgColor;
LONG i;
LONG j;
PPDEV ppdev = (PPDEV) psoTarget->dhsurf;
// For now, we only accelerate patterns using the latches, and we
// sometimes need offscreen memory as a temporary work space to
// initialize the latches for 2-color patterns:
if ((ppdev->fl & (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN)) !=
(DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN) )
{
return(FALSE);
}
// We only accelerate 8x8 patterns:
if (psoPattern->sizlBitmap.cx != 8 || psoPattern->sizlBitmap.cy != 8)
return(FALSE);
// We only implement n-color patterns on devices that have multiple
// or separate read/write banks:
if (ppdev->vbtPlanarType == VideoBanked1RW)
return(FALSE);
// We also only handle 1bpp, 4bpp and 8bpp patterns:
if (psoPattern->iBitmapFormat > BMF_8BPP)
return(FALSE);
// At this point, we're definitely going to realize the brush:
prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
if (prb == NULL)
return(FALSE);
pulRBits = &prb->aulPattern[0];
DISPDBG((2, "\n RBrush: "));
// If 8bpp or 4bpp, copy the bitmap to our local buffer:
if (psoPattern->iBitmapFormat == BMF_1BPP)
{
ULONG ulFlippedGlyph;
DISPDBG((2, "1bpp "));
// First, convert the bits to our desired format:
pjSrc = psoPattern->pvScan0;
pulDst = pulRBits;
for (i = 8; i > 0; i--)
{
// We want to take the byte with bits 76543210 and convert it
// to the word 4567012301234567. The pjGlyphFlipTable gives
// us 45670123 from 76543210.
ulFlippedGlyph = (ULONG) ppdev->pjGlyphFlipTable[*pjSrc];
*pulDst = (ulFlippedGlyph << 8) | ((ulFlippedGlyph & 15) << 4) |
(ulFlippedGlyph >> 4);
pulDst++;
pjSrc += psoPattern->lDelta;
}
// Now initialize the rest of the RBrush fields:
prb->xBrush = 0;
prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);
if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
{
prb->fl = RBRUSH_BLACKWHITE;
}
else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
{
// We have to invert the brush:
prb->fl = RBRUSH_BLACKWHITE;
for (i = 0; i < 8; i++)
{
prb->aulPattern[i] = ~prb->aulPattern[i];
}
}
else
{
prb->fl = RBRUSH_2COLOR;
}
return(TRUE);
}
else if (psoPattern->iBitmapFormat == BMF_8BPP)
{
if (pxlo == NULL || pxlo->flXlate & XO_TRIVIAL)
{
pulSrc = psoPattern->pvScan0;
pulDst = pulRBits;
DISPDBG((2, "8bpp noxlate "));
// 8bpp no translate case:
for (i = 4; i > 0; i--)
{
*(pulDst) = *(pulSrc);
*(pulDst + 1) = *(pulSrc + 1);
pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
*(pulDst + 2) = *(pulSrc);
*(pulDst + 3) = *(pulSrc + 1);
pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
pulDst += 4;
}
}
else
{
pjSrc = (BYTE*) psoPattern->pvScan0;
pjDst = (BYTE*) pulRBits;
DISPDBG((2, "8bpp xlate "));
// 8bpp translate case:
for (i = 8; i > 0; i--)
{
for (j = 8; j > 0; j--)
{
*pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc++];
}
pjSrc += psoPattern->lDelta - 8;
}
}
}
else
{
DISPDBG((2, "4bpp xlate "));
ASSERTVGA(psoPattern->iBitmapFormat == BMF_4BPP, "Extra case added?");
// 4bpp case:
pjSrc = (BYTE*) psoPattern->pvScan0;
pjDst = (BYTE*) pulRBits;
for (i = 8; i > 0; i--)
{
// Inner loop is repeated only 4 times because each loop handles
// 2 pixels:
for (j = 4; j > 0; j--)
{
*pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc >> 4];
*pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc & 15];
pjSrc++;
}
pjSrc += psoPattern->lDelta - 4;
}
}
// We want to check if the 4bpp or 8bpp patterns are actually
// only two colors:
if (b2ColorBrush(pulRBits, &jFgColor, &jBkColor))
{
DISPDBG((2, "2 color "));
// ??? We could actually also handle this case even if we have only
// 1 r/w window in planar format:
prb->xBrush = 0;
prb->ulBkColor = (ULONG) jBkColor;
prb->ulFgColor = (ULONG) jFgColor;
prb->fl = RBRUSH_2COLOR;
if (jFgColor == 0x00 && jBkColor == 0xff)
{
// Monochrome brushes always have to have the '0' bits
// as black and the '1' bits as white, so we'll have to
// invert the 1bpp pattern:
prb->fl = RBRUSH_BLACKWHITE;
for (i = 0; i < 8; i++)
{
prb->aulPattern[i] = ~prb->aulPattern[i];
}
}
return(TRUE);
}
prb->fl = RBRUSH_NCOLOR;
prb->cy = 8;
prb->cyLog2 = 3;
// xBrush is the brush alignment for the cached brush, and this value
// will get compared to (pptlBrush->x & 7) to see if the cache brush
// is correctly aligned with the brush requested. Since it will never
// match with -1, the brush will be correctly aligned and placed in
// the cache (which, of course, is what we want to finish our
// initialization):
prb->xBrush = -1;
// Copy those bitmap bits:
// See if pattern is really only 4 scans long:
if (pulRBits[0] == pulRBits[8] && pulRBits[1] == pulRBits[9] &&
pulRBits[2] == pulRBits[10] && pulRBits[3] == pulRBits[11] &&
pulRBits[4] == pulRBits[12] && pulRBits[5] == pulRBits[13] &&
pulRBits[6] == pulRBits[14] && pulRBits[7] == pulRBits[15])
{
prb->cy = 4;
prb->cyLog2 = 2;
// See if pattern is really only 2 scans long:
if (pulRBits[0] == pulRBits[4] && pulRBits[1] == pulRBits[5] &&
pulRBits[2] == pulRBits[6] && pulRBits[3] == pulRBits[7])
{
DISPDBG((2, "cy = 2 "));
prb->cy = 2;
prb->cyLog2 = 1;
}
else
{
DISPDBG((2, "cy = 4 "));
}
}
// See if pattern is really only 4 pels wide:
pulDst = pulRBits;
for (i = prb->cy / 2; i > 0; i--)
{
if (*(pulDst ) != *(pulDst + 1) ||
*(pulDst + 2) != *(pulDst + 3))
goto done_this_realize_brush_stuff;
pulDst += 4;
}
DISPDBG((2, "4pels wide"));
prb->fl |= RBRUSH_4PELS_WIDE;
done_this_realize_brush_stuff:
return(TRUE);
}