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
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);
|
|
}
|