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.
19 /* $Id: bitmaps.c,v 1.44 2003/10/29 16:25:00 navaraf Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
23 #include <win32k/color.h>
24 #include <win32k/gdiobj.h>
25 #include <win32k/bitmaps.h>
26 #include <win32k/brush.h>
27 //#include <win32k/debug.h>
28 #include "../eng/handle.h"
29 #include <include/inteng.h>
30 #include <include/eng.h>
31 #include <include/error.h>
32 #include <include/surface.h>
33 #include <include/palette.h>
36 #include <win32k/debug1.h>
38 BOOL STDCALL
NtGdiBitBlt(HDC hDCDest
,
50 PSURFOBJ SurfDest
, SurfSrc
;
51 PSURFGDI SurfGDIDest
, SurfGDISrc
;
55 PPALGDI PalDestGDI
, PalSourceGDI
;
56 PXLATEOBJ XlateObj
= NULL
;
57 HPALETTE SourcePalette
, DestPalette
;
58 ULONG SourceMode
, DestMode
;
60 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
61 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
63 DCDest
= DC_LockDc(hDCDest
);
66 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
67 SetLastWin32Error(ERROR_INVALID_HANDLE
);
73 if (hDCSrc
!= hDCDest
)
75 DCSrc
= DC_LockDc(hDCSrc
);
79 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
80 SetLastWin32Error(ERROR_INVALID_HANDLE
);
94 /* Offset the destination and source by the origin of their DCs. */
95 XDest
+= DCDest
->w
.DCOrgX
;
96 YDest
+= DCDest
->w
.DCOrgY
;
99 XSrc
+= DCSrc
->w
.DCOrgX
;
100 YSrc
+= DCSrc
->w
.DCOrgY
;
103 DestRect
.left
= XDest
;
104 DestRect
.top
= YDest
;
105 DestRect
.right
= XDest
+Width
;
106 DestRect
.bottom
= YDest
+Height
;
108 SourcePoint
.x
= XSrc
;
109 SourcePoint
.y
= YSrc
;
111 /* Determine surfaces to be used in the bitblt */
112 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
113 SurfGDIDest
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfDest
);
116 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
117 SurfGDISrc
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfSrc
);
127 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
128 if (NULL
== BrushObj
)
130 if (UsesSource
&& hDCSrc
!= hDCDest
)
134 DC_UnlockDc(hDCDest
);
135 SetLastWin32Error(ERROR_INVALID_HANDLE
);
144 if (DCDest
->w
.hPalette
!= 0)
146 DestPalette
= DCDest
->w
.hPalette
;
150 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
153 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
155 SourcePalette
= DCSrc
->w
.hPalette
;
159 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
162 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
163 if (NULL
== PalSourceGDI
)
165 if (UsesSource
&& hDCSrc
!= hDCDest
)
169 DC_UnlockDc(hDCDest
);
170 SetLastWin32Error(ERROR_INVALID_HANDLE
);
173 SourceMode
= PalSourceGDI
->Mode
;
174 PALETTE_UnlockPalette(SourcePalette
);
176 if (DestPalette
== SourcePalette
)
178 DestMode
= SourceMode
;
182 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
183 if (NULL
== PalDestGDI
)
185 if (UsesSource
&& hDCSrc
!= hDCDest
)
189 DC_UnlockDc(hDCDest
);
190 SetLastWin32Error(ERROR_INVALID_HANDLE
);
193 DestMode
= PalDestGDI
->Mode
;
194 PALETTE_UnlockPalette(DestPalette
);
197 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
198 if (NULL
== XlateObj
)
200 if (UsesSource
&& hDCSrc
!= hDCDest
)
204 DC_UnlockDc(hDCDest
);
205 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
209 /* Perform the bitblt operation */
210 Status
= IntEngBitBlt(SurfDest
, SurfSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
211 &DestRect
, &SourcePoint
, NULL
, BrushObj
, NULL
, ROP
);
213 EngDeleteXlate(XlateObj
);
216 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
218 if (UsesSource
&& hDCSrc
!= hDCDest
)
222 DC_UnlockDc(hDCDest
);
227 HBITMAP STDCALL
NtGdiCreateBitmap(INT Width
,
236 Planes
= (BYTE
) Planes
;
237 BitsPerPel
= (BYTE
) BitsPerPel
;
239 /* Check parameters */
240 if (!Height
|| !Width
)
258 /* Create the BITMAPOBJ */
259 hBitmap
= BITMAPOBJ_AllocBitmap ();
262 DPRINT("NtGdiCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n");
266 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
268 DPRINT("NtGdiCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width
, Height
,
269 1 << (Planes
* BitsPerPel
), BitsPerPel
, bmp
);
271 bmp
->size
.cx
= Width
;
272 bmp
->size
.cy
= Height
;
273 bmp
->bitmap
.bmType
= 0;
274 bmp
->bitmap
.bmWidth
= Width
;
275 bmp
->bitmap
.bmHeight
= Height
;
276 bmp
->bitmap
.bmPlanes
= Planes
;
277 bmp
->bitmap
.bmBitsPixel
= BitsPerPel
;
278 bmp
->bitmap
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes (Width
, BitsPerPel
);
279 bmp
->bitmap
.bmBits
= NULL
;
280 bmp
->DDBitmap
= NULL
;
283 // Allocate memory for bitmap bits
284 bmp
->bitmap
.bmBits
= ExAllocatePool(PagedPool
, bmp
->bitmap
.bmWidthBytes
* bmp
->bitmap
.bmHeight
);
286 BITMAPOBJ_UnlockBitmap( hBitmap
);
288 if (Bits
) /* Set bitmap bits */
290 NtGdiSetBitmapBits(hBitmap
, Height
* bmp
->bitmap
.bmWidthBytes
, Bits
);
296 BOOL FASTCALL
Bitmap_InternalDelete( PBITMAPOBJ pBmp
)
300 if (NULL
!= pBmp
->bitmap
.bmBits
)
302 if (NULL
!= pBmp
->dib
)
304 if (NULL
== pBmp
->dib
->dshSection
)
306 EngFreeUserMem(pBmp
->bitmap
.bmBits
);
310 /* This is a file-mapped section */
316 ExFreePool(pBmp
->bitmap
.bmBits
);
324 HBITMAP STDCALL
NtGdiCreateCompatibleBitmap(HDC hDC
,
334 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, dc
->w
.bitsPerPixel
);
340 if ((Width
>= 0x10000) || (Height
>= 0x10000))
342 DPRINT("got bad width %d or height %d, please look for reason\n", Width
, Height
);
346 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
347 if (!Width
|| !Height
)
349 hbmpRet
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
353 hbmpRet
= NtGdiCreateBitmap(Width
, Height
, 1, dc
->w
.bitsPerPixel
, NULL
);
356 DPRINT ("\t\t%04x\n", hbmpRet
);
361 HBITMAP STDCALL
NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
363 return NtGdiCreateBitmap (BM
->bmWidth
,
370 HBITMAP STDCALL
NtGdiCreateDiscardableBitmap(HDC hDC
,
374 /* FIXME: this probably should do something else */
375 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
378 BOOL STDCALL
NtGdiExtFloodFill(HDC hDC
,
387 BOOL STDCALL
NtGdiFloodFill(HDC hDC
,
395 BOOL STDCALL
NtGdiGetBitmapDimensionEx(HBITMAP hBitmap
,
400 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
406 *Dimension
= bmp
->size
;
408 BITMAPOBJ_UnlockBitmap(hBitmap
);
413 COLORREF STDCALL
NtGdiGetPixel(HDC hDC
,
418 COLORREF cr
= (COLORREF
) 0;
420 dc
= DC_LockDc (hDC
);
423 return (COLORREF
) CLR_INVALID
;
425 //FIXME: get actual pixel RGB value
430 BOOL STDCALL
NtGdiMaskBlt(HDC hDCDest
,
446 BOOL STDCALL
NtGdiPlgBlt(HDC hDCDest
,
460 LONG STDCALL
NtGdiSetBitmapBits(HBITMAP hBitmap
,
467 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
468 if (bmp
== NULL
|| Bits
== NULL
)
475 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
479 /* Only get entire lines */
480 height
= Bytes
/ bmp
->bitmap
.bmWidthBytes
;
481 if (height
> bmp
->bitmap
.bmHeight
)
483 height
= bmp
->bitmap
.bmHeight
;
485 Bytes
= height
* bmp
->bitmap
.bmWidthBytes
;
486 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
491 bmp
->bitmap
.bmHeight
,
492 1 << bmp
->bitmap
.bmBitsPixel
,
496 /* FIXME: call DDI specific function here if available */
499 DPRINT ("Calling device specific BitmapBits\n");
500 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
502 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
506 DPRINT ("BitmapBits == NULL??\n");
513 /* FIXME: Alloc enough for entire bitmap */
514 if (bmp
->bitmap
.bmBits
== NULL
)
516 bmp
->bitmap
.bmBits
= ExAllocatePool (PagedPool
, Bytes
);
518 if(!bmp
->bitmap
.bmBits
)
520 DPRINT ("Unable to allocate bit buffer\n");
525 memcpy(bmp
->bitmap
.bmBits
, Bits
, Bytes
);
530 BITMAPOBJ_UnlockBitmap(hBitmap
);
535 BOOL STDCALL
NtGdiSetBitmapDimensionEx(HBITMAP hBitmap
,
542 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
552 bmp
->size
.cx
= Width
;
553 bmp
->size
.cy
= Height
;
555 BITMAPOBJ_UnlockBitmap (hBitmap
);
560 COLORREF STDCALL
NtGdiSetPixel(HDC hDC
,
565 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
566 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
570 return ((COLORREF
) -1);
573 BOOL STDCALL
NtGdiSetPixelV(HDC hDC
,
578 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
581 if (NewBrush
== NULL
)
583 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
584 if (OldBrush
== NULL
)
586 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
587 NtGdiSelectObject(hDC
, OldBrush
);
588 NtGdiDeleteObject(NewBrush
);
592 BOOL STDCALL
NtGdiStretchBlt(HDC hDCDest
,
607 /* Internal Functions */
610 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
616 return 2 * ((bmWidth
+15) >> 4);
619 bmWidth
*= 3; /* fall through */
621 return bmWidth
+ (bmWidth
& 1);
631 return 2 * ((bmWidth
+3) >> 2);
640 return ((bmWidth
* bpp
+ 31) & ~31) >> 3;
643 HBITMAP FASTCALL
BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
649 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
658 BITMAPOBJ_UnlockBitmap(hBitmap
);
659 res
= NtGdiCreateBitmapIndirect(&bm
);
664 buf
= ExAllocatePool (NonPagedPool
, bm
.bmWidthBytes
* bm
.bmHeight
);
665 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
666 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
673 INT STDCALL
BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
677 if(count
< (INT
) sizeof(DIBSECTION
))
679 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
683 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
685 memcpy(buffer
, bmp
->dib
, count
);
690 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
691 memcpy(buffer
, &bmp
->bitmap
, count
);