2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define IN_RECT(r,x,y) \
40 IN OPTIONAL LPBYTE pUnsafeBits
)
47 /* NOTE: Windows also doesn't store nr. of planes separately! */
48 BitsPixel
= BitsPixel
* Planes
;
49 WidthBytes
= BITMAPOBJ_GetWidthBytes(Width
, BitsPixel
);
51 /* Check parameters */
52 if (0 == Height
|| 0 == Width
)
54 Size
.cx
= Size
.cy
= 1;
59 Size
.cy
= abs(Height
);
62 /* Create the bitmap object. */
63 hBitmap
= IntCreateBitmap(Size
, WidthBytes
,
64 BitmapFormat(BitsPixel
, BI_RGB
),
65 (Height
< 0 ? BMF_TOPDOWN
: 0) |
66 (NULL
== pUnsafeBits
? 0 : BMF_NOZEROINIT
), NULL
);
69 DPRINT("NtGdiCreateBitmap: returned 0\n");
73 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
74 Size
.cx
, Size
.cy
, BitsPixel
, hBitmap
);
76 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
79 /* FIXME should we free the hBitmap or return it ?? */
83 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
85 if (NULL
!= pUnsafeBits
)
89 ProbeForRead(pUnsafeBits
, bmp
->SurfObj
.cjBits
, 1);
90 IntSetBitmapBits(bmp
, bmp
->SurfObj
.cjBits
, pUnsafeBits
);
98 BITMAPOBJ_UnlockBitmap( bmp
);
104 BITMAP_Cleanup(PVOID ObjectBody
)
106 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
107 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
108 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
110 if (pBmp
->dib
== NULL
)
112 if (pBmp
->SurfObj
.pvBits
!= NULL
)
113 ExFreePool(pBmp
->SurfObj
.pvBits
);
117 if (pBmp
->SurfObj
.pvBits
!= NULL
)
118 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
120 if (pBmp
->hDIBPalette
!= NULL
)
122 NtGdiDeleteObject(pBmp
->hDIBPalette
);
126 if (NULL
!= pBmp
->BitsLock
)
128 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
129 pBmp
->BitsLock
= NULL
;
137 IntCreateCompatibleBitmap(
146 if ((Width
>= 0x10000) || (Height
>= 0x10000))
148 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
152 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
153 if (0 == Width
|| 0 == Height
)
155 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
159 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
166 NtGdiCreateCompatibleBitmap(
176 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
180 SetLastWin32Error(ERROR_INVALID_HANDLE
);
184 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
186 DPRINT ("\t\t%04x\n", Bmp
);
192 NtGdiGetBitmapDimension(
198 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
204 *Dimension
= bmp
->dimension
;
206 BITMAPOBJ_UnlockBitmap(bmp
);
212 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
215 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
216 BOOL bInRect
= FALSE
;
217 BITMAPOBJ
*BitmapObject
;
218 SURFOBJ
*SurfaceObject
;
223 dc
= DC_LockDc (hDC
);
227 SetLastWin32Error(ERROR_INVALID_HANDLE
);
235 XPos
+= dc
->w
.DCOrgX
;
236 YPos
+= dc
->w
.DCOrgY
;
237 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
240 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
241 SurfaceObject
= &BitmapObject
->SurfObj
;
244 if ( dc
->w
.hPalette
!= 0 )
245 Pal
= dc
->w
.hPalette
;
246 /* FIXME: Verify if it shouldn't be PAL_BGR! */
247 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
250 // check if this DC has a DIB behind it...
251 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
253 ASSERT ( SurfaceObject
->lDelta
);
254 Result
= XLATEOBJ_iXlate(XlateObj
,
255 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
257 EngDeleteXlate(XlateObj
);
259 BITMAPOBJ_UnlockBitmap(BitmapObject
);
264 // if Result is still CLR_INVALID, then the "quick" method above didn't work
265 if ( bInRect
&& Result
== CLR_INVALID
)
267 // FIXME: create a 1x1 32BPP DIB, and blit to it
268 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
271 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
273 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
274 hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
275 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
278 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
283 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
, 0, 0 );
284 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
286 // our bitmap is no longer selected, so we can access it's stuff...
287 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
290 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
291 BITMAPOBJ_UnlockBitmap ( bmpobj
);
294 NtGdiDeleteObject ( hBmpTmp
);
296 NtGdiDeleteObjectApp ( hDCTmp
);
314 /* Don't copy more bytes than the buffer has */
315 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
318 /* FIXME: Call DDI CopyBits here if available */
321 DPRINT("Calling device specific BitmapBits\n");
322 if(bmp
->DDBitmap
->funcs
->pBitmapBits
)
324 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hbitmap
, bits
, count
, DDB_GET
);
328 ERR_(bitmap
)("BitmapBits == NULL??\n");
335 RtlCopyMemory(Bits
, bmp
->SurfObj
.pvBits
, Bytes
);
342 NtGdiGetBitmapBits(HBITMAP hBitmap
,
344 OUT OPTIONAL PBYTE pUnsafeBits
)
349 if (pUnsafeBits
!= NULL
&& Bytes
== 0)
354 bmp
= BITMAPOBJ_LockBitmap (hBitmap
);
357 SetLastWin32Error(ERROR_INVALID_HANDLE
);
361 /* If the bits vector is null, the function should return the read size */
362 if (pUnsafeBits
== NULL
)
364 ret
= bmp
->SurfObj
.cjBits
;
365 BITMAPOBJ_UnlockBitmap (bmp
);
369 /* Don't copy more bytes than the buffer has */
370 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
374 ProbeForWrite(pUnsafeBits
, Bytes
, 1);
375 ret
= IntGetBitmapBits(bmp
, Bytes
, pUnsafeBits
);
383 BITMAPOBJ_UnlockBitmap (bmp
);
397 /* Don't copy more bytes than the buffer has */
398 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
401 /* FIXME: call DDI specific function here if available */
404 DPRINT ("Calling device specific BitmapBits\n");
405 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
407 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
411 DPRINT ("BitmapBits == NULL??\n");
418 RtlCopyMemory(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
430 IN PBYTE pUnsafeBits
)
435 if (pUnsafeBits
== NULL
|| Bytes
== 0)
440 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
443 SetLastWin32Error(ERROR_INVALID_HANDLE
);
449 ProbeForRead(pUnsafeBits
, Bytes
, 1);
450 ret
= IntSetBitmapBits(bmp
, Bytes
, pUnsafeBits
);
458 BITMAPOBJ_UnlockBitmap(bmp
);
464 NtGdiSetBitmapDimension(
472 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
480 *Size
= bmp
->dimension
;
482 bmp
->dimension
.cx
= Width
;
483 bmp
->dimension
.cy
= Height
;
485 BITMAPOBJ_UnlockBitmap (bmp
);
498 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
501 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
503 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
505 Color
= NtGdiGetPixel(hDC
,X
,Y
);
506 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
510 Color
= ((COLORREF
) -1);
511 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
522 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
, NULL
);
525 if (NewBrush
== NULL
)
527 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
528 if (OldBrush
== NULL
)
530 NtGdiDeleteObject(NewBrush
);
533 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
534 NtGdiSelectObject(hDC
, OldBrush
);
535 NtGdiDeleteObject(NewBrush
);
539 /* Internal Functions */
542 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
548 return 2 * ((bmWidth
+15) >> 4);
551 bmWidth
*= 3; /* fall through */
553 return bmWidth
+ (bmWidth
& 1);
563 return 2 * ((bmWidth
+3) >> 2);
572 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
576 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
580 BITMAPOBJ
*Bitmap
, *resBitmap
;
588 Bitmap
= GDIOBJ_LockObj(GdiHandleTable
, hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
594 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
596 if (Bitmap
->SurfObj
.lDelta
>= 0)
597 bm
.bmHeight
= -bm
.bmHeight
;
599 Size
.cx
= abs(bm
.bmWidth
);
600 Size
.cy
= abs(bm
.bmHeight
);
601 res
= IntCreateBitmap(Size
,
603 BitmapFormat(bm
.bmBitsPixel
* bm
.bmPlanes
, BI_RGB
),
604 (bm
.bmHeight
< 0 ? BMF_TOPDOWN
: 0) | BMF_NOZEROINIT
,
611 resBitmap
= GDIOBJ_LockObj(GdiHandleTable
, res
, GDI_OBJECT_TYPE_BITMAP
);
614 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
615 IntGetBitmapBits (Bitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
616 IntSetBitmapBits (resBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
618 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, resBitmap
);
622 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, Bitmap
);
628 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT Count
, LPVOID buffer
)
630 if ((UINT
)Count
< sizeof(BITMAP
)) return 0;
634 if((UINT
)Count
< sizeof(DIBSECTION
))
636 Count
= sizeof(BITMAP
);
640 Count
= sizeof(DIBSECTION
);
644 memcpy(buffer
, bmp
->dib
, Count
);
650 Count
= sizeof(BITMAP
);
655 Count
= sizeof(BITMAP
);
657 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
658 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
659 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
661 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
662 //Bitmap.bmBits = bmp->SurfObj.pvBits;
663 Bitmap
.bmBits
= NULL
; /* not set accoring wine test confirm in win2k */
664 memcpy(buffer
, &Bitmap
, Count
);