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.63 2004/03/16 02:15:06 royce 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/region.h>
28 //#include <win32k/debug.h>
29 #include "../eng/handle.h"
30 #include <include/inteng.h>
31 #include <include/eng.h>
32 #include <include/error.h>
33 #include <include/surface.h>
34 #include <include/palette.h>
35 #include <include/tags.h>
36 #include <rosrtl/gdimacro.h>
39 #include <win32k/debug1.h>
41 BOOL STDCALL
NtGdiBitBlt(HDC hDCDest
,
53 PSURFOBJ SurfDest
, SurfSrc
;
54 PSURFGDI SurfGDIDest
, SurfGDISrc
;
58 PPALGDI PalDestGDI
, PalSourceGDI
;
59 PXLATEOBJ XlateObj
= NULL
;
60 HPALETTE SourcePalette
, DestPalette
;
61 ULONG SourceMode
, DestMode
;
63 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
64 BOOL UsesPattern
= TRUE
;//((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
67 DCDest
= DC_LockDc(hDCDest
);
70 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
71 SetLastWin32Error(ERROR_INVALID_HANDLE
);
77 if (hDCSrc
!= hDCDest
)
79 DCSrc
= DC_LockDc(hDCSrc
);
83 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
84 SetLastWin32Error(ERROR_INVALID_HANDLE
);
98 /* Offset the destination and source by the origin of their DCs. */
99 XDest
+= DCDest
->w
.DCOrgX
;
100 YDest
+= DCDest
->w
.DCOrgY
;
103 XSrc
+= DCSrc
->w
.DCOrgX
;
104 YSrc
+= DCSrc
->w
.DCOrgY
;
107 DestRect
.left
= XDest
;
108 DestRect
.top
= YDest
;
109 DestRect
.right
= XDest
+Width
;
110 DestRect
.bottom
= YDest
+Height
;
112 SourcePoint
.x
= XSrc
;
113 SourcePoint
.y
= YSrc
;
115 /* Determine surfaces to be used in the bitblt */
116 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
117 SurfGDIDest
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfDest
);
120 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
121 SurfGDISrc
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfSrc
);
131 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
132 if (NULL
== BrushObj
)
134 if (UsesSource
&& hDCSrc
!= hDCDest
)
138 DC_UnlockDc(hDCDest
);
139 SetLastWin32Error(ERROR_INVALID_HANDLE
);
148 if (DCDest
->w
.hPalette
!= 0)
150 DestPalette
= DCDest
->w
.hPalette
;
154 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
157 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
159 SourcePalette
= DCSrc
->w
.hPalette
;
163 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
166 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
167 if (NULL
== PalSourceGDI
)
169 if (UsesSource
&& hDCSrc
!= hDCDest
)
173 DC_UnlockDc(hDCDest
);
174 SetLastWin32Error(ERROR_INVALID_HANDLE
);
177 SourceMode
= PalSourceGDI
->Mode
;
178 PALETTE_UnlockPalette(SourcePalette
);
180 if (DestPalette
== SourcePalette
)
182 DestMode
= SourceMode
;
186 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
187 if (NULL
== PalDestGDI
)
189 if (UsesSource
&& hDCSrc
!= hDCDest
)
193 DC_UnlockDc(hDCDest
);
194 SetLastWin32Error(ERROR_INVALID_HANDLE
);
197 DestMode
= PalDestGDI
->Mode
;
198 PALETTE_UnlockPalette(DestPalette
);
201 /* KB41464 details how to convert between mono and color */
202 if (DCDest
->w
.bitsPerPixel
== 1)
204 XlateObj
= (PXLATEOBJ
)IntEngCreateMonoXlate(SourceMode
, DestPalette
,
205 SourcePalette
, DCSrc
->w
.backgroundColor
);
207 else if (UsesSource
&& 1 == DCSrc
->w
.bitsPerPixel
)
211 Colors
[0] = DCSrc
->w
.textColor
;
212 Colors
[1] = DCSrc
->w
.backgroundColor
;
213 Mono
= EngCreatePalette(PAL_INDEXED
, 2, Colors
, 0, 0, 0);
216 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, PAL_INDEXED
, DestPalette
, Mono
);
225 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
227 if (NULL
== XlateObj
)
231 EngDeletePalette(Mono
);
233 if (UsesSource
&& hDCSrc
!= hDCDest
)
237 DC_UnlockDc(hDCDest
);
238 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
242 /* Perform the bitblt operation */
243 Status
= IntEngBitBlt(SurfDest
, SurfSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
244 &DestRect
, &SourcePoint
, NULL
, BrushObj
, NULL
, ROP
);
246 EngDeleteXlate(XlateObj
);
249 EngDeletePalette(Mono
);
253 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
255 if (UsesSource
&& hDCSrc
!= hDCDest
)
259 DC_UnlockDc(hDCDest
);
264 HBITMAP STDCALL
NtGdiCreateBitmap(INT Width
,
273 Planes
= (BYTE
) Planes
;
274 BitsPerPel
= (BYTE
) BitsPerPel
;
276 /* Check parameters */
277 if (!Height
|| !Width
)
284 DPRINT("NtGdiCreateBitmap - UNIMPLEMENTED\n");
296 /* Create the BITMAPOBJ */
297 hBitmap
= BITMAPOBJ_AllocBitmap ();
300 DPRINT("NtGdiCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n");
304 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
306 DPRINT("NtGdiCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width
, Height
,
307 1 << (Planes
* BitsPerPel
), BitsPerPel
, bmp
);
309 bmp
->dimension
.cx
= 0;
310 bmp
->dimension
.cy
= 0;
311 bmp
->bitmap
.bmType
= 0;
312 bmp
->bitmap
.bmWidth
= Width
;
313 bmp
->bitmap
.bmHeight
= Height
;
314 bmp
->bitmap
.bmPlanes
= Planes
;
315 bmp
->bitmap
.bmBitsPixel
= BitsPerPel
;
316 bmp
->bitmap
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes (Width
, BitsPerPel
);
317 bmp
->bitmap
.bmBits
= NULL
;
318 bmp
->DDBitmap
= NULL
;
321 // Allocate memory for bitmap bits
322 bmp
->bitmap
.bmBits
= ExAllocatePoolWithTag(PagedPool
, bmp
->bitmap
.bmWidthBytes
* bmp
->bitmap
.bmHeight
, TAG_BITMAP
);
324 BITMAPOBJ_UnlockBitmap( hBitmap
);
326 if (Bits
) /* Set bitmap bits */
328 NtGdiSetBitmapBits(hBitmap
, Height
* bmp
->bitmap
.bmWidthBytes
, Bits
);
332 // Initialize the bitmap (fixes bug 244?)
333 RtlZeroMemory(bmp
->bitmap
.bmBits
, Height
* bmp
->bitmap
.bmWidthBytes
);
339 BOOL FASTCALL
Bitmap_InternalDelete( PBITMAPOBJ pBmp
)
343 if (NULL
!= pBmp
->bitmap
.bmBits
)
345 if (NULL
!= pBmp
->dib
)
347 if (NULL
== pBmp
->dib
->dshSection
)
349 EngFreeUserMem(pBmp
->bitmap
.bmBits
);
353 /* This is a file-mapped section */
359 ExFreePool(pBmp
->bitmap
.bmBits
);
368 IntCreateCompatibleBitmap(PDC Dc
,
376 if ((Width
>= 0x10000) || (Height
>= 0x10000))
378 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
382 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
383 if (0 == Width
|| 0 == Height
)
385 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
389 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
396 NtGdiCreateCompatibleBitmap(HDC hDC
,
405 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, dc
->w
.bitsPerPixel
);
412 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
414 DPRINT ("\t\t%04x\n", Bmp
);
419 HBITMAP STDCALL
NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
421 return NtGdiCreateBitmap (BM
->bmWidth
,
428 HBITMAP STDCALL
NtGdiCreateDiscardableBitmap(HDC hDC
,
432 /* FIXME: this probably should do something else */
433 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
436 BOOL STDCALL
NtGdiExtFloodFill(HDC hDC
,
445 BOOL STDCALL
NtGdiFloodFill(HDC hDC
,
450 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
453 BOOL STDCALL
NtGdiGetBitmapDimensionEx(HBITMAP hBitmap
,
458 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
464 *Dimension
= bmp
->dimension
;
466 BITMAPOBJ_UnlockBitmap(hBitmap
);
473 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
476 COLORREF clrSource
, Result
= (COLORREF
)CLR_INVALID
; // default to failure
478 PSURFOBJ SurfaceObject
;
484 dc
= DC_LockDc (hDC
);
487 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
489 SurfaceObject
= (PSURFOBJ
)AccessUserObject((ULONG
)dc
->Surface
);
490 ASSERT(SurfaceObject
);
491 Surface
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfaceObject
);
492 if ( Surface
&& Surface
->DIB_GetPixel
)
494 clrSource
= Surface
->DIB_GetPixel(SurfaceObject
, XPos
, YPos
);
495 if (dc
->w
.hPalette
!= 0)
496 Pal
= dc
->w
.hPalette
;
498 Pal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
499 PalGDI
= PALETTE_LockPalette(Pal
);
502 PalMode
= PalGDI
->Mode
;
503 PALETTE_UnlockPalette(Pal
);
505 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate ( PAL_RGB
, PalMode
, NULL
, Pal
);
508 Result
= XLATEOBJ_iXlate(XlateObj
, clrSource
);
509 EngDeleteXlate(XlateObj
);
520 /***********************************************************************
522 * Ported from WINE by sedwards 11-4-03
524 * Someone thought it would be faster to do it here and then switch back
525 * to GDI32. I dunno. Write a test and let me know.
528 static inline BYTE
SwapROP3_SrcDst(BYTE bRop3
)
530 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
533 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
534 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
535 #define DSTCOPY 0x00AA0029
536 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
538 BOOL STDCALL
NtGdiMaskBlt(HDC hdcDest
, INT nXDest
, INT nYDest
,
539 INT nWidth
, INT nHeight
, HDC hdcSrc
,
540 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
541 INT xMask
, INT yMask
, DWORD dwRop
)
543 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
544 HDC hDCMask
, hDC1
, hDC2
;
545 static const DWORD ROP3Table
[256] =
547 0x00000042, 0x00010289,
548 0x00020C89, 0x000300AA,
549 0x00040C88, 0x000500A9,
550 0x00060865, 0x000702C5,
551 0x00080F08, 0x00090245,
552 0x000A0329, 0x000B0B2A,
553 0x000C0324, 0x000D0B25,
554 0x000E08A5, 0x000F0001,
555 0x00100C85, 0x001100A6,
556 0x00120868, 0x001302C8,
557 0x00140869, 0x001502C9,
558 0x00165CCA, 0x00171D54,
559 0x00180D59, 0x00191CC8,
560 0x001A06C5, 0x001B0768,
561 0x001C06CA, 0x001D0766,
562 0x001E01A5, 0x001F0385,
563 0x00200F09, 0x00210248,
564 0x00220326, 0x00230B24,
565 0x00240D55, 0x00251CC5,
566 0x002606C8, 0x00271868,
567 0x00280369, 0x002916CA,
568 0x002A0CC9, 0x002B1D58,
569 0x002C0784, 0x002D060A,
570 0x002E064A, 0x002F0E2A,
571 0x0030032A, 0x00310B28,
572 0x00320688, 0x00330008,
573 0x003406C4, 0x00351864,
574 0x003601A8, 0x00370388,
575 0x0038078A, 0x00390604,
576 0x003A0644, 0x003B0E24,
577 0x003C004A, 0x003D18A4,
578 0x003E1B24, 0x003F00EA,
579 0x00400F0A, 0x00410249,
580 0x00420D5D, 0x00431CC4,
581 0x00440328, 0x00450B29,
582 0x004606C6, 0x0047076A,
583 0x00480368, 0x004916C5,
584 0x004A0789, 0x004B0605,
585 0x004C0CC8, 0x004D1954,
586 0x004E0645, 0x004F0E25,
587 0x00500325, 0x00510B26,
588 0x005206C9, 0x00530764,
589 0x005408A9, 0x00550009,
590 0x005601A9, 0x00570389,
591 0x00580785, 0x00590609,
592 0x005A0049, 0x005B18A9,
593 0x005C0649, 0x005D0E29,
594 0x005E1B29, 0x005F00E9,
595 0x00600365, 0x006116C6,
596 0x00620786, 0x00630608,
597 0x00640788, 0x00650606,
598 0x00660046, 0x006718A8,
599 0x006858A6, 0x00690145,
600 0x006A01E9, 0x006B178A,
601 0x006C01E8, 0x006D1785,
602 0x006E1E28, 0x006F0C65,
603 0x00700CC5, 0x00711D5C,
604 0x00720648, 0x00730E28,
605 0x00740646, 0x00750E26,
606 0x00761B28, 0x007700E6,
607 0x007801E5, 0x00791786,
608 0x007A1E29, 0x007B0C68,
609 0x007C1E24, 0x007D0C69,
610 0x007E0955, 0x007F03C9,
611 0x008003E9, 0x00810975,
612 0x00820C49, 0x00831E04,
613 0x00840C48, 0x00851E05,
614 0x008617A6, 0x008701C5,
615 0x008800C6, 0x00891B08,
616 0x008A0E06, 0x008B0666,
617 0x008C0E08, 0x008D0668,
618 0x008E1D7C, 0x008F0CE5,
619 0x00900C45, 0x00911E08,
620 0x009217A9, 0x009301C4,
621 0x009417AA, 0x009501C9,
622 0x00960169, 0x0097588A,
623 0x00981888, 0x00990066,
624 0x009A0709, 0x009B07A8,
625 0x009C0704, 0x009D07A6,
626 0x009E16E6, 0x009F0345,
627 0x00A000C9, 0x00A11B05,
628 0x00A20E09, 0x00A30669,
629 0x00A41885, 0x00A50065,
630 0x00A60706, 0x00A707A5,
631 0x00A803A9, 0x00A90189,
632 0x00AA0029, 0x00AB0889,
633 0x00AC0744, 0x00AD06E9,
634 0x00AE0B06, 0x00AF0229,
635 0x00B00E05, 0x00B10665,
636 0x00B21974, 0x00B30CE8,
637 0x00B4070A, 0x00B507A9,
638 0x00B616E9, 0x00B70348,
639 0x00B8074A, 0x00B906E6,
640 0x00BA0B09, 0x00BB0226,
641 0x00BC1CE4, 0x00BD0D7D,
642 0x00BE0269, 0x00BF08C9,
643 0x00C000CA, 0x00C11B04,
644 0x00C21884, 0x00C3006A,
645 0x00C40E04, 0x00C50664,
646 0x00C60708, 0x00C707AA,
647 0x00C803A8, 0x00C90184,
648 0x00CA0749, 0x00CB06E4,
649 0x00CC0020, 0x00CD0888,
650 0x00CE0B08, 0x00CF0224,
651 0x00D00E0A, 0x00D1066A,
652 0x00D20705, 0x00D307A4,
653 0x00D41D78, 0x00D50CE9,
654 0x00D616EA, 0x00D70349,
655 0x00D80745, 0x00D906E8,
656 0x00DA1CE9, 0x00DB0D75,
657 0x00DC0B04, 0x00DD0228,
658 0x00DE0268, 0x00DF08C8,
659 0x00E003A5, 0x00E10185,
660 0x00E20746, 0x00E306EA,
661 0x00E40748, 0x00E506E5,
662 0x00E61CE8, 0x00E70D79,
663 0x00E81D74, 0x00E95CE6,
664 0x00EA02E9, 0x00EB0849,
665 0x00EC02E8, 0x00ED0848,
666 0x00EE0086, 0x00EF0A08,
667 0x00F00021, 0x00F10885,
668 0x00F20B05, 0x00F3022A,
669 0x00F40B0A, 0x00F50225,
670 0x00F60265, 0x00F708C5,
671 0x00F802E5, 0x00F90845,
672 0x00FA0089, 0x00FB0A09,
673 0x00FC008A, 0x00FD0A0A,
674 0x00FE02A9, 0x00FF0062,
678 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
680 /* 1. make mask bitmap's dc */
681 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
682 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
684 /* 2. make masked Background bitmap */
686 /* 2.1 make bitmap */
687 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
688 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
689 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
691 /* 2.2 draw dest bitmap and mask */
692 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
693 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
694 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
696 /* 3. make masked Foreground bitmap */
698 /* 3.1 make bitmap */
699 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
700 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
701 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
703 /* 3.2 draw src bitmap and mask */
704 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
705 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
706 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
708 /* 4. combine two bitmap and copy it to hdcDest */
709 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
710 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
712 /* 5. restore all object */
713 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
714 NtGdiSelectObject(hDC1
, hOldBitmap2
);
715 NtGdiSelectObject(hDC2
, hOldBitmap3
);
717 /* 6. delete all temp object */
718 NtGdiDeleteObject(hBitmap2
);
719 NtGdiDeleteObject(hBitmap3
);
723 NtGdiDeleteDC(hDCMask
);
728 BOOL STDCALL
NtGdiPlgBlt(HDC hDCDest
,
742 LONG STDCALL
NtGdiSetBitmapBits(HBITMAP hBitmap
,
749 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
750 if (bmp
== NULL
|| Bits
== NULL
)
757 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
761 /* Only get entire lines */
762 height
= Bytes
/ bmp
->bitmap
.bmWidthBytes
;
763 if (height
> bmp
->bitmap
.bmHeight
)
765 height
= bmp
->bitmap
.bmHeight
;
767 Bytes
= height
* bmp
->bitmap
.bmWidthBytes
;
768 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
773 bmp
->bitmap
.bmHeight
,
774 1 << bmp
->bitmap
.bmBitsPixel
,
778 /* FIXME: call DDI specific function here if available */
781 DPRINT ("Calling device specific BitmapBits\n");
782 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
784 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
788 DPRINT ("BitmapBits == NULL??\n");
795 /* FIXME: Alloc enough for entire bitmap */
796 if (bmp
->bitmap
.bmBits
== NULL
)
798 bmp
->bitmap
.bmBits
= ExAllocatePoolWithTag(PagedPool
, Bytes
, TAG_BITMAP
);
800 if(!bmp
->bitmap
.bmBits
)
802 DPRINT ("Unable to allocate bit buffer\n");
807 memcpy(bmp
->bitmap
.bmBits
, Bits
, Bytes
);
812 BITMAPOBJ_UnlockBitmap(hBitmap
);
817 BOOL STDCALL
NtGdiSetBitmapDimensionEx(HBITMAP hBitmap
,
824 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
832 *Size
= bmp
->dimension
;
834 bmp
->dimension
.cx
= Width
;
835 bmp
->dimension
.cy
= Height
;
837 BITMAPOBJ_UnlockBitmap (hBitmap
);
842 COLORREF STDCALL
NtGdiSetPixel(HDC hDC
,
847 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
848 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
852 return ((COLORREF
) -1);
855 BOOL STDCALL
NtGdiSetPixelV(HDC hDC
,
860 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
863 if (NewBrush
== NULL
)
865 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
866 if (OldBrush
== NULL
)
868 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
869 NtGdiSelectObject(hDC
, OldBrush
);
870 NtGdiDeleteObject(NewBrush
);
874 BOOL STDCALL
NtGdiStretchBlt(HDC hDCDest
,
888 PSURFOBJ SurfDest
, SurfSrc
;
889 PSURFGDI SurfGDIDest
, SurfGDISrc
;
893 PPALGDI PalDestGDI
, PalSourceGDI
;
894 PXLATEOBJ XlateObj
= NULL
;
895 HPALETTE SourcePalette
, DestPalette
;
896 ULONG SourceMode
, DestMode
;
898 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
899 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
901 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
903 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
906 DCDest
= DC_LockDc(hDCDest
);
909 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
910 SetLastWin32Error(ERROR_INVALID_HANDLE
);
916 if (hDCSrc
!= hDCDest
)
918 DCSrc
= DC_LockDc(hDCSrc
);
921 DC_UnlockDc(hDCDest
);
922 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
923 SetLastWin32Error(ERROR_INVALID_HANDLE
);
937 /* Offset the destination and source by the origin of their DCs. */
938 XOriginDest
+= DCDest
->w
.DCOrgX
;
939 YOriginDest
+= DCDest
->w
.DCOrgY
;
942 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
943 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
946 DestRect
.left
= XOriginDest
;
947 DestRect
.top
= YOriginDest
;
948 DestRect
.right
= XOriginDest
+WidthDest
;
949 DestRect
.bottom
= YOriginDest
+HeightDest
;
951 SourceRect
.left
= XOriginSrc
;
952 SourceRect
.top
= YOriginSrc
;
953 SourceRect
.right
= XOriginSrc
+WidthSrc
;
954 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
956 /* Determine surfaces to be used in the bitblt */
957 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
958 SurfGDIDest
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfDest
);
961 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
962 SurfGDISrc
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfSrc
);
972 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
973 if (NULL
== BrushObj
)
975 if (UsesSource
&& hDCSrc
!= hDCDest
)
979 DC_UnlockDc(hDCDest
);
980 SetLastWin32Error(ERROR_INVALID_HANDLE
);
989 if (DCDest
->w
.hPalette
!= 0)
991 DestPalette
= DCDest
->w
.hPalette
;
995 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
998 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
1000 SourcePalette
= DCSrc
->w
.hPalette
;
1004 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
1007 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
1008 if (NULL
== PalSourceGDI
)
1010 if (UsesSource
&& hDCSrc
!= hDCDest
)
1012 DC_UnlockDc(hDCSrc
);
1014 DC_UnlockDc(hDCDest
);
1015 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1018 SourceMode
= PalSourceGDI
->Mode
;
1019 PALETTE_UnlockPalette(SourcePalette
);
1021 if (DestPalette
== SourcePalette
)
1023 DestMode
= SourceMode
;
1027 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
1028 if (NULL
== PalDestGDI
)
1030 if (UsesSource
&& hDCSrc
!= hDCDest
)
1032 DC_UnlockDc(hDCSrc
);
1034 DC_UnlockDc(hDCDest
);
1035 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1038 DestMode
= PalDestGDI
->Mode
;
1039 PALETTE_UnlockPalette(DestPalette
);
1042 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
1043 if (NULL
== XlateObj
)
1045 if (UsesSource
&& hDCSrc
!= hDCDest
)
1047 DC_UnlockDc(hDCSrc
);
1049 DC_UnlockDc(hDCDest
);
1050 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1054 /* Perform the bitblt operation */
1055 Status
= IntEngStretchBlt(SurfDest
, SurfSrc
, NULL
, DCDest
->CombinedClip
,
1056 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1058 EngDeleteXlate(XlateObj
);
1061 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1063 if (UsesSource
&& hDCSrc
!= hDCDest
)
1065 DC_UnlockDc(hDCSrc
);
1067 DC_UnlockDc(hDCDest
);
1072 /* Internal Functions */
1075 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1081 return 2 * ((bmWidth
+15) >> 4);
1084 bmWidth
*= 3; /* fall through */
1086 return bmWidth
+ (bmWidth
& 1);
1096 return 2 * ((bmWidth
+3) >> 2);
1105 return ((bmWidth
* bpp
+ 31) & ~31) >> 3;
1108 HBITMAP FASTCALL
BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1114 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1123 BITMAPOBJ_UnlockBitmap(hBitmap
);
1124 res
= NtGdiCreateBitmapIndirect(&bm
);
1129 buf
= ExAllocatePoolWithTag (NonPagedPool
, bm
.bmWidthBytes
* bm
.bmHeight
, TAG_BITMAP
);
1130 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1131 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1138 INT STDCALL
BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1142 if(count
< (INT
) sizeof(DIBSECTION
))
1144 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1148 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1150 memcpy(buffer
, bmp
->dib
, count
);
1155 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1156 memcpy(buffer
, &bmp
->bitmap
, count
);