reactos/subsystems/win32/win32k/objects/bitmaps.c
Timo Kreuzer f8a49f4c75 [WIN32K]
Introduce GreCreateBitmapEx, which has the extended functionality needed by some callers, GreCreateBitmap calls GreCreateBitmapEx to keep the simple syntax. Use it in DIB_CreateDIBSection to fix build. Also pass the size of the image (still ignored), which is needed for compressed bitmaps (we currently assume that RLEs take as much space as an uncompressed bitmap)

svn path=/branches/reactos-yarotows/; revision=47663
2010-06-07 15:55:03 +00:00

1088 lines
29 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)
{
PSURFACE psurf;
SURFOBJ *pso;
HBITMAP hbmp;
PVOID pvCompressedBits;
SIZEL sizl;
FLONG fl = 0;
/* 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);
fl |= 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);
fl |= BMF_RLE_HACK;
}
/* 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;
}
/* Mark as API bitmap */
psurf->flags |= API_BITMAP;
/* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
return hbmp;
}
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);
}
HBITMAP
APIENTRY
NtGdiCreateBitmap(
IN INT nWidth,
IN INT nHeight,
IN UINT cPlanes,
IN UINT cBitsPixel,
IN OPTIONAL LPBYTE pUnsafeBits)
{
PSURFACE psurf;
SURFOBJ *pso;
HBITMAP hbmp;
FLONG fl = 0;
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 = DIB_GetDIBWidthBytes(nWidth, cBitsPixel);
if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
{
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
nWidth, nHeight, cBitsPixel);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
if (!psurf)
{
DPRINT1("SURFACE_AllocSurface failed.\n");
EngSetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
/* Get the handle for the bitmap and the surfobj */
hbmp = (HBITMAP)psurf->SurfObj.hsurf;
pso = &psurf->SurfObj;
/* Allocate the bitmap bits */
if (!SURFACE_bSetBitmapBits(psurf, fl, 0, NULL))
{
/* Bail out if that failed */
DPRINT1("SURFACE_bSetBitmapBits failed.\n");
SURFACE_FreeSurfaceByHandle(hbmp);
return NULL;
}
if (pUnsafeBits)
{
_SEH2_TRY
{
ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SURFACE_FreeSurfaceByHandle(hbmp);
_SEH2_YIELD(return NULL;)
}
_SEH2_END
}
/* Mark as API bitmap */
psurf->flags |= API_BITMAP;
/* Unlock the surface and return */
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 */
BITMAPINFO *bi;
PVOID Bits;
/* Allocate memory for a BITMAPINFOHEADER structure and a
color table. The maximum number of colors in a color table
is 256 which corresponds to a bitmap with depth 8.
Bitmaps with higher depths don't have color tables. */
bi = ExAllocatePoolWithTag(PagedPool,
sizeof(BITMAPINFOHEADER) +
256 * sizeof(RGBQUAD),
TAG_TEMP);
if (bi)
{
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(DWORD));
}
else if (bi->bmiHeader.biBitCount <= 8)
{
/* Copy the color table */
UINT Index;
PPALETTE PalGDI;
if (!psurf->ppal)
{
ExFreePoolWithTag(bi, TAG_TEMP);
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);
ExFreePoolWithTag(bi, TAG_TEMP);
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 = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
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 = GreCreateBitmap(abs(bm.bmWidth),
abs(bm.bmHeight),
1,
bm.bmBitsPixel,
NULL);
if (res)
{
PBYTE buf;
resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
if (resBitmap)
{
buf = ExAllocatePoolWithTag(PagedPool,
bm.bmWidthBytes * abs(bm.bmHeight),
TAG_BITMAP);
if (buf == NULL)
{
GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
GreDeleteObject(res);
return 0;
}
IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
ExFreePoolWithTag(buf,TAG_BITMAP);
resBitmap->flags = Bitmap->flags;
/* Copy palette */
if (Bitmap->ppal)
{
resBitmap->ppal = Bitmap->ppal ;
GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject);
}
GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
}
else
{
GreDeleteObject(res);
res = NULL;
}
}
GDIOBJ_UnlockObjByPtr((POBJ)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->bmWidthBytes = abs(psurf->SurfObj.lDelta);
pBitmap->bmPlanes = 1;
pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
/* Check for DIB section */
if (psurf->hSecure)
{
/* Set bmBits in this case */
pBitmap->bmBits = psurf->SurfObj.pvBits;
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;
switch (psurf->SurfObj.iBitmapFormat)
{
/* FIXME: What about BI_BITFIELDS? */
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->biClrUsed;
pds->dsBmih.biClrImportant = psurf->biClrImportant;
pds->dsBitfields[0] = psurf->dsBitfields[0];
pds->dsBitfields[1] = psurf->dsBitfields[1];
pds->dsBitfields[2] = psurf->dsBitfields[2];
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 */