* COPYRIGHT: GNU GPL, See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Bitmap functions
- * FILE: subsys/win32k/objects/bitmaps.c
- * PROGRAMER: Timo Kreuzer <timo.kreuzer@reactos.org>
+ * FILE: win32ss/gdi/ntgdi/bitmaps.c
+ * PROGRAMERS: Timo Kreuzer <timo.kreuzer@reactos.org>
+ * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
-void
+BOOL
+NTAPI
+GreSetBitmapOwner(
+ _In_ HBITMAP hbmp,
+ _In_ ULONG ulOwner)
+{
+ /* Check if we have the correct object type */
+ if (GDI_HANDLE_GET_TYPE(hbmp) != GDILoObjType_LO_BITMAP_TYPE)
+ {
+ DPRINT1("Incorrect type for hbmp: %p\n", hbmp);
+ return FALSE;
+ }
+
+ /// FIXME: this is a hack and doesn't handle a race condition properly.
+ /// It needs to be done in GDIOBJ_vSetObjectOwner atomically.
+
+ /* Check if we set public or none */
+ if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) ||
+ (ulOwner == GDI_OBJ_HMGR_NONE))
+ {
+ /* Only allow this for owned objects */
+ if (GreGetObjectOwner(hbmp) != GDI_OBJ_HMGR_POWNED)
+ {
+ DPRINT1("Cannot change owner for non-powned hbmp\n");
+ return FALSE;
+ }
+ }
+
+ return GreSetObjectOwner(hbmp, ulOwner);
+}
+
+LONG
NTAPI
UnsafeSetBitmapBits(
- PSURFACE psurf,
- IN ULONG cjBits,
- IN PVOID pvBits)
+ _Inout_ PSURFACE psurf,
+ _In_ ULONG cjBits,
+ _In_ const VOID *pvBits)
{
- PUCHAR pjDst, pjSrc;
+ PUCHAR pjDst;
+ const UCHAR *pjSrc;
LONG lDeltaDst, lDeltaSrc;
- ULONG nWidth, nHeight, cBitsPixel;
+ ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel;
+
+ NT_ASSERT(psurf->flags & API_BITMAP);
+ NT_ASSERT(psurf->SurfObj.iBitmapFormat <= BMF_32BPP);
nWidth = psurf->SurfObj.sizlBitmap.cx;
- nHeight = psurf->SurfObj.sizlBitmap.cy;
+ nHeight = labs(psurf->SurfObj.sizlBitmap.cy);
cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- /* Get pointers */
pjDst = psurf->SurfObj.pvScan0;
pjSrc = pvBits;
lDeltaDst = psurf->SurfObj.lDelta;
lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+ NT_ASSERT(lDeltaSrc <= labs(lDeltaDst));
+
+ cbDst = labs(lDeltaDst) * nHeight;
+ cbSrc = lDeltaSrc * nHeight;
+ cjBits = min(cjBits, cbSrc);
- while (nHeight--)
+ iSrc = iDst = 0;
+ for (Y = 0; Y < nHeight; Y++)
{
+ if (iSrc + lDeltaSrc > cjBits || iDst + labs(lDeltaDst) > cbDst)
+ {
+ LONG lDelta = min(cjBits - iSrc, cbDst - iDst);
+ NT_ASSERT(lDelta >= 0);
+ RtlCopyMemory(pjDst, pjSrc, lDelta);
+ iSrc += lDelta;
+ break;
+ }
+
/* Copy one line */
- memcpy(pjDst, pjSrc, lDeltaSrc);
+ RtlCopyMemory(pjDst, pjSrc, lDeltaSrc);
pjSrc += lDeltaSrc;
pjDst += lDeltaDst;
+ iSrc += lDeltaSrc;
+ iDst += labs(lDeltaDst);
}
+ return iSrc;
}
HBITMAP
iFormat,
fjBitmap,
cjWidthBytes,
+ pvCompressedBits ? 0 : cjSizeImage,
pvBits);
if (!psurf)
{
lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]);
pvBits = psurf->SurfObj.pvBits;
- DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat);
+ DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat, cjSizeImage);
}
/* Get the handle for the bitmap */
IN OPTIONAL LPBYTE pUnsafeBits)
{
HBITMAP hbmp;
- ULONG cRealBpp, cjWidthBytes, iFormat, fjBitmap;
+ ULONG cRealBpp, cjWidthBytes, iFormat;
ULONGLONG cjSize;
PSURFACE psurf;
return NULL;
}
- /* Allocations larger than PAGE_SIZE go into user mem */
- fjBitmap = (cjSize > PAGE_SIZE) ? BMF_USERMEM : 0;
-
/* Allocate the surface (but don't set the bits) */
psurf = SURFACE_AllocSurface(STYPE_BITMAP,
nWidth,
nHeight,
iFormat,
- fjBitmap,
+ 0,
+ 0,
0,
NULL);
if (!psurf)
_SEH2_TRY
{
ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1);
- UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
+ UnsafeSetBitmapBits(psurf, cjSize, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
IntCreateCompatibleBitmap(
PDC Dc,
INT Width,
- INT Height)
+ INT Height,
+ UINT Planes,
+ UINT Bpp)
{
HBITMAP Bmp = NULL;
PPALETTE ppal;
Bmp = GreCreateBitmap(abs(Width),
abs(Height),
- 1,
- Dc->ppdev->gdiinfo.cBitsPixel,
+ Planes ? Planes : 1,
+ Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel,
NULL);
+ if (Bmp == NULL)
+ {
+ DPRINT1("Failed to allocate a bitmap!\n");
+ return NULL;
+ }
+
psurf = SURFACE_ShareLockSurface(Bmp);
ASSERT(psurf);
/* Set flags */
psurf->flags = API_BITMAP;
psurf->hdc = NULL; // FIXME:
+ psurf->SurfObj.hdev = (HDEV)Dc->ppdev;
SURFACE_ShareUnlockSurface(psurf);
}
else
Bmp = GreCreateBitmap(abs(Width),
abs(Height),
- 1,
- dibs.dsBm.bmBitsPixel,
+ Planes ? Planes : 1,
+ Bpp ? Bpp : dibs.dsBm.bmBitsPixel,
NULL);
psurfBmp = SURFACE_ShareLockSurface(Bmp);
ASSERT(psurfBmp);
/* Set flags */
psurfBmp->flags = API_BITMAP;
psurfBmp->hdc = NULL; // FIXME:
+ psurf->SurfObj.hdev = (HDEV)Dc->ppdev;
SURFACE_ShareUnlockSurface(psurfBmp);
}
else if (Count == sizeof(DIBSECTION))
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.biPlanes = Planes ? Planes : dibs.dsBmih.biPlanes;
+ bi->bmiHeader.biBitCount = Bpp ? Bpp : dibs.dsBmih.biBitCount;
bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
bi->bmiHeader.biSizeImage = 0;
bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
return NULL;
}
- Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
+ Bmp = IntCreateCompatibleBitmap(Dc, Width, Height, 0, 0);
DC_UnlockDc(Dc);
return Bmp;
}
BOOL
-APIENTRY
-NtGdiGetBitmapDimension(
- HBITMAP hBitmap,
- LPSIZE psizDim)
+NTAPI
+GreGetBitmapDimension(
+ _In_ HBITMAP hBitmap,
+ _Out_ LPSIZE psizDim)
{
PSURFACE psurfBmp;
- BOOL bResult = TRUE;
if (hBitmap == NULL)
return FALSE;
return FALSE;
}
+ *psizDim = psurfBmp->sizlDim;
+
+ /* Unlock the bitmap */
+ SURFACE_ShareUnlockSurface(psurfBmp);
+
+ return TRUE;
+}
+
+BOOL
+APIENTRY
+NtGdiGetBitmapDimension(
+ HBITMAP hBitmap,
+ LPSIZE psizDim)
+{
+ SIZE dim;
+
+ if (!GreGetBitmapDimension(hBitmap, &dim))
+ return FALSE;
+
/* Use SEH to copy the data to the caller */
_SEH2_TRY
{
- ProbeForWrite(psizDim, sizeof(SIZE), 1);
- *psizDim = psurfBmp->sizlDim;
+ ProbeForWrite(psizDim, sizeof(*psizDim), 1);
+ *psizDim = dim;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- bResult = FALSE;
+ _SEH2_YIELD(return FALSE);
}
_SEH2_END
- /* Unlock the bitmap */
- SURFACE_ShareUnlockSurface(psurfBmp);
-
- return bResult;
+ return TRUE;
}
-VOID
+LONG
FASTCALL
UnsafeGetBitmapBits(
PSURFACE psurf,
{
PUCHAR pjDst, pjSrc;
LONG lDeltaDst, lDeltaSrc;
- ULONG nWidth, nHeight, cBitsPixel;
+ ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel;
nWidth = psurf->SurfObj.sizlBitmap.cx;
- nHeight = psurf->SurfObj.sizlBitmap.cy;
+ nHeight = labs(psurf->SurfObj.sizlBitmap.cy);
cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
/* Get pointers */
pjDst = pvBits;
lDeltaSrc = psurf->SurfObj.lDelta;
lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+ NT_ASSERT(labs(lDeltaSrc) >= lDeltaDst);
- while (nHeight--)
+ cbSrc = nHeight * labs(lDeltaSrc);
+ cbDst = nHeight * lDeltaDst;
+ Bytes = min(Bytes, cbDst);
+
+ iSrc = iDst = 0;
+ for (Y = 0; Y < nHeight; Y++)
{
+ if (iSrc + labs(lDeltaSrc) > cbSrc || iDst + lDeltaDst > Bytes)
+ {
+ LONG lDelta = min(cbSrc - iSrc, Bytes - iDst);
+ NT_ASSERT(lDelta >= 0);
+ RtlCopyMemory(pjDst, pjSrc, lDelta);
+ iDst += lDelta;
+ break;
+ }
+
/* Copy one line */
RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
pjSrc += lDeltaSrc;
pjDst += lDeltaDst;
+ iSrc += labs(lDeltaSrc);
+ iDst += lDeltaDst;
}
+
+ return iDst;
}
LONG
_SEH2_TRY
{
ProbeForWrite(pUnsafeBits, cjBuffer, 1);
- UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
- ret = cjBuffer;
+ ret = UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
return 0;
}
+ if (GDI_HANDLE_IS_STOCKOBJ(hBitmap))
+ {
+ return 0;
+ }
+
psurf = SURFACE_ShareLockSurface(hBitmap);
if (psurf == NULL)
{
return 0;
}
+ if (((psurf->flags & API_BITMAP) == 0) ||
+ (psurf->SurfObj.iBitmapFormat > BMF_32BPP))
+ {
+ DPRINT1("Invalid bitmap: iBitmapFormat = %lu, flags = 0x%lx\n",
+ psurf->SurfObj.iBitmapFormat,
+ psurf->flags);
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ SURFACE_ShareUnlockSurface(psurf);
+ return 0;
+ }
+
_SEH2_TRY
{
+ /* NOTE: Win2k3 doesn't check WORD alignment here. */
ProbeForRead(pUnsafeBits, Bytes, 1);
- UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
- ret = 1;
+ ret = UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{