reactos/subsystems/win32/win32k/objects/bitmaps.c
Jérôme Gardou 501947714e [WIN32K]
- Use correct offset in UserLoadImage, create the bitmap using display DC.
  - BITMAP_GetObject : Report BI_BITFIELDS compression when we should.
  - Use a 0 compatible DC when none is given in NtGdiCreateDIBitmapInternal.
This fixes some wine tests. Enjoy.

svn path=/branches/reactos-yarotows/; revision=48415
2010-08-02 14:45:51 +00:00

1047 lines
27 KiB
C

/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
LONG APIENTRY
IntSetBitmapBits(
PSURFACE psurf,
DWORD Bytes,
IN PBYTE Bits)
{
/* Don't copy more bytes than the buffer has */
Bytes = min(Bytes, psurf->SurfObj.cjBits);
RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
return Bytes;
}
void
NTAPI
UnsafeSetBitmapBits(
PSURFACE psurf,
IN ULONG cjBits,
IN PVOID pvBits)
{
PUCHAR pjDst, pjSrc;
LONG lDeltaDst, lDeltaSrc;
ULONG nWidth, nHeight, cBitsPixel;
nWidth = psurf->SurfObj.sizlBitmap.cx;
nHeight = psurf->SurfObj.sizlBitmap.cy;
cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
/* Get pointers */
pjDst = psurf->SurfObj.pvScan0;
pjSrc = pvBits;
lDeltaDst = psurf->SurfObj.lDelta;
lDeltaSrc = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
while (nHeight--)
{
/* Copy one line */
memcpy(pjDst, pjSrc, lDeltaSrc);
pjSrc += lDeltaSrc;
pjDst += lDeltaDst;
}
}
HBITMAP
APIENTRY
GreCreateBitmapEx(
IN INT nWidth,
IN INT nHeight,
IN ULONG cjWidthBytes,
IN ULONG iFormat,
IN USHORT fjBitmap,
IN ULONG cjSizeImage,
IN OPTIONAL PVOID pvBits,
IN FLONG flags)
{
PSURFACE psurf;
SURFOBJ *pso;
HBITMAP hbmp;
PVOID pvCompressedBits;
SIZEL sizl;
/* Verify format */
if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
/* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
if (!psurf)
{
DPRINT1("SURFACE_AllocSurface failed.\n");
return NULL;
}
/* Get the handle for the bitmap and the surfobj */
hbmp = (HBITMAP)psurf->SurfObj.hsurf;
pso = &psurf->SurfObj;
/* The infamous RLE hack */
if (iFormat == BMF_4RLE)
{
sizl.cx = nWidth; sizl.cy = nHeight;
pvCompressedBits = pvBits;
pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
Decompress4bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
fjBitmap |= BMF_RLE_HACK;
}
else if (iFormat == BMF_8RLE)
{
sizl.cx = nWidth; sizl.cy = nHeight;
pvCompressedBits = pvBits;
pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
Decompress8bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
fjBitmap |= BMF_RLE_HACK;
}
/* Mark as API bitmap */
psurf->flags |= (flags | API_BITMAP);
/* Set the bitmap bits */
if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
{
/* Bail out if that failed */
DPRINT1("SURFACE_bSetBitmapBits failed.\n");
SURFACE_FreeSurfaceByHandle(hbmp);
return NULL;
}
/* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
return hbmp;
}
/* Creates a DDB surface,
* as in CreateCompatibleBitmap or CreateBitmap.
*/
HBITMAP
APIENTRY
GreCreateBitmap(
IN INT nWidth,
IN INT nHeight,
IN UINT cPlanes,
IN UINT cBitsPixel,
IN OPTIONAL PVOID pvBits)
{
/* Call the extended function */
return GreCreateBitmapEx(nWidth,
nHeight,
0, /* auto width */
BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
0, /* no bitmap flags */
0, /* auto size */
pvBits,
DDB_SURFACE /* DDB */);
}
HBITMAP
APIENTRY
NtGdiCreateBitmap(
IN INT nWidth,
IN INT nHeight,
IN UINT cPlanes,
IN UINT cBitsPixel,
IN OPTIONAL LPBYTE pUnsafeBits)
{
HBITMAP hbmp;
ULONG cjWidthBytes, iFormat;
/* NOTE: Windows also doesn't store nr. of planes separately! */
cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes);
/* Calculate bitmap format */
iFormat = BitmapFormat(cBitsPixel, BI_RGB);
/* Check parameters */
if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0)
{
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
nWidth, nHeight, cBitsPixel);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Make sure that cjBits will not overflow */
cjWidthBytes = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
{
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
nWidth, nHeight, cBitsPixel);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* cBitsPixel = cBitsPixel * cPlanes now! */
hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
if (pUnsafeBits)
{
PSURFACE psurf = SURFACE_LockSurface(hbmp);
_SEH2_TRY
{
ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SURFACE_UnlockSurface(psurf);
SURFACE_FreeSurfaceByHandle(hbmp);
_SEH2_YIELD(return NULL;)
}
_SEH2_END
SURFACE_UnlockSurface(psurf);
}
return hbmp;
}
HBITMAP FASTCALL
IntCreateCompatibleBitmap(
PDC Dc,
INT Width,
INT Height)
{
HBITMAP Bmp = NULL;
/* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
if (0 == Width || 0 == Height)
{
Bmp = NtGdiGetStockObject(DEFAULT_BITMAP);
}
else
{
if (Dc->dctype != DC_TYPE_MEMORY)
{
PSURFACE psurf;
SIZEL size;
size.cx = abs(Width);
size.cy = abs(Height);
Bmp = GreCreateBitmap(abs(Width),
abs(Height),
1,
Dc->ppdev->gdiinfo.cBitsPixel,
NULL);
psurf = SURFACE_LockSurface(Bmp);
ASSERT(psurf);
/* Set palette */
psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
/* Set flags */
psurf->flags = API_BITMAP;
psurf->hdc = NULL; // Fixme
SURFACE_UnlockSurface(psurf);
}
else
{
DIBSECTION dibs;
INT Count;
PSURFACE psurf = Dc->dclevel.pSurface;
Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
if (Count)
{
if (Count == sizeof(BITMAP))
{
SIZEL size;
PSURFACE psurfBmp;
size.cx = abs(Width);
size.cy = abs(Height);
Bmp = GreCreateBitmap(abs(Width),
abs(Height),
1,
dibs.dsBm.bmBitsPixel,
NULL);
psurfBmp = SURFACE_LockSurface(Bmp);
ASSERT(psurfBmp);
/* Assign palette */
psurfBmp->ppal = psurf->ppal;
GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
/* Set flags */
psurfBmp->flags = API_BITMAP;
psurfBmp->hdc = NULL; // Fixme
SURFACE_UnlockSurface(psurfBmp);
}
else
{
/* A DIB section is selected in the DC */
BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
PVOID Bits;
BITMAPINFO* bi = (BITMAPINFO*)buf;
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
bi->bmiHeader.biWidth = Width;
bi->bmiHeader.biHeight = Height;
bi->bmiHeader.biPlanes = dibs.dsBmih.biPlanes;
bi->bmiHeader.biBitCount = dibs.dsBmih.biBitCount;
bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
bi->bmiHeader.biSizeImage = 0;
bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed;
bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant;
if (bi->bmiHeader.biCompression == BI_BITFIELDS)
{
/* Copy the color masks */
RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
}
else if (bi->bmiHeader.biBitCount <= 8)
{
/* Copy the color table */
UINT Index;
PPALETTE PalGDI;
if (!psurf->ppal)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
for (Index = 0;
Index < 256 && Index < PalGDI->NumColors;
Index++)
{
bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed;
bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
bi->bmiColors[Index].rgbReserved = 0;
}
PALETTE_UnlockPalette(PalGDI);
Bmp = DIB_CreateDIBSection(Dc,
bi,
DIB_RGB_COLORS,
&Bits,
NULL,
0,
0);
return Bmp;
}
}
}
}
}
return Bmp;
}
HBITMAP APIENTRY
NtGdiCreateCompatibleBitmap(
HDC hDC,
INT Width,
INT Height)
{
HBITMAP Bmp;
PDC Dc;
if (Width <= 0 || Height <= 0 || (Width * Height) > 0x3FFFFFFF)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
if (!hDC)
return GreCreateBitmap(Width, Height, 1, 1, 0);
Dc = DC_LockDc(hDC);
DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n",
hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel);
if (NULL == Dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL;
}
Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
DPRINT("\t\t%04x\n", Bmp);
DC_UnlockDc(Dc);
return Bmp;
}
BOOL APIENTRY
NtGdiGetBitmapDimension(
HBITMAP hBitmap,
LPSIZE Dimension)
{
PSURFACE psurfBmp;
BOOL Ret = TRUE;
if (hBitmap == NULL)
return FALSE;
psurfBmp = SURFACE_LockSurface(hBitmap);
if (psurfBmp == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
_SEH2_TRY
{
ProbeForWrite(Dimension, sizeof(SIZE), 1);
*Dimension = psurfBmp->sizlDim;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Ret = FALSE;
}
_SEH2_END
SURFACE_UnlockSurface(psurfBmp);
return Ret;
}
COLORREF APIENTRY
NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
{
PDC dc = NULL;
COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
BOOL bInRect = FALSE;
SURFACE *psurf;
SURFOBJ *pso;
PPALETTE ppal;
EXLATEOBJ exlo;
HBITMAP hBmpTmp;
dc = DC_LockDc(hDC);
if (!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return Result;
}
if (dc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(dc);
return Result;
}
XPos += dc->ptlDCOrig.x;
YPos += dc->ptlDCOrig.y;
if (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos))
{
bInRect = TRUE;
psurf = dc->dclevel.pSurface;
if (psurf)
{
pso = &psurf->SurfObj;
if (psurf->ppal)
{
ppal = psurf->ppal;
GDIOBJ_IncrementShareCount(&ppal->BaseObject);
}
else
ppal = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault);
if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
{
/* FIXME: palette should be gpalMono already ! */
EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0);
}
else
{
EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0);
}
// check if this DC has a DIB behind it...
if (pso->pvScan0) // STYPE_BITMAP == pso->iType
{
ASSERT(pso->lDelta);
Result = XLATEOBJ_iXlate(&exlo.xlo,
DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_GetPixel(pso, XPos, YPos));
}
EXLATEOBJ_vCleanup(&exlo);
PALETTE_ShareUnlockPalette(ppal);
}
}
DC_UnlockDc(dc);
// if Result is still CLR_INVALID, then the "quick" method above didn't work
if (bInRect && Result == CLR_INVALID)
{
// FIXME: create a 1x1 32BPP DIB, and blit to it
HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
if (hDCTmp)
{
static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
BITMAPINFO bi;
RtlMoveMemory(&(bi.bmiHeader), &bih, sizeof(bih));
hBmpTmp = NtGdiCreateDIBitmapInternal(hDC,
bi.bmiHeader.biWidth,
bi.bmiHeader.biHeight,
0,
NULL,
&bi,
DIB_RGB_COLORS,
bi.bmiHeader.biBitCount,
bi.bmiHeader.biSizeImage,
0,
0);
//HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL);
if (hBmpTmp)
{
HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
if (hBmpOld)
{
PSURFACE psurf;
NtGdiBitBlt(hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0);
NtGdiSelectBitmap(hDCTmp, hBmpOld);
// our bitmap is no longer selected, so we can access it's stuff...
psurf = SURFACE_LockSurface(hBmpTmp);
if (psurf)
{
// Dont you need to convert something here?
Result = *(COLORREF*)psurf->SurfObj.pvScan0;
SURFACE_UnlockSurface(psurf);
}
}
GreDeleteObject(hBmpTmp);
}
NtGdiDeleteObjectApp(hDCTmp);
}
}
return Result;
}
LONG APIENTRY
IntGetBitmapBits(
PSURFACE psurf,
DWORD Bytes,
OUT PBYTE Bits)
{
LONG ret;
ASSERT(Bits);
/* Don't copy more bytes than the buffer has */
Bytes = min(Bytes, psurf->SurfObj.cjBits);
#if 0
/* FIXME: Call DDI CopyBits here if available */
if (psurf->DDBitmap)
{
DPRINT("Calling device specific BitmapBits\n");
if (psurf->DDBitmap->funcs->pBitmapBits)
{
ret = psurf->DDBitmap->funcs->pBitmapBits(hbitmap,
bits,
count,
DDB_GET);
}
else
{
ERR_(bitmap)("BitmapBits == NULL??\n");
ret = 0;
}
}
else
#endif
{
RtlCopyMemory(Bits, psurf->SurfObj.pvBits, Bytes);
ret = Bytes;
}
return ret;
}
LONG APIENTRY
NtGdiGetBitmapBits(
HBITMAP hBitmap,
ULONG Bytes,
OUT OPTIONAL PBYTE pUnsafeBits)
{
PSURFACE psurf;
LONG bmSize, ret;
if (pUnsafeBits != NULL && Bytes == 0)
{
return 0;
}
psurf = SURFACE_LockSurface(hBitmap);
if (!psurf)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx,
BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
abs(psurf->SurfObj.sizlBitmap.cy);
/* If the bits vector is null, the function should return the read size */
if (pUnsafeBits == NULL)
{
SURFACE_UnlockSurface(psurf);
return bmSize;
}
/* Don't copy more bytes than the buffer has */
Bytes = min(Bytes, bmSize);
// FIXME: use MmSecureVirtualMemory
_SEH2_TRY
{
ProbeForWrite(pUnsafeBits, Bytes, 1);
ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ret = 0;
}
_SEH2_END
SURFACE_UnlockSurface(psurf);
return ret;
}
LONG APIENTRY
NtGdiSetBitmapBits(
HBITMAP hBitmap,
DWORD Bytes,
IN PBYTE pUnsafeBits)
{
LONG ret;
PSURFACE psurf;
if (pUnsafeBits == NULL || Bytes == 0)
{
return 0;
}
psurf = SURFACE_LockSurface(hBitmap);
if (psurf == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
_SEH2_TRY
{
ProbeForRead(pUnsafeBits, Bytes, 1);
UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
ret = 1;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ret = 0;
}
_SEH2_END
SURFACE_UnlockSurface(psurf);
return ret;
}
BOOL APIENTRY
NtGdiSetBitmapDimension(
HBITMAP hBitmap,
INT Width,
INT Height,
LPSIZE Size)
{
PSURFACE psurf;
BOOL Ret = TRUE;
if (hBitmap == NULL)
return FALSE;
psurf = SURFACE_LockSurface(hBitmap);
if (psurf == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if (Size)
{
_SEH2_TRY
{
ProbeForWrite(Size, sizeof(SIZE), 1);
*Size = psurf->sizlDim;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Ret = FALSE;
}
_SEH2_END
}
/* The dimension is changed even if writing the old value failed */
psurf->sizlDim.cx = Width;
psurf->sizlDim.cy = Height;
SURFACE_UnlockSurface(psurf);
return Ret;
}
VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color)
{
PDC pdc = NULL;
RGBQUAD quad;
PALETTEENTRY palEntry;
UINT index;
switch (*Color >> 24)
{
case 0x10: /* DIBINDEX */
if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
{
*Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
}
else
{
/* Out of color table bounds - use black */
*Color = RGB(0, 0, 0);
}
break;
case 0x02: /* PALETTERGB */
pdc = DC_LockDc(hDC);
if (pdc->dclevel.hpal != NtGdiGetStockObject(DEFAULT_PALETTE))
{
index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color);
IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry);
*Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
}
else
{
/* Use the pure color */
*Color = *Color & 0x00FFFFFF;
}
DC_UnlockDc(pdc);
break;
case 0x01: /* PALETTEINDEX */
pdc = DC_LockDc(hDC);
if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1)
{
*Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
}
else
{
/* Index does not exist, use zero index */
IntGetPaletteEntries(pdc->dclevel.hpal, 0, 1, &palEntry);
*Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
}
DC_UnlockDc(pdc);
break;
default:
DPRINT("Unsupported color type %d passed\n", *Color >> 24);
break;
}
}
BOOL APIENTRY
GdiSetPixelV(
HDC hDC,
INT X,
INT Y,
COLORREF Color)
{
HBRUSH hBrush;
HGDIOBJ OldBrush;
if ((Color & 0xFF000000) != 0)
{
IntHandleSpecialColorType(hDC, &Color);
}
hBrush = NtGdiCreateSolidBrush(Color, NULL);
if (hBrush == NULL)
return FALSE;
OldBrush = NtGdiSelectBrush(hDC, hBrush);
if (OldBrush == NULL)
{
GreDeleteObject(hBrush);
return FALSE;
}
NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
NtGdiSelectBrush(hDC, OldBrush);
GreDeleteObject(hBrush);
return TRUE;
}
COLORREF APIENTRY
NtGdiSetPixel(
HDC hDC,
INT X,
INT Y,
COLORREF Color)
{
DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
if (GdiSetPixelV(hDC,X,Y,Color))
{
Color = NtGdiGetPixel(hDC,X,Y);
DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
return Color;
}
Color = (COLORREF)CLR_INVALID;
DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
return Color;
}
/* Internal Functions */
UINT FASTCALL
BITMAP_GetRealBitsPixel(UINT nBitsPixel)
{
if (nBitsPixel <= 1)
return 1;
if (nBitsPixel <= 4)
return 4;
if (nBitsPixel <= 8)
return 8;
if (nBitsPixel <= 16)
return 16;
if (nBitsPixel <= 24)
return 24;
if (nBitsPixel <= 32)
return 32;
return 0;
}
INT FASTCALL
BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
{
#if 0
switch (bpp)
{
case 1:
return 2 * ((bmWidth+15) >> 4);
case 24:
bmWidth *= 3; /* fall through */
case 8:
return bmWidth + (bmWidth & 1);
case 32:
return bmWidth * 4;
case 16:
case 15:
return bmWidth * 2;
case 4:
return 2 * ((bmWidth+3) >> 2);
default:
DPRINT ("stub");
}
return -1;
#endif
return ((bmWidth * bpp + 15) & ~15) >> 3;
}
HBITMAP FASTCALL
BITMAP_CopyBitmap(HBITMAP hBitmap)
{
HBITMAP res;
BITMAP bm;
SURFACE *Bitmap, *resBitmap;
SIZEL Size;
if (hBitmap == NULL)
{
return 0;
}
Bitmap = SURFACE_LockSurface(hBitmap);
if (Bitmap == NULL)
{
return 0;
}
BITMAP_GetObject(Bitmap, sizeof(BITMAP), (PVOID)&bm);
bm.bmBits = NULL;
if (Bitmap->SurfObj.lDelta >= 0)
bm.bmHeight = -bm.bmHeight;
Size.cx = abs(bm.bmWidth);
Size.cy = abs(bm.bmHeight);
res = GreCreateBitmapEx(Size.cx,
Size.cy,
bm.bmWidthBytes,
Bitmap->SurfObj.iBitmapFormat,
Bitmap->SurfObj.fjBitmap,
Bitmap->SurfObj.cjBits,
NULL,
Bitmap->flags);
if (res)
{
resBitmap = SURFACE_LockSurface(res);
if (resBitmap)
{
IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
SURFACE_UnlockSurface(resBitmap);
}
else
{
GreDeleteObject(res);
res = NULL;
}
}
SURFACE_UnlockSurface(Bitmap);
return res;
}
INT APIENTRY
BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
{
PBITMAP pBitmap;
if (!buffer) return sizeof(BITMAP);
if ((UINT)Count < sizeof(BITMAP)) return 0;
/* always fill a basic BITMAP structure */
pBitmap = buffer;
pBitmap->bmType = 0;
pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
pBitmap->bmPlanes = 1;
pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
pBitmap->bmWidthBytes = BITMAP_GetWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
/* Check for DIB section */
if (psurf->hSecure)
{
/* Set bmBits in this case */
pBitmap->bmBits = psurf->SurfObj.pvBits;
/* DIBs data are 32 bits aligned */
pBitmap->bmWidthBytes = DIB_GetDIBWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
if (Count >= sizeof(DIBSECTION))
{
/* Fill rest of DIBSECTION */
PDIBSECTION pds = buffer;
pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
pds->dsBmih.biWidth = pds->dsBm.bmWidth;
pds->dsBmih.biHeight = pds->dsBm.bmHeight;
pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
if(psurf->ppal->Mode & PAL_BITFIELDS)
{
pds->dsBmih.biCompression = BI_BITFIELDS;
}
else
{
switch (psurf->SurfObj.iBitmapFormat)
{
case BMF_1BPP:
case BMF_4BPP:
case BMF_8BPP:
case BMF_16BPP:
case BMF_24BPP:
case BMF_32BPP:
pds->dsBmih.biCompression = BI_RGB;
break;
case BMF_4RLE:
pds->dsBmih.biCompression = BI_RLE4;
break;
case BMF_8RLE:
pds->dsBmih.biCompression = BI_RLE8;
break;
case BMF_JPEG:
pds->dsBmih.biCompression = BI_JPEG;
break;
case BMF_PNG:
pds->dsBmih.biCompression = BI_PNG;
break;
}
}
pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
pds->dsBmih.biXPelsPerMeter = 0;
pds->dsBmih.biYPelsPerMeter = 0;
pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
pds->dsBmih.biClrImportant = psurf->biClrImportant;
pds->dsBitfields[0] = psurf->ppal->RedMask;
pds->dsBitfields[1] = psurf->ppal->GreenMask;
pds->dsBitfields[2] = psurf->ppal->BlueMask;
pds->dshSection = psurf->hDIBSection;
pds->dsOffset = psurf->dwOffset;
return sizeof(DIBSECTION);
}
}
else
{
/* not set according to wine test, confirmed in win2k */
pBitmap->bmBits = NULL;
}
return sizeof(BITMAP);
}
/*
* @implemented
*/
HDC
APIENTRY
NtGdiGetDCforBitmap(
IN HBITMAP hsurf)
{
HDC hdc = NULL;
PSURFACE psurf = SURFACE_LockSurface(hsurf);
if (psurf)
{
hdc = psurf->hdc;
SURFACE_UnlockSurface(psurf);
}
return hdc;
}
/* EOF */