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.
 
 
 
 
 
 

515 lines
16 KiB

/******************************Module*Header*******************************\
* Module Name: pixelapi.cxx
*
* This contains the functions that get/set individual pixels.
*
* Created: 25-Apr-1991 11:32:15
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1990-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* GreSetPixel
*
* API entry point for putting a single pixel on the screen.
*
* Returns: -1 if point not in clip rgn or for blt failure,
* or the color put on the device surface for success.
*
* History:
* Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
* update for size/perf and bug fix.
*
* Thu 4-Mar-1992 -by- Kent Diamond [kentd]
* Pass in Attribute cache.
*
* Thu 27-Feb-1992 -by- Patrick Haluptzok [patrickh]
* Fix RGB return.
*
* Thu 05-Dec-1991 -by- Patrick Haluptzok [patrickh]
* bug fix, optimize for size, add error code logging.
*
* Fri 16-Aug-1991 -by- Patrick Haluptzok [patrickh]
* Bug fix, make it return -1 for blt failure, cleanup
*
* 20-Apr-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
DWORD APIENTRY NtGdiSetPixel(HDC hdcDst, int x, int y, COLORREF crColor)
{
PAL_ULONG palul;
palul.ul = 0xFFFFFFFF;
XDCOBJ dcoDst(hdcDst);
if (dcoDst.bValid())
{
//
// Transform the coordinates to device space.
//
EPOINTL eptlDst(x,y);
EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
xoDst.bXform(eptlDst);
ERECTL erclDst(eptlDst.x,eptlDst.y,eptlDst.x+1,eptlDst.y+1);
//
// Accumulate bounds. We can do this before knowing if the operation is
// successful because bounds can be loose.
//
if (dcoDst.fjAccum())
dcoDst.vAccumulate(erclDst);
//
// Check surface is included in DC.
//
if (dcoDst.bHasSurface())
{
//
// Lock the device.
//
DEVLOCKOBJ dloTrg;
if (dloTrg.bLock(dcoDst))
{
SURFACE *pSurfDst = dcoDst.pSurface();
//
// With a fixed DC origin we can change the destination to SCREEN coordinates.
//
erclDst += dcoDst.eptlOrigin();
//
// Parameter validation to avoid sticky overflow errors.
// Note the validation is performed after the transform.
// Any point that starts out in the invalid FIX zone may
// potentially be transformed into the valid range and
// therefore should be plotted.
// Any point that's had it's bottom right wrap will be also invalidated
// by this check.
// Use of BLTOFXOK is probably an overkill, but lower level code
// could potentially do a FIX conversion.
//
if (!BLTOFXOK(erclDst.left) ||
!BLTOFXOK(erclDst.right) ||
!BLTOFXOK(erclDst.top) ||
!BLTOFXOK(erclDst.bottom))
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
//
// XDCOBJ does not automagically clean up it's locks in
// its destructor so we have do it explicitly here.
//
dcoDst.vUnlockFast();
return (DWORD)(GDI_ERROR); //fail
}
ECLIPOBJ *pco = NULL;
//
// This is a pretty knarly expression to save a return in here.
// Basically pco can be NULL if the rect is completely in the
// cached rect in the DC or if we set up a clip object that isn't empty.
//
if (((erclDst.left >= dcoDst.prclClip()->left) &&
(erclDst.right <= dcoDst.prclClip()->right) &&
(erclDst.top >= dcoDst.prclClip()->top) &&
(erclDst.bottom <= dcoDst.prclClip()->bottom)) ||
(pco = dcoDst.pco(),
pco->vSetup(dcoDst.prgnEffRao(), erclDst,CLIP_NOFORCETRIV),
!pco->erclExclude().bEmpty()))
{
//
// Make a fake solid color brush for this guy.
//
XEPALOBJ palDst(pSurfDst->ppal());
XEPALOBJ palDstDC(dcoDst.ppal());
BBRUSHOBJ bo;
BOOL bCMYKColor = dcoDst.pdc->bIsCMYKColor();
//
// Initialize BRUSHOBJ on stack.
//
bo.pvRbrush = (PVOID) NULL;
bo.flColorType = 0;
//
// if the in CMYK color mode, iSolidColor is CMYK color.
//
if (bCMYKColor)
{
bo.iSolidColor = crColor;
bo.flColorType = (BR_CMYKCOLOR | BR_HOST_ICM);
if (gbMultiMonMismatchColor)
{
bo.crRealized(crColor);
bo.crDCPalColor(crColor);
}
}
else
{
bo.iSolidColor = ulGetNearestIndexFromColorref(palDst, palDstDC, crColor);
if (dcoDst.pdc->bIsSoftwareICM())
{
bo.flColorType = BR_HOST_ICM;
}
else if (dcoDst.pdc->bIsDeviceICM())
{
bo.flColorType = BR_DEVICE_ICM;
}
if (gbMultiMonMismatchColor)
{
bo.crRealized(crColor);
bo.crDCPalColor(rgbFromColorref(palDst, palDstDC, crColor));
}
}
//
// Set up the correct return value.
//
DEVEXCLUDEOBJ dxo(dcoDst,&erclDst,pco);
INC_SURF_UNIQ(pSurfDst);
ULONG rop4 = gaMix[dcoDst.pdc->jROP2() & 0x0F];
rop4 |= (rop4 << 8);
if ((*(pSurfDst->pfnBitBlt()))
(
pSurfDst->pSurfobj(),
(SURFOBJ *) NULL,
(SURFOBJ *) NULL,
NULL,
NULL,
&erclDst,
(POINTL *) NULL,
(POINTL *) NULL,
&bo,
&dcoDst.pdc->ptlFillOrigin(),
rop4
))
{
if (bCMYKColor)
{
palul.ul = bo.iSolidColor;
}
else
{
palul.ul = ulIndexToRGB(palDst, palDstDC, bo.iSolidColor);
}
}
}
}
}
dcoDst.vUnlockFast();
}
else
{
WARNING1("ERROR GreSetPixel called on invalid DC\n");
}
return(palul.ul);
}
#if 0
/******************************Public*Routine******************************\
* EngGetPixel
*
* This facilitates GetPixel on DIBs.
*
* History:
* 27-Apr-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG EngGetPixel(
SURFACE *pSurfSrc,
PPOINTL pptlSrc)
{
ULONG ulReturn;
PBYTE pjBits;
LONG lDelta;
ASSERTGDI(pSurfSrc != (PDIBOBJ) NULL, "ERROR GDI EngCopyBits");
ASSERTGDI(pptlSrc != (PPOINTL) NULL, "ERROR GDI EngCopyBits");
ASSERTGDI(pSurfSrc->iType() == STYPE_BITMAP, "ERROR GDI EngCopyBits");
ASSERTGDI(pptlSrc->x < pSurfSrc->sizl().cx, "ERROR GDI EngCopyBits");
ASSERTGDI(pptlSrc->y < pSurfSrc->sizl().cy, "ERROR GDI EngCopyBits");
lDelta = pSurfSrc->lDelta();
pjBits = (PBYTE) pSurfSrc->pvScan0();
pjBits = pjBits + (lDelta * pptlSrc->y);
// Synchronize with the device driver before touching the device surface.
{
PDEVOBJ po(pSurfSrc->hdev());
po.vSync(pSurfSrc,NULL,0);
}
switch(pSurfSrc->iFormat())
{
case BMF_1BPP:
// Get the correct byte.
ulReturn = (ULONG) *(pjBits + (pptlSrc->x >> 3));
// Get the correct bit in the lowest bit.
ulReturn = ulReturn >> (7 - (pptlSrc->x & 7));
// Mask off the top bits.
ulReturn = ulReturn & 1;
break;
case BMF_4BPP:
// Get the correct byte.
ulReturn = (ULONG) *(pjBits + (pptlSrc->x >> 1));
if (pptlSrc->x & 1)
ulReturn = ulReturn & 15;
else
ulReturn = ulReturn >> 4;
ASSERTGDI(ulReturn < 16, "ERROR GDI EngCopyBits");
break;
case BMF_8BPP:
ulReturn = (ULONG) *(pjBits + pptlSrc->x);
break;
case BMF_16BPP:
ulReturn = (ULONG) *((PUSHORT) (pjBits + (pptlSrc->x << 1)));
break;
case BMF_24BPP:
pjBits += (pptlSrc->x * 3);
ulReturn = (ULONG) *(pjBits + 2);
ulReturn <<= 8;
ulReturn |= ((ULONG) *(pjBits + 1));
ulReturn <<= 8;
ulReturn |= ((ULONG) *pjBits);
break;
case BMF_32BPP:
ulReturn = *((PULONG) (pjBits + (pptlSrc->x << 2)));
break;
default:
RIP("ERROR GDI EngCopyBits1");
}
return(ulReturn);
}
#endif
/******************************Public*Routine******************************\
* GreGetPixel
*
* API entry point for getting a single pixel on the screen.
*
* Returns: -1 if point not in clip rgn or for blt failure,
* the RGB color put on the device surface for success.
*
* History:
* Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
* update for size/perf and bug fix.
*
* Thu 27-Feb-1992 -by- Patrick Haluptzok [patrickh]
* Fix RGB return, remove unnecesary work.
*
* 22-Apr-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
DWORD NtGdiGetPixel(HDC hdc, int x, int y)
{
//
// Lock the destination and its transform.
//
DWORD iSolidColor = 0xFFFFFFFF;
XDCOBJ dcoSrc(hdc);
if (dcoSrc.bValid())
{
//
// Lock the Rao region if we are drawing on a display surface. The Rao
// region might otherwise change asynchronously. The DEVLOCKOBJ also makes
// sure that the VisRgn is up to date, calling the window manager if
// necessary to recompute it. It also protects us from pSurfSrc
// being changed asynchronously by a dynamic mode change.
//
DEVLOCKOBJ dlo;
if (dlo.bLock(dcoSrc))
{
//
// Check we can really do a GetPixel on this device.
//
SURFACE *pSurfSrc = dcoSrc.pSurface();
if ((pSurfSrc != NULL) &&
(pSurfSrc->bReadable() || UserScreenAccessCheck()))
{
EXFORMOBJ xoSrc(dcoSrc, WORLD_TO_DEVICE);
//
// Transform the coordinates to device space.
//
EPOINTL eptlSrc(x,y);
xoSrc.bXform(eptlSrc);
ERECTL erclSrc(eptlSrc.x,eptlSrc.y,eptlSrc.x+1,eptlSrc.y+1);
//
// Shift to Sreen Coordinates
//
erclSrc += dcoSrc.eptlOrigin();
//
// Parameter validation not necessary here. It seems
// that if the +1 above wraps, the initialization of the
// clip obj will catch it in this case.
//
//
// Compute the clipping complexity and maybe reduce the exclusion rectangle.
//
ECLIPOBJ co(dcoSrc.prgnEffRao(), erclSrc);
//
// Check the destination which is reduced by clipping.
//
if (!co.erclExclude().bEmpty())
{
//
// Exclude the pointer.
//
DEVEXCLUDEOBJ dxo(dcoSrc,&erclSrc);
//
// Check target device color.
//
BOOL bCMYKColor = dcoSrc.pdc->bIsCMYKColor();
#if 0
if (pSurfSrc->iType() == STYPE_BITMAP)
{
// We have a special function to quick get it.
iSolidColor = EngGetPixel(
pSurfSrc, // Source surface.
(POINTL *) &erclSrc // Source origin.
);
if (!bCMYKColor)
{
iSolidColor = ulIndexToRGB(palSurf, palDC, iSolidColor);
}
}
else
#endif
{
iSolidColor = 0;
//
// Allocate up a temporary DIB.
//
DEVBITMAPINFO dbmi;
dbmi.cxBitmap = 1;
dbmi.cyBitmap = 1;
dbmi.hpal = (HPALETTE) 0;
dbmi.fl = BMF_TOPDOWN;
RECTL rclDst;
//
// To make sure the color falls into the lower
// bit/nibble/word, the destination rect is adjusted.
//
dbmi.iFormat = pSurfSrc->iFormat();
switch (dbmi.iFormat)
{
case BMF_1BPP:
rclDst.left = 7;
rclDst.right = 8;
break;
case BMF_4BPP:
rclDst.left = 1;
rclDst.right = 2;
break;
default:
rclDst.left = 0;
rclDst.right = 1;
}
SURFMEM SurfTempDIB;
if (SurfTempDIB.bCreateDIB(&dbmi, &iSolidColor))
{
rclDst.top = 0;
rclDst.bottom = 1;
PDEVOBJ pdo(pSurfSrc->hdev());
if ((*PPFNGET(pdo, CopyBits, pSurfSrc->flags()))
(SurfTempDIB.pSurfobj(),
pSurfSrc->pSurfobj(),
(CLIPOBJ *) NULL,
&xloIdent,
&rclDst,
(POINTL *) &erclSrc))
{
if (!bCMYKColor)
{
XEPALOBJ palDC(dcoSrc.ppal());
XEPALOBJ palSurf(pSurfSrc->ppal());
iSolidColor = ulIndexToRGB(palSurf, palDC, iSolidColor);
}
}
}
}
}
}
}
dcoSrc.vUnlockFast();
}
return(iSolidColor);
}